Proc or function returning n rows
Returning multi-rows with informix or sysbase procedures is very simple
for example it's possible to declare in esql/c sybase a cursor for execute procedure and retrieve all tutles in a cursor in the esql/c code.
This procedure is also usable in sql with execute blablabla and the result is like a simple select.
Oracle proc or function simes to be more complicated!
Is someone got a part of pro*C code and stored proc or function code about multirows retrieval? Is this function or proc usable in VB for example?
If you are certain to get a small number of rows (10, 20, ..., 100), than PL table is the best choice.
But for a large number of rows, cursor is the best choice, having in view that a PL table will have to be entirely stored in the server memory (and this requires some SGA space), while cursors allow fetching a number of rows, processing the fetched rows, again fetch a number of rows and so on ...
Forms with data-blocks based on functions that return ref cursor allow fetching rows in bulks of 10-20...100 at a time.
null
Similar Messages
-
Need a function that return multiple rows
Hi,
I need a function that should return output of this query
SELECT b.branding_code, c.name_desc
FROM
development.brandings b, godot.company c
WHERE b.company_id = c.company_id;
This above function return 30 rows and I am not giving any input
Function using cursor,pipeline
Please help
Edited by: 1008783 on Jun 6, 2013 6:40 AMHi,
1008783 wrote:
Hi
Table A:
Development schema
branding_code,company_id
Table B:
Gogot schema
name_desc,...Those aren't CREATE TABLE and INSERT statements. Post something that the people who want to help you can run on their own systems to re-create the problem and test their ideas.
o/p:
branding_code,name_desc
I should return these column as o/p, no i/pA query will do that. There's no need for a function.
There are good reasons for wanting a functin. If you have one, say what it is. Explain how you plan to use the function.
Have you tried writing a function? Post your code. What specific problems did you have? -
Oracle 11g Table function returns no records on first call
Hello,
On a Oracle 11g R2 I've a table function ( PIPELINED ) returning rows selected from a table.
The first time the function is selected, in a session ( I've tried to disconnect and log in again ), it returns no rows.
I've tried to log the call using DBMS_OUTPUT and from what I see the select on the table function returns no rows and no output is printed. So I presume Oracle is not calling the function.
The same function on a similar environment ( same db versions, patches and database structure ) works fine. The second environment is a production environment so it has more memory and some other settings enabled.
Does anyone know of settings that can relate to this behaviour ?
Thanks in advance for the help.
Regards,
Stefano MuretThank you for answering so fast.
Here's the function code:
FUNCTION template_parameters (iTemplate IN TEMPLATE_RAW_DATA.TMPL_ID%TYPE := NULL)
RETURN table_type_tmpl_parameters PIPELINED
IS
li_exception INTEGER DEFAULT -20025;
POUT_PARM TABLE_TYPE_TMPL_PARAMETERS;
lt_parms table_type_tmpl_parms_raw;
sParmCheck VARCHAR2(4000);
iOccurrence INTEGER;
BEGIN
pOut_Parm := table_type_tmpl_parameters();
pOut_Parm.EXTEND;
select
tmpl_id
*,tmpl_name*
*,replace(upper(trim(sql_out)),'[SCHEMA].')*
*,UPPER(TRIM(out_tmpl_parms))*
bulk collect into lt_parms
from ref_templates
where tmpl_id = NVL(iTemplate,tmpl_id)
order by tmpl_id;
FOR k IN 1..lt_parms.COUNT
LOOP
pOut_Parm(1).tmpl_id := lt_parms(k).tmpl_id;
pOut_Parm(1).tmpl_name := lt_parms(k).tmpl_name;
FOR i IN 1..2
LOOP
IF i = 1 THEN
sParmCheck := lt_parms(k).sql_out;
ELSE
sParmCheck := lt_parms(k).sql_parms;
END IF;
iOccurrence := 1;
*pOut_Parm(1).parameter_name := regexp_substr(sParmCheck,'\[[^\[]+\]',1,iOccurrence);*
WHILE pOut_Parm(1).parameter_name IS NOT NULL
LOOP
PIPE ROW (pOut_Parm(1));
iOccurrence := iOccurrence + 1;
*pOut_Parm(1).parameter_name := regexp_substr(sParmCheck,'\[[^\[]+\]',1,iOccurrence);*
END LOOP;
END LOOP;
END LOOP;
RETURN;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(li_exception,SUBSTR(SQLERRM,1,1000));
RETURN;
END template_parameters;
This function is part of a package.
The data on both environments is the same. -
How to create a function that returns multiple rows in table
Dear all,
I want to create a funtion that returns multiple rows from the table (ex: gl_balances). I done following:
-- Create type (successfull)
Create or replace type tp_gl_balance as Object
PERIOD_NAME VARCHAR2(15),
CURRENCY_CODE VARCHAR2(15),
PERIOD_TYPE VARCHAR2(15),
PERIOD_YEAR NUMBER(15),
BEGIN_BALANCE_DR NUMBER,
BEGIN_BALANCE_CR NUMBER
-- successfull
create type tp_tbl_gl_balance as table of tp_gl_balance;
but i create a function for return some rows from gl_balances, i can't compile it
create or replace function f_gl_balance(p_period varchar2) return tp_tbl_gl_balance pipelined
as
begin
return
(select gb.period_name, gb.currency_code, gb.period_type, gb.period_year, gb.begin_balance_dr, gb.begin_balance_cr
from gl_balances gb
where gb.period_name = p_period);
end;
I also try
create or replace function f_gl_balance(p_period varchar2) return tp_tbl_gl_balance pipelined
as
begin
select gb.period_name, gb.currency_code, gb.period_type, gb.period_year, gb.begin_balance_dr, gb.begin_balance_cr
from gl_balances gb
where gb.period_name = p_period;
return;
end;
Please help me solve this function.
thanks and best reguardhi,
Use TABLE FUNCTIONS,
[http://www.oracle-base.com/articles/9i/PipelinedTableFunctions9i.php]
Regards,
Danish -
SQL Query (PL/SQL Function Body returning SQL query) doesn't return any row
I have a region with the following type:
SQL Query (PL/SQL Function Body returning SQL query).
In a search screen the users can enter different numbers, separated by an ENTER.
I want to check these numbers by replacing the ENTER, which is CHR(13) || CHR(10) I believe, with commas. And then I can use it like this: POD IN (<<text>>).
It's something like this:
If (:P30_POD Is Not Null) Then
v_where := v_where || v_condition || 'POD IN (''''''''||REPLACE(''' || :P30_POD || ''', CHR(13) || CHR(10), '','')||'''''''''')';
v_condition := ' AND ';
End If;
But the query doesn't return any rows.
I tried to reproduce it in Toad:
select * from asx_worklistitem
where
POD IN (''''||REPLACE('541449200000171813'||CHR(13) || CHR(10)||'541449206006341366', CHR(13) || CHR(10), ''',''')||'''')
==> This is the query that does't return any rows
select (''''||REPLACE('541449200000171813'||CHR(13) || CHR(10)||'541449206006341366', CHR(13) || CHR(10), ''',''')||'''')
from dual;
==> This returns '541449200000171813','541449206006341366'
select * from asx_worklistitem
where pod in ('541449200000171813','541449206006341366');
==> and when I copy/paste this in the above query, it does return my rows.
So why does my first query doesn't work?
Doe anyone have any idea?
Kind regards,
Geert
Message was edited by:
ZorryThanks for the help.
I made it work, but via the following code:
If (:P30_POD Is Not Null) Then
v_pods := REPLACE(:P30_POD, CHR(13) || CHR(10));
v_where := v_where || v_condition || 'POD IN (';
v_counter := 1;
WHILE (v_counter < LENGTH(v_pods)) LOOP
v_pod := SUBSTR(v_pods, v_counter, 18);
IF (v_counter <> 1) THEN
v_where := v_where || ',';
END IF;
v_where := v_where || '''' || v_pod || '''';
v_counter := v_counter + 18;
END LOOP;
v_where := v_where || ')';
v_condition := ' AND ';
End If;But now I want to make an update of all the records that correspond to this search criteria. I can give in a status via a dropdownlist and that I want to update all the records that correspond to one of these POD's with that status.
For a region you can build an SQL query via PL/SQL, but for a process you only have a PL/SQL block. Is the only way to update all these records by making a loop and make an update for every POD that is specified.
Because I think this will have a lot of overhead.
I would like to make something like a multi row update in an updateable report, but I want to specify the status from somewhere else. Is this possible? -
Having a SP or Function return a set of rows ?
Hi,
I been looking through the documentation that came with PL/SQL and I am trying to figure out how to get a procedure or function to return the rows of a select statement. Would it have to be done using a Table function ?? I am trying to access the results of a procedure that does some pre-processing before returning the results of the query in a JDBC application..
ThanksYou can't return the rows of a SQL query through PL/SQL.
You need to create one or more functions that are called in your select statement to perform the pre-processing i.e.
select function1(param1), function2(param2)
from ...
Regards. -
How to return 0 on max function when no rows found
Hi everyone!
I am using a max fuction, but I want that the function return 0 if there are not rows that match with the conditions.
I was thinking in something like this
SELECT nvl(max(salary),0)
But it doesn't work, it doesn't show the value 0
Please someone can give and idea
Thanks a lot.Hi,
Welcome to the forum!
NVL (salary, 0) returns either salary or 0 on each row. It does not change number of rows.
To make sure that rows exist, you can do an outer join, like this:
SELECT NVL ( MAX (t.salary)
, 0
) AS max_salary
FROM dual
LEFT OUTER JOIN table_x t ON 1 = 1
I hope this answers your question.
If not, post a little sample data (CREATE TABLE and INSERT statements, relevant columns only) for all the tables involved, and the results you want from that data.
Explain, using specific examples, how you get those results from that data.
Always say what version of Oracle you're using (e.g. 11.2.0.2.0).
See the forum FAQ {message:id=9360002} -
Function not returning any rows
If I run this code with a standard SQL statement it will return (1) row - which is correct. But when I try to use a function it is not returning any records. Could someone point what I'm doing wrong?
Also, if a use BindByName if get Oracle error: ORA-06550: line 1, column 50: PLS-00103: Encountered the symbol ">". If I comment out BindByName I will not get this error . Thanks!
C# code:
string domainuser = 'brockj';
string ConnectString = ConfigurationSettings.AppSettings["ConnectString"];
OracleConnection dbconn = new OracleConnection(ConnectString);
OracleCommand cmd = new OracleCommand("access_admin",dbconn);
cmd.CommandType = CommandType.StoredProcedure;
//cmd.BindByName = true;
OracleParameter p_username = new OracleParameter();
OracleParameter p_retval = new OracleParameter();
p_username.OracleDbType = OracleDbType.Varchar2;
p_retval.OracleDbType = OracleDbType.Int16;
p_username.Direction = ParameterDirection.Input;
p_retval.Direction = ParameterDirection.ReturnValue;
p_username.Value = domainuser;
cmd.Parameters.Add(p_username);
cmd.Parameters.Add(p_retval);
dbconn.Open();
cmd.ExecuteScalar();
lblResponse.Text = p_retval.Value.ToString(); -- prints '0', should print '3'
********FUNCTION************
Function access_admin
p_username IN varchar2
RETURN number
IS
l_accesscode users.access_admin%TYPE; -- number(1)
cursor c1 IS
SELECT access_admin
FROM users
WHERE username = p_username
AND active=1
AND rownum=1;
BEGIN
open c1;
fetch c1 into l_accesscode;
if c1%NOTFOUND then
l_accesscode := 0;
end if;
close c1;
RETURN l_accesscode;
END access_admin;Turn the function call into a standard SQL statement:
SELECT access_admin FROM dual;
Here's how you use BindByName:
adapter = new OracleDataAdapter();
adapter.SelectCommand = new OracleCommand("SELECT * FROM emp WHERE sal >= :SAL OR empno = :EMPNO", conn);
adapter.SelectCommand.BindByName = true;
adapter.SelectCommand.Parameters.Add(new OracleParameter("EMPNO", OracleDbType.Int32, 0));
adapter.SelectCommand.Parameters["EMPNO"].Value = 7788;
adapter.SelectCommand.Parameters.Add(new OracleParameter("SAL", OracleDbType.Int32, 0));
adapter.SelectCommand.Parameters["SAL"].Value = 2000;
-- Tom -
Date function not returning any rows
I am trying to pull back rows for data of people who were born in the 90s
a.birthday >= to_date('01/01/90','dd/mm/yy')
and
a.birthday <= to_date('31/12/90','dd/mm/yy')
I know that there is definately users born in the 90s in my database but it returns 0 rows with the above ouptut Date format is like "05-FEB-93", have tried using dd/mon/yy but that gives an erroruser8652681 wrote:
I am trying to pull back rows for data of people who were born in the 90s
a.birthday >= to_date('01/01/90','dd/mm/yy')
and
a.birthday <= to_date('31/12/90','dd/mm/yy')
I know that there is definately users born in the 90s in my database but it returns 0 rows with the above ouptut Date format is like "05-FEB-93", have tried using dd/mon/yy but that gives an errorFirst off to_date('01/01/90','dd/mm/yy') is Jan 1, 2090. You need to use a four digit year.
Secondly a.birthday >= to_date('01/01/1990','dd/mm/yyyy') and a.birthday <= to_date('31/12/1990','dd/mm/yyyy')
is not everyone born in the 90's, it's everyone born in 1990. If you want everyone born in the 90's you need:
a.birthday between to_date('01/01/1990','dd/mm/yyyy') and to_date('31/12/1999 23:59:59','dd/mm/yyyy hh24:mi:ss')I realize your birthdays are most likely trunc'ed so the time portion probably isn't necessary but I included it just to be safe.
Edited by: kendenny on Jul 22, 2009 6:13 AM -
Problem with Function returned without value -
all i am having a problem w/ jdev passing the values. when hardcoded it works. when i remove to pass the 2 vals for doc_type and doc_num the params are being passed to the impl but the String sql = " BEGIN :5 := scotts_test_proc.get_log(:1, :2, :3, :4 ); END; "; is not sending the values to the pkg. to verify i am getting data i created a table to store the data being passed/retrieved by function. i am getting the log_pieces posted when hard coded so i know that works. but when i try to pass the doc_type and doc_num it errors w/ function returend without value . am i passing the params correctly from co to impl to func to get the return l0g_piece. thats for the help
calling package
spec
function Get_Log( -- rmode IN NUMBER , rmode IN STRING, doc_type IN VARCHAR2 DEFAULT 'TEL',
doc_id IN VARCHAR2 DEFAULT NULL , doc_num IN VARCHAR2 DEFAULT NULL
-- , p_out out varchar2
) -- IS --proc
RETURN varchar2 IS --function
body
l_doc_type := 'TEL';- remove this hardcoded
l_doc_type := doc_type ; --to pass the param
IF l_doc_type = 'TEL' THEN
-- l_log_pieces := Get_TEL(TRIM(3524204)); --change 3524204 to doc_num hardcoded presently
l_log_pieces := Get_TEL(TRIM(doc_num)); --to pass the param
-- (doc_num);
l_log_piece := l_log_pieces(1);
-- p_out := l_log_piece ;
insert into isitthere (doc_type, doc_num, isitthere) VALUES (doc_type, doc_num, l_log_piece); commit;
return l_log_piece; -- function -- return p_out; -- function p_out := l_log_piece ; proc
END IF; --if doc type is TEL
FROM CO
System.out.println("CO Passing paramDOC_TYPE for -------> " +docAbbr.getValue(pageContext) ); -- passing TEL
System.out.println("CO Passing paramDOC_NUM for -------> " + paramDOC_NUM ); -- passing 88
String getDocAbbrForHTML = docAbbr.getText(pageContext);
System.out.println("Passing CO getDocAbbrForHTML for -------> " + getDocAbbrForHTML ); -- passing TEL
Serializable paramDocLocatorParamList [] = {paramRMODE, getDocAbbrForHTML , paramDOC_ID, paramDOC_NUM , p_out };
OAApplicationModule am = (OAApplicationModule)pageContext.getApplicationModule(webBean);
OADBTransaction dbtrans;
OAViewObject docLocator = (OAViewObject)am.findViewObject("DocLocatorVO1");
Serializable paramABC = "TELNET";
paramABC = am.invokeMethod("getHTMLString", paramDocLocatorParamList);
rtxt0.setValue(pageContext, "here it is 12354" + paramABC.toString() );
// docLocator.executeQuery();
// --------------- End getHTMLString ----------------- //
FROM AM IMPL
public String getHTMLString ( String paramRMODE, String getDocAbbrForHTML , String paramDOC_ID, String paramDOC_NUM, String p_out )
System.out.println("Entering The AM Impl");
System.out.println("Passing getDocAbbrForHTML in IMPL -------> " +getDocAbbrForHTML ); -- got TEL in param
System.out.println("Passing paramDOC_NUM in IMPL -------> " + paramDOC_NUM ); -- got 88 in param
CallableStatement st = null;
OADBTransaction txn = (OADBTransaction)getDBTransaction();
Connection conn = txn.getJdbcConnection();
String sql = " BEGIN :5 := scotts_test_proc.get_log(:1, :2, :3, :4 ); END; ";
CallableStatement cs = txn.createCallableStatement(sql,1);
String ErrorExist = "";
String getHTML = "";
try
cs.setString(1, paramRMODE); // cs.setInt(1, paramRMODE.intValue()); // cs.setInt(1,Integer.parseInt(paramRMODE));
cs.setString(2, getDocAbbrForHTML); //paramDOC_TYPE);
cs.setString(3, paramDOC_ID);
cs.setString(4, paramDOC_NUM);
// cs.setString(5,p_out); // --param
/* cs.registerOutParameter(1,Types.CHAR);
cs.registerOutParameter(2,Types.CHAR);
cs.registerOutParameter(3,Types.CHAR);
cs.registerOutParameter(4,Types.CHAR);*/
cs.registerOutParameter(5,Types.VARCHAR);
cs.execute();
getHTML = cs.getString(5 ) ;
p_out = getHTML;
//this string is to see my results. only......
String x ="abc 123";/*"<BR><font face=Verdana ><b>TEL Document Action History <BR><font color=#336699>(3524204 Nosulina, Yelena N COMPLETE)</b></font></font><br><br><table border=1 width=100% cellspacing=0 cellpadding=2 bordercolor=#EEEEDC> <tr bgcolor=#F7F7E7>"
+ " <td width=11% valign=top align=left><font face=Verdana size=2 color=#336699><b>Action</b></font></td> <td width=17% valign=top align=left ><font face=Verdana size=2 color=#336699><b>Approver UserName</b></font></td> <td width=14% valign=top align=left ><font face=Verdana size=2 color=#336699><b>Date/Time </b></font></td> <td width=56% valign=top align=left ><font face=Verdana size=2 color=#336699><b>Notes</b></font></td> "
+" </tr> <!-- loop thru this set of rows ---> <tr bgcolor=#FFFFFF> <td width=11% valign=top align=left ><font face=Verdana size=2 > </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2> </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Dec-20-2011 03:01:23 PM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>DOCUMENT CREATED </font></td> </tr> <!-- end loop--> "
+ " <tr bgcolor=#FFFFFF> <td width=11% valign=top align=left ><font face=Verdana size=2 > </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2>McCombs, Tracey L </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Dec-30-2011 01:12:10 PM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>Requestor </font></td> </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> "
+" <td width=11% valign=top align=left ><font face=Verdana size=2 >WF STARTED </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2>Workflow </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Dec-30-2011 01:12:21 PM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>Workflow Started </font></td> </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> "
+"<td width=11% valign=top align=left ><font face=Verdana size=2 > </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2>McCombs, Tracey L </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Dec-30-2011 01:12:21 PM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>SUBMIT </font></td> </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> "
+"<td width=11% valign=top align=left ><font face=Verdana size=2 >NOTIFICATION SENT </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2>Workflow </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Dec-30-2011 01:12:21 PM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>Notification sent to User Approvals Level 1, Org ID: 455 311402400 Med - Infectious Diseases </font></td> "
+" </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> <td width=11% valign=top align=left ><font face=Verdana size=2 > </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2>Brownlow, Lana Jill </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Jan-03-2012 08:49:48 AM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>Approved : </font></td> </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> "
+" <td width=11% valign=top align=left ><font face=Verdana size=2 >USER APPROVED </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2>Workflow </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Jan-03-2012 08:49:48 AM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>Completed all User Approvals </font></td> </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> "
+ " <td width=11% valign=top align=left ><font face=Verdana size=2 >CENTRAL APPROVED </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2> </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Jan-03-2012 08:49:48 AM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>Completed Central Approval Process </font></td> </tr> <!-- end loop--> <tr bgcolor=#FFFFFF> "
+" <td width=11% valign=top align=left ><font face=Verdana size=2 > </font></td> <td width=17% valign=top align=left ><font face=Verdana size=2> </font></td> <td width=14% valign=top align=left ><font face=Verdana size=2>Jan-03-2012 02:17:07 PM </font></td> <td width=56% valign=top align=left ><font face=Verdana size=2>DOCUMENT REASON CHANGED TO COMPLETE. DATA LOADED IN BASE TABLES. </font></td> </tr> <!-- end loop--></table>";
getHTML = x;
System.out.println("getHTML 1234 is " + getHTML ); -- testing output to get returned
cs.close();
catch (SQLException sqle)
try { cs.close(); }
catch (Exception e) {}
throw OAException.wrapperException(sqle);
return getHTML;when return is encountered your function terminates.
-
Silly old fogey (me) cannot figure out why this query returns 1 row
Hi all,
In reference to {thread:id=2456973}, why does
select sum(count(decode(job, 'CLERK', 1, null))) CLERKS
, sum(count(decode(job, 'SALESMAN', 1, null))) SALESMANS
from emp group by job;only return 1 row and not 1 for each job? I actually had to test it myself to believe it.
It returns data as if the query were
select sum(CLERKS), sum(SALESMANS)
from (select count(decode(job, 'CLERK', 1, null)) CLERKS, count(decode(job, 'SALESMAN', 1, null)) SALESMANS
from emp group by job)Using only a single aggregate (either count or sum) returns 1 row per job, as expectedJohn Stegeman wrote:
It returns data as if the query were
select sum(CLERKS), sum(SALESMANS)
from (select count(decode(job, 'CLERK', 1, null)) CLERKS, count(decode(job, 'SALESMAN', 1, null)) SALESMANS
from emp group by job)
Exactly the point ;-)
Seems like Oracle actually can do a "double group by" in the same operation.
Witness the explain plans in this example:
SQL> select count(decode(job, 'CLERK', 1, null)) CLERKS
2 , count(decode(job, 'SALESMAN', 1, null)) SALESMANS
3 from scott.emp group by job;
CLERKS SALESMANS
0 0
0 0
0 0
0 4
4 0
Execution Plan
Plan hash value: 1697595674
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 5 | 40 | 4 (25)| 00:00:01 |
| 1 | HASH GROUP BY | | 5 | 40 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL| EMP | 14 | 112 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------And compare it to this one with the double aggregates:
SQL> select sum(count(decode(job, 'CLERK', 1, null))) CLERKS
2 , sum(count(decode(job, 'SALESMAN', 1, null))) SALESMANS
3 from scott.emp group by job;
CLERKS SALESMANS
4 4
Execution Plan
Plan hash value: 417468012
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 8 | 4 (25)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 8 | 4 (25)| 00:00:01 |
| 2 | HASH GROUP BY | | 1 | 8 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 14 | 112 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------There is both HASH GROUP BY and SORT AGGREGATE.
It does not really make sense to do an aggregate on an aggregate - if both aggregates are used "on the same group-by level".
The sum() aggregates are used upon an already aggregated value, so it does look like Oracle actually treats that as "first do the inner aggregate using the specified group by and then do the outer aggregate on the result with no group by."
Look at this example where I combine "double" aggregates with "single" aggregates:
SQL> select sum(count(decode(job, 'CLERK', 1, null))) CLERKS
2 , sum(count(decode(job, 'SALESMAN', 1, null))) SALESMANS
3 , count(decode(job, 'SALESMAN', 1, null)) SALESMANS2
4 , count(*) COUNTS
5 from scott.emp group by job;
CLERKS SALESMANS SALESMANS2 COUNTS
4 4 1 5
Execution Plan
Plan hash value: 417468012
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 8 | 4 (25)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 8 | 4 (25)| 00:00:01 |
| 2 | HASH GROUP BY | | 1 | 8 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 14 | 112 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------When mixing "double" and "single" aggregates, Oracle decides that single aggregates belong in the "outer" aggregation.
SALESMAN2 is doing a count on the aggregated job column that is the result of the "inner" group by - therefore only 1.
The count(*) also counts the result of the "inner" aggregation.
I am not sure if this is documented or if it is a "sideeffect" of either the internal code used for GROUPING SETS or the internal code used for allowing analytic functions like this:
SQL> select count(decode(job, 'CLERK', 1, null)) CLERKS
2 , count(decode(job, 'SALESMAN', 1, null)) SALESMANS
3 , sum(count(decode(job, 'CLERK', 1, null))) over () CLERKS2
4 , sum(count(decode(job, 'SALESMAN', 1, null))) over () SALESMANS2
5 from scott.emp group by job;
CLERKS SALESMANS CLERKS2 SALESMANS2
0 0 4 4
4 0 4 4
0 0 4 4
0 0 4 4
0 4 4 4
Execution Plan
Plan hash value: 4115955660
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 5 | 40 | 4 (25)| 00:00:01 |
| 1 | WINDOW BUFFER | | 5 | 40 | 4 (25)| 00:00:01 |
| 2 | SORT GROUP BY | | 5 | 40 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 14 | 112 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------Personally I think I would have preferred if Oracle raised an error on this "double aggregation" and thus require me to write it this way (if that is the result I desired):
select sum(CLERKS), sum(SALESMANS)
from (select count(decode(job, 'CLERK', 1, null)) CLERKS, count(decode(job, 'SALESMAN', 1, null)) SALESMANS
from emp group by job)I can not really think of good use-cases for the "double aggregation" - but rather that it could give you unnoticed bugs in your code if you happen to do double aggregation without noticing it.
Interesting thing to know ;-) -
Issue with running PL/SQL function returning Sql query
hi, I am trying to create a report region by using the option of PL/SQL function returning sql query.
I notice that it's very slow for the report region page to show up. In my PL/SQL function body, there are only 3 steps, first update all the 10 rows of varchar2 fields to null,then insert values to those fields, then select all from the table to show report results. It takes more than 5 minitues for the page to load up, how ever, if i run those steps in SQL*Plus, it only takes a couple of seconds to finish. Any suggestions?
Thanks,
ginaSergio, the codes are as followed,
Declare
q varchar2(32767); -- query
Begin
q := 'select "ID",'||
'"ENTRY NAME","TOTAL","#CM","%CM","#CA",'||
'"%CA", from Info_table';
update info_table
set "TOTAL" = '',
"#CM" = '',
"%CM" = '',
"#CA" ='',
"%CA"=''
where "ID"<=10;
// set all data in column Total to null,there is only 10 rows in the table
update info_Table set Total = vTotal,
"#CM" = vCM
(those variables hold user key-in Text filed value)
where ID = 1;
return q;
End; -
Returning Multiple Rows From DBAdapter Calling PL/SQL Procedure
Oracle XE 10g Express Edition
JDeveloper 11.1.1.2.0
WebLogic Server 11g
Guys,
I have a table of orders, which I need to interrogate, and pass back any matching rows which meet certain criteria (e.g. status = 'OPEN').
However, rather than create a DBAdapter using an Operation Type of "Peform an Operation on a Table/Select", I need to use an Operation Type of "Call a Stored Procedure or Function".
I therefore need the procedure to return all the matching rows, rather than a single row.
I have looked at declaring return parameters for the procedure of the following types:
RECORD - is good because it allows me to return the elements of the row with their correct datatypes, but does not meet my needs because it will only support the return of a single row.
VARRAY - good because it can contain many row elements, but not good because it only supports a single row return, and also because all elements of the VARRAY must be of the same data type.
TABLE - good because it can contain many rows, but bad because each row can contain only two elements - the index element and the data element.
I think I could first define a RECORD (to hold a row), and then define a TABLE, with the data element being the RECORD, but I have found JDeveloper very fussy indeed when dealing with 'non-standard' data types in the DBAdapter.
Apologies if I am missing something obvious, but can anyone suggest a way of doing this?
Many thanks in advance.
Edited by: user2541290 on 17-Feb-2010 02:48Hi, I've been able to create process that seems to work. My platform is a but different but I don't think this is important for your question.
Here is the PL/SQL code. Just make Db Adapter for Calling stored procedure and it returns all rows!
Be aware of possible limitations on how manyrows you could return in one select! This can have severe impact on performance.
Succes.
Jos Baan
CREATE OR REPLACE PACKAGE lab2_multiple_rows IS
-- Author : 801455
-- Created : 18-2-2010 8:05:52
-- Purpose :
-- Public type declarations
TYPE rrows IS RECORD(
mutdat DATE,
opmerking VARCHAR2(20));
TYPE trows IS TABLE OF rrows INDEX BY BINARY_INTEGER;
-- Public constant declarations
-- Public variable declarations
-- Public function and procedure declarations
FUNCTION retrows RETURN trows;
END lab2_multiple_rows;
CREATE OR REPLACE PACKAGE BODY lab2_multiple_rows IS
-- Private type declarations
-- Private constant declarations
-- Private variable declarations
-- Function and procedure implementations
FUNCTION retrows RETURN trows IS
lrows trows;
lidx binary_integer := 1;
BEGIN
FOR rsql IN (SELECT t.* FROM jba_transactions t ORDER BY t.mutdat)
LOOP
lrows(lidx).mutdat := rsql.mutdat;
lrows(lidx).opmerking := rsql.opmerking;
lidx := lidx + 1;
END LOOP;
RETURN(lrows);
END;
BEGIN
-- Initialization
NULL;
END lab2_multiple_rows;
Edited by: Baan, Jos on 18-feb-2010 8:53 -
Function returning error - change notification
I have a function returning error text. When error occurs I get the message
'xx error has occurred' on the screen (in notification). Is there a way to control the message text so I can display different text?It's something like this:
DECLARE l_code zip.code%TYPE;
got_error varchar2(1) := 'N';
l_check_fld varchar2(30000);
l_error_fld varchar2(32000);
vErrorFields varchar2(1000);
CURSOR check_zip IS
select ''
from zip
where code = l_code;
BEGIN
apex_collection.create_or_truncate_collection('ZIP');
FOR i IN 1 .. apex_application.g_f03.COUNT LOOP
vErrorFields := '';
/* Code MUST be entered */
if (apex_application.g_f03(i) is null and
(apex_application.g_f04(i) is not null or
apex_application.g_f05(i) is not null))then
got_error := 'Y';
vErrorFields := vErrorFields || ',f03';
l_error_fld := l_error_fld || 'Row ' || to_char(i) || ':' ||' <span style="color: red">Code cannot be <strong>blank.</strong></span><br>';
end if;
END LOOP;
if got_error = 'N' then
apex_collection.delete_collection('ZIP');
end if;
RETURN l_error_fld;
END; -
How just return one row of a one to many join..
So I have a one to many join where the SMOPERATOR table has data I need however it has a couple of rows that match the JOIN condition in there. I just need to return one row. I think this can be accomplished with a subquery in the join however have not been able to come up with the right syntax to do so.
So:
SELECT "NUMBER" as danumber,
NAME,
SMINCREQ.ASSIGNMENT,
SMOPERATOR.PRIMARY_ASSIGNMENT_GROUP,
SMOPERATOR.WDMANAGERNAME,
SMINCREQ.owner_manager_name,
SMINCREQ.subcategory, TO_DATE('01-'||TO_CHAR(open_time,'MM-YYYY'),'DD-MM-YYYY')MONTHSORT,
(CASE WHEN bc_request='f' THEN 'IAIO'
WHEN (bc_request='t' and substr(assignment,1,3)<>'MTS') THEN 'RARO'
WHEN (bc_request='t' and substr(assignment,1,3)='MTS') THEN 'M'
ELSE 'U' end) as type
from SMINCREQ
left outer join SMOPERATOR on SMINCREQ.assignment=SMOPERATOR.primary_assignment_group
WHERE SMINCREQ.owner_manager_name=:P170_SELECTION and SMOPERATOR.wdmanagername=:P170_SELECTION
AND open_time BETWEEN to_date(:P170_SDATEB,'DD-MON-YYYY') AND to_date(:P170_EDATEB,'DD-MON-YYYY')
AND
(bc_request='f' and subcategory='ACTIVATION' and related_record<>'t')
OR
(bc_request='f' and subcategory<>'ACTIVATION')
OR
(bc_request='t' and substr(assignment,1,3)<>'MTS')
order by OPEN_TIMeHi,
This sounds like a Top-N Query , where you pick N items (N=1 in this case) off the top of an orderded list. I think you want a separate ordered list for each assignment; the analytic ROW_NUMBER function does that easily.
Since you didn't post CREATE TABLE and INSERT statements for your sample data, I'll use tables from the scott schema to show how this is done.
Say you have a query like this:
SELECT d.dname
, e.empno, e.ename, e.job, e.sal
FROM scott.dept d
JOIN scott.emp e ON d.deptno = e.deptno
ORDER BY dname
;which produces this output:
DNAME EMPNO ENAME JOB SAL
ACCOUNTING 7934 MILLER CLERK 1300
ACCOUNTING 7839 KING PRESIDENT 5000
ACCOUNTING 7782 CLARK MANAGER 2450
RESEARCH 7876 ADAMS CLERK 1100
RESEARCH 7902 FORD ANALYST 3000
RESEARCH 7566 JONES MANAGER 2975
RESEARCH 7369 SMITH CLERK 800
RESEARCH 7788 SCOTT ANALYST 3000
SALES 7521 WARD SALESMAN 1250
SALES 7844 TURNER SALESMAN 1500
SALES 7499 ALLEN SALESMAN 1600
SALES 7900 JAMES CLERK 950
SALES 7698 BLAKE MANAGER 2850
SALES 7654 MARTIN SALESMAN 1250Now say you want to change the query so that it only returns one row per department, like this:
DNAME EMPNO ENAME JOB SAL
ACCOUNTING 7782 CLARK MANAGER 2450
RESEARCH 7876 ADAMS CLERK 1100
SALES 7499 ALLEN SALESMAN 1600where the empno, ename, job and sal columns on each row of output are all taken from the same row of scott.emp, though it doesn't really matter which row that is.
One way to do it is to use the analytic ROW_NUMBER function to assign a sequence of unique numbers (1, 2, 3, ...) to all the rows in each department. Since each sequence startw with 1, and the numbers are unique within a department, there will be exactly one row per departement that was assigned the numebr 1, and we''ll display that row.
Here's how to code that:
WITH got_r_num AS
SELECT d.dname
, e.empno, e.ename, e.job, e.sal
, ROW_NUMBER () OVER ( PARTITION BY d.dname
ORDER BY e.ename
) AS r_num
FROM scott.dept d
JOIN scott.emp e ON d.deptno = e.deptno
SELECT dname
, empno, ename, job, sal
FROM got_r_num
WHERE r_num = 1
ORDER BY dname
;Notice that he sub-query got_r_num is almost the same as the original query; only it has one additional column, r_num, in the SELECT clause, and the sub-qeury does not have an ORDER BY clause. (Sub-queries almost never have an ORDER BY clause.)
The ROW_NUMBER function must have an ORDER BY clause. In this example, I used "ORDER BY ename", meaning that, within each department, the row with the first ename (in sort order) will get r_num=1. You can use any column, or expression, or expressions in the ORDER BY clause. You muight as well use something consistent and predictable, like ename, but if you really wanted arbitrary numbering you could use a constant in the analytic ORDER BY clause, e.g. "ORDER BY NULL".
Maybe you are looking for
-
Navigating from Summary Report to Detail Report in OBIEE 11g
Hi, I have creted two reports.One corresponds to Summary and the other Detail.By clicking on one of the fields in the Summary report the values are captured and then the detail report is displayed based on the values selected. Now,What I need to know
-
Flash MX profesional 2004 fails to open on mac osx 10.6.7
i am trying to install a copy of Flash macromeadia 2004 mx profesional. the software installs fine when i go to open it it apears in the dock and nothing happens. right clicking on the icon in the dock the program says it's not reasponding. on the bo
-
Gmail contact addresses not syncing properly in iOS 4
Since updating my 3GS to iOS 4, I've noticed a change in the way contact addresses are entered: there is a separate field for each individual address component. The problem is that all my contact addresses are now populating the fields incorrectly. T
-
Camera RAW Support 2.3 is available in Software Updates
It has been mentioned, but not in a separate post. It adds support for the: Nikon D90 Canon 50D Sony A900 Nikon CoolPix P6000 Message was edited by: Steven Hale
-
How to start Forms Server listener automatically?
hi... i use forms 5.0 on Windows NT for the web. i want to start forms server listenner automatic same as WWW listener. because i must logon on Windows NT before start forms server listener. thank you very much. jibjoi null