Xmltable returning no rows
I have the following XML
<?xml version = '1.0' encoding = 'UTF-8'?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:sawsoap="urn://oracle.bi.webservices/v6">
<soap:Body>
<sawsoap:getGroupsResult>
<sawsoap:account xsi:type="sawsoap:Account">
<sawsoap:name>Presentation Server Administrators</sawsoap:name>
<sawsoap:accountType>1</sawsoap:accountType>
<sawsoap:guid>bipse53c4188a730640cc6c0a242</sawsoap:guid>
</sawsoap:account>
<sawsoap:account xsi:type="sawsoap:Account">
<sawsoap:name>AuthenticatedUser</sawsoap:name>
<sawsoap:accountType>4</sawsoap:accountType>
<sawsoap:guid>AuthenticatedUser</sawsoap:guid>
</sawsoap:account>
<sawsoap:account xsi:type="sawsoap:Account">
<sawsoap:name>BIConsumer</sawsoap:name>
<sawsoap:accountType>4</sawsoap:accountType>
<sawsoap:guid>BIConsumer</sawsoap:guid>
</sawsoap:account>
</sawsoap:getGroupsResult>
</soap:Body>
</soap:Envelope>I am trying to generate the list of account types, which in this case would just be
Presentation Server Administrators
AuthenticatedUser
BIConsumer
I am using the following SQL statement in my attempt, but it is returning zero rows.
select x.*
from tony, xmltable ('/account'
passing extract(x,'//sawsoap:getGroupsResult','xmlns:sawsoap="urn://oracle.bi.webservices/v6"')
columns
group_name varchar2(255) path '/name'
) x;I have tried different combinations of XPaths, including the sawsoap:account and sawsoap:name,but other continue to return no records. I have the sense that I am close and would appreciate a second set of eyes that could point out the mistake.
Tony
Welcome to the forums. When posting, always include your version as shown by
select * from v$version
It makes a difference. For your issue, you are mixing some pre 10.2 syntax (extract) with 10.2 and later syntax (XMLTable).
What you are looking for is something like
WITH tony AS
(SELECT XMLTYPE('<?xml version = ''1.0'' encoding = ''UTF-8''?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:sawsoap="urn://oracle.bi.webservices/v6">
<soap:Body>
<sawsoap:getGroupsResult>
<sawsoap:account xsi:type="sawsoap:Account">
<sawsoap:name>Presentation Server Administrators</sawsoap:name>
<sawsoap:accountType>1</sawsoap:accountType>
<sawsoap:guid>bipse53c4188a730640cc6c0a242</sawsoap:guid>
</sawsoap:account>
<sawsoap:account xsi:type="sawsoap:Account">
<sawsoap:name>AuthenticatedUser</sawsoap:name>
<sawsoap:accountType>4</sawsoap:accountType>
<sawsoap:guid>AuthenticatedUser</sawsoap:guid>
</sawsoap:account>
<sawsoap:account xsi:type="sawsoap:Account">
<sawsoap:name>BIConsumer</sawsoap:name>
<sawsoap:accountType>4</sawsoap:accountType>
<sawsoap:guid>BIConsumer</sawsoap:guid>
</sawsoap:account>
</sawsoap:getGroupsResult>
</soap:Body>
</soap:Envelope>') x
FROM dual)
-- The above WITH simulates your table. You only care about the below
SELECT x.*
FROM tony,
XMLTable(XMLNamespaces('http://schemas.xmlsoap.org/soap/envelope/' AS "soap",
'urn://oracle.bi.webservices/v6' AS "sawsoap"),
'/soap:Envelope/soap:Body/sawsoap:getGroupsResult/sawsoap:account'
PASSING tony.x
COLUMNS
group_name VARCHAR2(40) PATH 'sawsoap:name'
) x;
GROUP_NAME
Presentation Server Administrators
AuthenticatedUser
BIConsumer
Similar Messages
-
Query with XMLTABLE returns null rows
Hello all,
I'm trying a query with XMLTABLE, but even thought the number of returned rows is correct, the row content is (null).
DB version is: 10.2.0.4.0
Here is my query;
SELECT s.DESCRIPTION
FROM EXECUTIONPLAN p,
XMLTABLE
('//executionPlan/executionPlanItems/summary'
PASSING p.DATA
COLUMNS
DESCRIPTION VARCHAR(250) PATH '/taskId'
) s
WHERE
trunc(extractValue(data, '/executionPlan/executionPlanHeader/statusChanged')) = to_date('2010-03-05','YYYY-MM-DD');Sorry the XML content is quite big -50k lines at average- so can't post the whole XML, but to give an idea;
/executionPlan
/executionPlan
/executionPlanHeader
/statusChanged
/x
/y
/executionPlanItems
/summary
/taskId
/summary
/summary
...The result looks like;
1 (null)
2 (null)
3 (null)
4 (null)
...Suggestions are very much appreciated :)
CheersHi guys,
Cracked it at last. It seems the column definition part does not like the forward slash in front of it. The following works;
SELECT s.DESCRIPTION
FROM EXECUTIONPLAN p,
XMLTABLE
( XmlNamespaces(DEFAULT 'http://www.staffware.com/frameworks/gen/valueobjects'),
'/executionPlan/executionPlanItems/summary'
PASSING p.DATA
COLUMNS
DESCRIPTION VARCHAR(250) PATH 'taskId'
) s
WHERE
trunc(extractValue(p.data, '/executionPlan/executionPlanHeader/statusChanged'
, 'xmlns="http://www.staffware.com/frameworks/gen/valueobjects"')) = to_date('2010-03-05','YYYY-MM-DD');I'm not sure if this is the way it is intended since it seems a bit weird to me and is not in line with the docs - or at least my understanding of them.
Thanks for taking the time to help out. Now on to coding :) -
XMLTABLE returns only first row
I have follwoing XML inserted into the column named as TEXT in the table MASTERTB.
*<?xml version="1.0" encoding="utf-8" ?>*
*<Rowsets DateCreated="2010-11-30T11:12:10" EndDate="2010-06-05T16:52:23" StartDate="2010-06-05T16:52:23" Version="12.0.10 Build(18)">*
*<Rowset>*
*<Columns>*
*<Column Description="Material Number" MaxRange="1" MinRange="0" Name="MATERIAL" SQLDataType="1" SourceColumn="MATERIAL"/>*
*<Column Description="" MaxRange="1" MinRange="0" Name="TANK" SQLDataType="1" SourceColumn="TANK"/>*
*</Columns>*
*<Row>*
*<MATERIAL>1000000144</MATERIAL>*
*<TANK>T1000</TANK>*
*</Row>*
*<Row>*
*<MATERIAL>2000000008</MATERIAL>*
*<TANK>T1000</TANK>*
*</Row>*
*<Row>*
*<MATERIAL>2000000009</MATERIAL>*
*<TANK>T1000</TANK>*
*</Row>*
*<Row>*
*<MATERIAL>2000000016</MATERIAL>*
*<TANK>T1000</TANK>*
*</Row>*
*<Row>*
*<MATERIAL>3000000036</MATERIAL>*
*<TANK>T1000</TANK>*
*</Row>*
*</Rowset>*
*</Rowsets>*
Now, when my requirement is to get all the Material values so when I run follwoing query in Oracle,
SELECT RW.MATERIAL
FROM MASTERTB TM,
XMLTable('//Row' PASSING TM.TEXT
COLUMNS "MATERIAL" CHAR(30) PATH 'MATERIAL') AS RW
it return only 1000000144 (First MATERIAL). How can I read all the MATERIAL? Also, how can I read the entire XML in Text format if I want to check what has been inserted?
ANy help will be appreciated !
Edited by: 967327 on Oct 27, 2012 12:28 AM>
<Rowsets DateCreated="2010-11-30T11:12:10" EndDate="2010-06-05T16:52:23" StartDate="2010-06-05T16:52:23" Version="12.0.10 Build(18)">
<Rowset>
</Rowset>
>
so where is </Rowsets> ?
your query works for me
SQL> select * from v$version where rownum=1;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
SQL>
SQL> with MASTERTB as
2 (select
3 xmltype('<?xml version="1.0" encoding="utf-8" ?>
4 <Rowsets DateCreated="2010-11-30T11:12:10" EndDate="2010-06-05T16:52:23" StartDate="2010-06-05T16:52:23" Version="12.0.10 Build(18)">
5 <Rowset>
6 <Columns>
7 <Column Description="Material Number" MaxRange="1" MinRange="0" Name="MATERIAL" SQLDataType="1" SourceColumn="MATERIAL"/>
8 <Column Description="" MaxRange="1" MinRange="0" Name="TANK" SQLDataType="1" SourceColumn="TANK"/>
9 </Columns>
10 <Row>
11 <MATERIAL>1000000144</MATERIAL>
12 <TANK>T1000</TANK>
13 </Row>
14 <Row>
15 <MATERIAL>2000000008</MATERIAL>
16 <TANK>T1000</TANK>
17 </Row>
18 <Row>
19 <MATERIAL>2000000009</MATERIAL>
20 <TANK>T1000</TANK>
21 </Row>
22 <Row>
23 <MATERIAL>2000000016</MATERIAL>
24 <TANK>T1000</TANK>
25 </Row>
26 <Row>
27 <MATERIAL>3000000036</MATERIAL>
28 <TANK>T1000</TANK>
29 </Row>
30 </Rowset></Rowsets>') TEXT from dual)
31 SELECT RW.MATERIAL
32 FROM MASTERTB TM,
33 XMLTable('//Row' PASSING TM.TEXT
34 COLUMNS "MATERIAL" CHAR(30) PATH 'MATERIAL') AS RW
35 /
MATERIAL
1000000144
2000000008
2000000009
2000000016
3000000036
SQL>
SQL> select * from v$version where rownum=1;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
SQL>
SQL> with MASTERTB as
2 (select
3 xmltype('<?xml version="1.0" encoding="utf-8" ?>
4 <Rowsets DateCreated="2010-11-30T11:12:10" EndDate="2010-06-05T16:52:23" StartDate="2010-06-05T16:52:23" Version="12.0.10 Build(18)">
5 <Rowset>
6 <Columns>
7 <Column Description="Material Number" MaxRange="1" MinRange="0" Name="MATERIAL" SQLDataType="1" SourceColumn="MATERIAL"/>
8 <Column Description="" MaxRange="1" MinRange="0" Name="TANK" SQLDataType="1" SourceColumn="TANK"/>
9 </Columns>
10 <Row>
11 <MATERIAL>1000000144</MATERIAL>
12 <TANK>T1000</TANK>
13 </Row>
14 <Row>
15 <MATERIAL>2000000008</MATERIAL>
16 <TANK>T1000</TANK>
17 </Row>
18 <Row>
19 <MATERIAL>2000000009</MATERIAL>
20 <TANK>T1000</TANK>
21 </Row>
22 <Row>
23 <MATERIAL>2000000016</MATERIAL>
24 <TANK>T1000</TANK>
25 </Row>
26 <Row>
27 <MATERIAL>3000000036</MATERIAL>
28 <TANK>T1000</TANK>
29 </Row>
30 </Rowset></Rowsets>') TEXT from dual)
31 SELECT RW.MATERIAL
32 FROM MASTERTB TM,
33 XMLTable('//Row' PASSING TM.TEXT
34 COLUMNS "MATERIAL" CHAR(30) PATH 'MATERIAL') AS RW
35 /
MATERIAL
1000000144
2000000008
2000000009
2000000016
3000000036
SQL> try
31 SELECT RW.MATERIAL
32 FROM MASTERTB TM,
33 XMLTable('Rowsets/Rowset/Row' PASSING TM.TEXT
34 COLUMNS "MATERIAL" varchar2(30) PATH 'MATERIAL') AS RW
35 /
MATERIAL
1000000144
2000000008
2000000009
2000000016
3000000036
SQL> -
XML attributes makes my query return no rows
Hello everyone,
I've an odd problem.
I'm querying some XML, but the attributes in one of the tags make my query return no rows; if I remove the attributes, then the query works as expected.
The XML is below; it's the attributes in the Report tag that cause the issues:
<result errorCode="0">
<return>
<Report
xsi:schemaLocation="Items_x0020_status_x0020_information http://******-****/ReportServer?%2FReports%2FContent%20Producer%20Reports%2FItems%20status%20information&rs%3AFormat=xml&rc%3ASchema=True"
Name="Items status information" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="Items_x0020_status_x0020_information">
<Tablix1>
<Details_Collection>
<Details ItemId="914P7" Username="test" user_role="IT"
first_name="Barry" last_name="Donovan" organisation=""
content_format="On_Screen" modified_date="26/05/2011 13:16:49"
item_status="Draft" status_date="" component_name="" demand="" />
</Details_Collection>
</Tablix1>
</Report>
</return>
</result>My query is:
select
a.item_id
,a.username
,a.user_role
,a.first_name
,a.last_name
,a.supplier_id
,a.format
,a.modified_date
,a.item_status
,a.completion_date
,a.component_code
from dual
,xmltable
('/result/return/Report/Tablix1/Details_Collection/Details'
passing p_xml
columns
item_id varchar2(1000) path '@ItemId'
,username varchar2(1000) path '@Username'
,user_role varchar2(1000) path '@user_role'
,first_name varchar2(1000) path '@first_name'
,last_name varchar2(1000) path '@last_name'
,supplier_id varchar2(1000) path '@organisation'
,format varchar2(1000) path '@content_format'
,modified_date varchar2(1000) path '@modified_date'
,item_status varchar2(1000) path '@item_status'
,completion_date varchar2(1000) path '@status_date'
,component_code varchar2(1000) path '@demand'
) a;I've tried stripping out the attributes in the tag, which does work, but some of the XML I'm expecting back may be quite large (many records), so that caused issues in itself. I'd rather deal with it and not mess with the XML itself if possible.
Any help would be hugely appreciated!
Thank you very much in advance.
Robin
Edited by: User_resU on Apr 12, 2012 2:50 PMExample:
SQL> ed
Wrote file afiedt.buf
1 with t as (select xmltype('<result errorCode="0">
2 <return>
3 <Report
4 xsi:schemaLocation="Items_x0020_status_x0020_information http://******-****/ReportServer?%2FReports%2FContent%20Producer%20Reports%2FItems%20status%20information&rs%3AFormat=xml&rc%3ASchema=True"
5 Name="Items status information" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6 xmlns="Items_x0020_status_x0020_information">
7 <Tablix1>
8 <Details_Collection>
9 <Details ItemId="914P7" Username="test" user_role="IT"
10 first_name="Barry" last_name="Donovan" organisation=""
11 content_format="On_Screen" modified_date="26/05/2011 13:16:49"
12 item_status="Draft" status_date="" component_name="" demand="" />
13 </Details_Collection>
14 </Tablix1>
15 </Report>
16 </return>
17 </result>') as xml from dual)
18 --
19 -- end of test data
20 --
21 select
22 a.item_id
23 ,a.username
24 ,a.user_role
25 ,a.first_name
26 ,a.last_name
27 ,a.supplier_id
28 ,a.format
29 ,a.modified_date
30 ,a.item_status
31 ,a.completion_date
32 ,a.component_code
33 from t
34 ,xmltable
35 (xmlnamespaces('Items_x0020_status_x0020_information' as "x0"),
36 '//x0:Report/x0:Tablix1/x0:Details_Collection/x0:Details'
37 passing xml
38 columns
39 item_id varchar2(1000) path '@ItemId'
40 ,username varchar2(1000) path '@Username'
41 ,user_role varchar2(1000) path '@user_role'
42 ,first_name varchar2(1000) path '@first_name'
43 ,last_name varchar2(1000) path '@last_name'
44 ,supplier_id varchar2(1000) path '@organisation'
45 ,format varchar2(1000) path '@content_format'
46 ,modified_date varchar2(1000) path '@modified_date'
47 ,item_status varchar2(1000) path '@item_status'
48 ,completion_date varchar2(1000) path '@status_date'
49 ,component_code varchar2(1000) path '@demand'
50* ) a
SQL> /
ITEM_ID
USERNAME
USER_ROLE
FIRST_NAME
LAST_NAME
SUPPLIER_ID
FORMAT
MODIFIED_DATE
ITEM_STATUS
COMPLETION_DATE
COMPONENT_CODE
914P7
test
IT
Barry
Donovan
On_Screen
26/05/2011 13:16:49
Draft -
The simplest way for plsql procedure to return multiple rows
Hi,
What is the simplest way for plsql procedure to return multiple rows (records). There are many combination of ways to do it but I am looking for a solution that is appropriate for plsql beginners. Many solutions use cursors, cursor variables, collections and more that kind of things that are complex on the face of it. Is it somehow possible to achieve the same with less effort?
Sample query would be: SELECT * FROM EMPLOYEES;
I want to use returned rows in APEX to compose APEX SQL(in that context plsql) report.
It is enough to use just SELECT * FROM EMPLOYEES query in APEX but I want to use plsql procedure for that.
Thank you!Hi,
It depends :-).
With +...that is appropriate for plsql beginners...+ in mind... it still depends!
The list of techniques (ref cursors, cursor variables, collections, arrays, using explict SQL) you have referenced in your post can be made to work. but...
+Is it somehow possible to achieve the same with less effort?+ Less effort : That needs to be defined (measured). Especially in the context of pl/sql beginners (who is a beginner?) .
What is the level of "programming experience" ?
What is the level of understanding of "Relational Result set" as processible in Oracle?
If you are looking for
Process_the_set_of rows_in APEX () kind of capabilitywhich "abstracts/hides" relation database from developers when working on relation database, it may not be the best approach (at least strategically). Because I believe it already is abstracted enough.
I find REF CUROSOR most effective for such use, when the "begginer" has basic understanding of processing SQL result set .
So in a nut shell, the techniques (that you already are familiar with) are the tools available. I am not aware of any alternative tools (in pure Oracle) that will simplify / hide basics from develpers.
vr,
Sudhakar B. -
Query to return ALL rows even those with zero counts
Hi,
The following query will return only those rows that have a non zero count value:
select c.id, a.name, count(*) as XYZ from CON c, CUST a
where c.help !='1' and (c.id = a.id) group by c.id, a.name order by c.id;
The results are:
1 ME 3
3 YOU 4
What i want is to return all rows in CUST and the count, XYZ, that correspond to each row in CUST that matches the whare condition above, even if the count is zero.
ie
1 ME 3
2 WE 0
3 YOU 4
Can this be done?You may want to get the counts then do the outer join. If you simply count with an outer join you will get 1 for 'WE' because there is a row in the cust table with 'WE'. This may work for you;
with
cust as (
select 1 id, 'ME' name from dual union all
select 2 id, 'YOU' name from dual union all
select 3 id, 'WE' name from dual),
con as (
select 1 id, '2' help from dual union all
select 1 id, '2' help from dual union all
select 1 id, '2' help from dual union all
select 2 id, '2' help from dual union all
select 2 id, '2' help from dual union all
select 2 id, '2' help from dual union all
select 2 id, '2' help from dual)
-- end of test data
select a.id, a.name, nvl(c.cnt,0) xyz
from cust a,
(select id, help, count(*) cnt
from con
where help !='1'
group by id, help) c
where a.id = c.id(+) -
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 -
Query executed within a plug-in script returns 0 rows, although data exists
I created a plug-in script for algorithm entity: Service Quantity Rule.
The script calls a business service that I created using query zones. The query returns the values of the bill segment (ci.bseg.bseg_id and ci_bseg.closing_bseg_sw) that is created while running a bill manually. The zone receives the bseg_id as a parameter.
The problem is that when I execute the business service within the plug-in script the business services returns 0 rows even though the data is actually being stored in the database.
The script calculates some SQI values and saves it to the bill segment based on a response that is received from MDM (I'm using the usage request object).
Steps:
1.- Create Bill. The bill segment is created in error as it is waiting for the bill determinants to be sent from the MDM. If I test the zone with the bseg_id (as a parameter) of the newly created bill segment it works fine.
2.- We send a message from the MDM to CC&B. The message is received and processed and it gets to a point when the usage updates the bill segment.
3.- After the bill segment has been updated with the values from the usage request object it starts executing the plug-in script.
4.- I obtain the bseg_id from the usage request and use the business service (passing the bseg_id as a parameter) and it returns no result.
5.- The process finishes and if test the zone with the bseg_id (as a paramter) of the billing segment it works fine.
So apparently during the execution of the script after the billing determinants are received from MDM I can't have access to the Bill segment that was created, even if the physically the record exists in the database (CI_BSEG).
I also tried instantiating an object related with the bill segment and got the same result.
Any idea or clue of what is happening?Could you be more explicit.
What CC&B version?
What MDM version?
More details are required for:
2.- We send a message from the MDM to CC&B. The message is received and processed and it gets to a point when the usage updates the bill segment.
3.- After the bill segment has been updated with the values from the usage request object it starts executing the plug-in script.
4.- I obtain the bseg_id from the usage request and use the business service (passing the bseg_id as a parameter) and it returns no result. -
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 ;-) -
Bug Report: ResultSet.isLast() returns false when queries return zero rows
When calling the method isLast() on a resultset that contains zero (0) rows, false is returned. If a resultset contains no rows, isLast() should return true because returning false would indicate that there are more rows to be retrieved.
Try the following Java source:
import java.io.*;
import java.sql.*;
import java.util.*;
import oracle.jdbc.driver.*;
public class Test2 {
public static void main (String [] args) throws Exception {
Connection conn = null;
String jdbcURL = "jdbc:oracle:thin:@" +
"(DESCRIPTION=(ADDRESS=(HOST=<host computer>)"+
"(PROTOCOL=tcp)(PORT=<DB port number>))"+
"(CONNECT_DATA=(SID=<Oracle DB instance>)))";
String userId = "userid";
String password = "password";
try{
// Load the Oracle JDBC Driver and register it.
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
// *** The following statement creates a database connection object
// using the DriverManager.getConnection method. The first parameter is
// the database URL which is constructed based on the connection parameters
// specified in ConnectionParams.java.
// The URL syntax is as follows:
// "jdbc:oracle:<driver>:@<db connection string>"
// <driver>, can be 'thin' or 'oci8'
// <db connect string>, is a Net8 name-value, denoting the TNSNAMES entry
conn = DriverManager.getConnection(jdbcURL, userId, password);
} catch(SQLException ex){ //Trap SQL errors
// catch error
//conn = new OracleDriver().defaultConnection(); // Connect to Oracle 8i (8.1.7), use Oracle thin client.
PreparedStatement ps = conn.prepareStatement("select 'a' from dual where ? = ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); // Use any query that will return zero rows.
ps.setInt(1, 1); // Set the params so that the query returns 0 rows.
ps.setInt(2, 2);
ResultSet rs = ps.executeQuery();
System.out.println("1. Last here? " + rs.isLast());
while (rs.next()) {
// do whatever
System.out.println("2. Last here? " + rs.isLast());
ps.close();
rs.close();
EXPECTED RESULT -
1. Last here? true
2. Last here? true
ACTUAL RESULT -
1. Last here? false
2. Last here? false
This happens to me on Oracle 9.2.0.1.0.387561,
For your information, I discovered this problem from
running a query that did access an actual DB table.
Try it and let me know.I did say I was only guessing, and yes, I did try it (after I posted my reply, and before I read yours). And I did check the query plan for the queries I tried -- to verify that they were actually doing some database "gets".
In any case, the usual way that I determine whether a "ResultSet" is empty is when the very first invocation of method "next()" returns 'false'. Is that not sufficient for you?
Good Luck,
Avi. -
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 -
ExecuteWithParams is not returning the rows from cache
Hi,
We have two VO's based on same entity ,whenever new row is inserted in one VO and we do executeWithParams on another VO ,It is not returning the rows which are uncommitted.
I replaced the executeWithParams with a custom method in AM in which I am executing the query after applying the view criteria and setting query mode.Its returning rows which are uncommitted.
Jdev Version which I am using is 11.1.1.7.0
ExecuteWithParams used to work with uncommitted data in 11.1.1.6.0 .
Do we need to raise a bug on framework or Am I missing something?
Edited by: sharavnkumar_malla on Oct 18, 2012 1:02 AMStill the same answer, even after you updated the question. We (the public) don't have 11.1.1.7, know nothing about 11.1.1.7, and cannot help you with 11.1.1.7. Questions about internal builds belong on internal forums.
-
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". -
Pl/sql block returning multiple rows
Hi,
I've created a plsql block which obtains an id from a name and then uses this id in another sql statement. The select statement to get the id works fine and the correct id is placed into the variable awardID.
when i try to use this variable in another select statement it returns multiple rows. but when i just use the id in the select statement it works fine.
select AwardID into awardID
from award_objtabA
where Name = awardName;
this returns the correct id '5999'
select Points into award_points
from award_objtabA
where AwardID = awardID;
this returns multiple rows
select Points into award_points
from award_objtabA
where AwardID = 5999;
this works fine
can anybody help with this confusing error?
Cheersselect AwardID
into awardID <= the same column
from award_objtabA
where Name = awardName;
this returns the correct id '5999'
select Points
into award_points
from award_objtabA
where AwardID = awardID; <= the same column
this returns multiple rows
to solve use different name not exactly the same as that of the column name
select AwardID
into vAwardID
from award_objtabA
where Name = awardName;
select Points
into award_points
from award_objtabA
where AwardID = vAwardID;as Alex and Kamal have suggested use different name for your variable. -
Returning a row of data in a stored procedure
Please help me remember how to return a row or rows from a pl/sql query in a stored procedure.
I am having a major brain fart.If want to return a resultset from stored procedures see here for an example
http://asktom.oracle.com/~tkyte/ResultSets/index.html
Maybe you are looking for
-
Hi Gurus, I'm working on a table of below structure. namexxxxx message [email protected] abc123 [email protected] def456 Now, I'm sending mail based on this table using SMPT_UTIL. but the problem is, their exists some special characters (ITALY langua
-
I made a short 6 second reference movie from FCP 5 and then took it into Motion and added that glow-y box effect, from one of the templates, with some text flying in. This worked great. I saved the file as a Motion file, then brought it in to DVD SP
-
Sequence Settings for HD to SD DVD
I have an HD Camcorder that records to a flash 8 GB memory card. Once I import the files into Final Cut Pro, I need to export using Compressor with the "DVD Best Quality for 90 minutes" option. The problem is that Compressor takes forever. Over 60 ho
-
Error output to 'write to spreadsheet'
Hi I dont know, whether someone talked about this earlier. But I prefer error output for 'write to spreadsheet file' subvi, as it keep crashing the software with error 5. I want this, Thanks Cube
-
When browsing files on a file server via the IOS WebVPN clientless VPN, the files do not appear to be indexed an any logical manner. Is there a way to get the VPN to index the files in any type of order such as alphabetical? Thanks, Mike