Is it necessary to use GROUP BY in Oracle? - oracle

Is it necessary to use GROUP BY while you use an aggregate function with column in Oracle?
In MySQL, if I don't use it's working fine, but in Oracle, it gives me an error.

It's necessary if you select at least one column without an aggregate function.
So, this will work:
select sum(col_1), avg(col_2) from table_1;
while this wont:
select sum(col_1), avg(col_2), col_3 from table_1;

You should always use GROUP BY when using aggregate functions. Not using GROUP BY is a non-standard SQL extension allowed by MySQL.
RANT
IMHO, this extension is brain-dead, outright dangerous and should never be used at all because MySQL returns values for a random row for the non-aggregated columns.
END_OF_RANT

Related

How to create Interactive/Classic Report with dynamic SQL?

I'm running Apex 19.2 and I would like to create a classical or interactive report based on dynamic query.
The query I'm using is not known at design time. It depends on an page item value.
-- So I have a function that generates the SQL as follows
GetSQLQuery(:P1_MyItem);
This function may return something like
select Field1 from Table1
or
Select field1,field2 from Table1 inner join Table2 on ...
So it's not a sql query always with the same number of columns. It's completely variable.
I tried using PL/SQL function Body returning SQL Query but it seems like Apex needs to parse the query at design time.
Has anyone an idea how to solve that please ?
Cheers,
Thanks.
Enable the Use Generic Column Names option, as Koen said.
Then set Generic Column Count to the upper bound of the number of columns the query might return.
If you need dynamic column headers too, go to the region attributes and set Type (under Heading) to the appropriate value. PL/SQL Function Body is the most flexible and powerful option, but it's also the most work. Just make sure you return the correct number of headings as per the query.

Compound select query in Oracle Database

I have a table, mealdb, which has three fields viz. "userid", "timeofday", "daydate"(all varchar2). timeofday can have two values, "noon" or "afternoon". Now I want to calculate the total number of afternoons against a given userid. I tried like
select sum(timeofday)
from mealdb
where timeofday='afternoon' where userid='1200';
But it is giving an error in Oracle 10g.
How do I fix this problem?
Only one WHERE keyword is allowed.
Further conditions are added using boolean operators like AND, OR
select count(*)
from mealdb
where timeofday='afternoon'
and userid='1200';
select count(1)
from mealdb
where timeofday='afternoon' and userid='1200';
Try select count(timeofday) from mealdb where timeofday='afternoon' and userid='1200' You need to use Count not Sum and use and where your second where is.

Stored Procedure: Cursor is bad?

I read somewhere that 99% of time you don't need to use a cursor.
But I can't think of any other way beside using a cursor in this following situation.
Select t.flag
From Dual t;
Let's say this return 4 rows of either 'Y' or 'N'. I want the procedure to trigger something if it finds 'Y'. I usually declare a cursor and loop until %NOTFOUND. Please tell me if there is a better way.
Also, if you have any idea, when is the best time to use a cursor?
EDIT: Instead of inserting the flags, what if I want to do "If 'Y' then trigger something"?
Your case definitely falls into the 99%.
You can easily do the conditional insert using insert into ... select.... It's just a matter or making a select that returns the result that you want to insert.
If you want to insert one record for each 'Y' then use a query with where flag = 'Y'. If you only want to insert a single record depending on whether there are at least one 'Y', then you can add distinct to the query.
A cursor is useful when you make something more complicated. I for example use a cursor when need to insert or update records in one table, and also for each record insert or update one or more records into several other tables.
Something like this:
INSERT INTO TBL_FLAG (col)
SELECT ID FROM Dual where flag = 'Y'
You will usually see a performance gain when using set based instead of procedural operations because most modern DBMS are setup to perform set based operations. You can read more here.
well the example doesnt quite make sense..
but you can always write an insert as select statement instead of what i think you are describing
Cursors are best to use when an column value form one table will be used repeatedly in multiple queries on different tables.
Suppose the values of id_test column are fetched from MY_TEST_TBL using a cursor CUR_TEST. Now this id_test column is a foreign key in MY_TEST_TBL. If we want to use id_test to insert or update any rows in table A_TBL,B_TBL and C_TBL, then in this case it's best to use cursors instead of using complex queries.
Hope this might help to understand the purpose of cursors

oracle default value for a column

You know how we could use:
dateStamp DATE DEFAULT sysdate
to assign a default value to a column in table_x. What if I want to assign a default function? Can I do that?
The function will have some values from "table_params" to run some formula including a column named : "base" in table_x.
I could possibly write a cursor to loop through and run an update statement, but I was just curious if this is possible.
thanks in advance.
From Oracle documentation:
Restriction on Default Column Values
A DEFAULT expression cannot contain references to PL/SQL functions or to other columns, the
pseudocolumns CURRVAL, NEXTVAL, LEVEL, PRIOR, and ROWNUM, or date
constants that are not fully specified.
Either use a trigger (as was already mentioned) or run an UPDATE statement after your INSERT statement(s) (shouldn't be a problem if you keep your DML in PL/SQL).
You can write an INSERT trigger for the table that calls the function you want.

Good way to deal with comma separated values in oracle

I am getting passed comma separated values to a stored procedure in oracle. I want to treat these values as a table so that I can use them in a query like:
select * from tabl_a where column_b in (<csv values passed in>)
What is the best way to do this in 11g?
Right now we are looping through these one by one and inserting them into a gtt which I think is inefficient.
Any pointers?
This solves exactly same problem
Ask Tom
Oracle does not come with a built-in tokenizer. But it is possible to roll our own, using SQL Types and PL/SQL. I have posted a sample solution in this other SO thread.
That would enable a solution like this:
select * from tabl_a
where column_b in ( select *
from table (str_to_number_tokens (<csv values passed in>)))
/
In 11g you can use the "occurrence" parameter of REGEXP_SUBSTR to select the values directly in SQL:
select regexp_substr(<csv values passed in>,'[^,]+',1,level) val
from dual
connect by level < regexp_count(<csv values passed in>,',')+2;
But since regexp_substr is somewhat expensive I am not sure if it is the most effective in terms of being the fastest.

Resources