Return multiple cursors
I need help in figuring out the best solution for returning data through a package which will contain repeating data from multiple tables. For example
I have two tables one and two
one(position,name) and contains
sales, david
sales, jane
marketing, jon
two (name, product_id) contains
david, 45
david, 68
david, 75
jane, 1
the user will input position and i need to return a cursor that will contain all the values in tables one and two where names equal each other. So if a person enters in sales i would need to return
sales, david, 45
68
75
sales, jane 1
without repeating position and name over and over.
You may use two ref cursors
CREATE OR REPLACE PROCEDURE test_ps (
in_id NUMBER,
cur1 OUT sys_refcursor,
cur2 OUT sys_refcursor
AS
BEGIN
OPEN cur1 FOR
SELECT 1
FROM DUAL;
OPEN cur2 FOR
SELECT 2
FROM DUAL;
END;
Similar Messages
-
Return multiple cursors from one procedure
Hi,
I have a stored procedure that is suposed to return multiple records. I know that for each table that I return I have to add a param to the stored procedure, param with ref cursor type.
I do not know exactly how many tables I have to return, it depends on data from some tables.
Is it possible to return an unknown number of tables? like an array or something ...
Please helpIn order to keep it transparent to the developer, I have to translate exactly the stored procedures from SQL Server to Oracle.Well "exactly" is not something that you are going to achieve. You're talking about two disperate languages. That's like saying you want to translate French to English, but it must stay French.
You obviously want to mimick the existing functionality, but in some cases you're just going to have to bite the bullet and accept that you won't be able to do it totally transparently. In this case, the developers are going to have to make some changes at their end of things too.
To translate the procedures from T-SQL to Oracle was
the easiest and most convenient option to the
developers, so they will not have to write different
code for Oracle and SQL.But they will. Anyone who evaluated the project and determined that the developers wouldn't need to do anything when moving from one platform to another should be sacked for incompetence.
;) -
This is a pretty straightforward question but I'm a bit of a newbie. I'm interested in returning a bunch of data from about 10 or so tables so I can dynamically populate some dropdown lists, etc.
I'd like to create a stored procudure to do this. What is best practice?
Should I make one stored procudure that has 10 Out Ref Cursor Paramaters or break this up into multiple Stored Procedures? Is using the Out Ref Cursors the best way of doing this?
Any help would be much appreciated, Thanks.Having one stored procedure returning 10 REF Cursors would give you much better performance then having 10 stored procedures returning one REF Cursor each.
-
Sending an Email with a cursor that returns multiple fields.
I was investigating about sending emails from apex, and I'd like to know if you can help me, I need to send an Email report with multiple fields, I m using this code :
DECLARE
CURSOR c1 is
select id,gk,creation_date,sr_count,issue_notes,sr_impacted,oldest_creation_date
from gk_report where id = (select max(id) from gk_report);
reg c1%ROWTYPE;
begin
IF (c1%ISOPEN = TRUE) THEN
CLOSE c1;
END IF;
OPEN c1;
FETCH c1 INTO reg;
CLOSE c1;
APEX_MAIL.send(
p_to => '[email protected]',
p_from => '[email protected]',
p_body => 'Hourly GK Log',
p_body_html =>
'GK: '||to_char(reg.gk)||'<br>
CREATION DATE: '||to_char(reg.CREATION_DATE,'DD-MON-YYYY HH24:MI:SS')||'<br>
SR COUNT: '||to_char(reg.SR_COUNT)||'<br>
ISSUE NOTES: '||to_char(reg.ISSUE_NOTES)||'<br>
SRs IMPACTED: '||to_char(reg.SR_IMPACTED)||'<br>
OLDEST CREATION DATE: '||to_char(reg.OLDEST_CREATION_DATE,'DD-MON-YYYY HH24:MI:SS'),
p_SUBJ => 'Hourly GK Log: ' || to_char(reg.CREATION_DATE,'DD-MON-YYYY HH24:MI:SS'),
p_cc => NULL,
p_bcc => NULL ,
p_replyto => NULL
end;
In this code there is a cursor that returns just one field, But what about if the cursor returns multiple fields, How can I insert a Loop into this code.?
Thanks,
Pablo.Hi,
DECLARE
p_collection_name VARCHAR2(9000) := 'Report_collection';
begin
IF (apex_collection.collection_exists(p_collection_name => p_collection_name)) THEN
apex_collection.delete_collection(p_collection_name => p_collection_name);
END IF;
apex_collection.create_collection_from_query(
p_collection_name => 'Report_collection',
p_query => 'SELECT DISTINCT AUD_SR AS SR, C.USER_NAME AS AUDITOR, F.ERROR_NAM , A.AUD_OBSERV AS AUDIT_OBS,D.FEEDBK_OBSERV AS FEEDBACK_OBS , E.ANALYSIS_OBS ,A.AUD_STATUS
FROM AUDIT_PROCESS A, MICC_AT_DATA B, MICC_AT_USER C, FEEDBACK_PROCESS D, MICC_AT_ANALISYS E, MICC_AT_ERROR F
WHERE B.DATA_MONTH = :P27_MONTH AND B.DATA_SR = A.AUD_SR AND C.ID = B.DATA_AUDITOR AND F.ERROR_ID = A.AUD_ERROR AND A.FEEDBACK_COD = D.FEEDBACK_COD AND D.FEEDBK_AGREE = 'N' AND E.COD_ANALYSIS = A.COD_ANALYSIS ORDER BY AUDITOR');
APEX_MAIL.send(
p_to => '[email protected]',
p_from => '[email protected]',
p_body => p_collection_name ,
p_body_html => '',
p_SUBJ => 'hi',
p_cc => NULL,
p_bcc => NULL ,
p_replyto => NULL
END;
Error
ORA-06550: line 18, column 176:
PLS-00103: Encountered the symbol " AND E.COD_ANALYSIS = A.COD_ANALYSIS ORDER BY AUDITOR" when expecting one of the following:
) , * & = - + < / > at in is mod remainder not rem
<> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
The symbol "," was substituted for " AND E.COD_ANALYSIS = A.COD_ANALYSIS ORDER BY AUDITOR" to continue.
1. DECLARE
2. p_collection_name VARCHAR2(9000) := 'Report_collection';
3. begin
I got out the 'N' quotes of the N :
DECLARE
p_collection_name VARCHAR2(9000) := 'Report_collection';
begin
IF (apex_collection.collection_exists(p_collection_name => p_collection_name)) THEN
apex_collection.delete_collection(p_collection_name => p_collection_name);
END IF;
apex_collection.create_collection_from_query(
p_collection_name => 'Report_collection',
p_query => 'SELECT DISTINCT AUD_SR AS SR, C.USER_NAME AS AUDITOR, F.ERROR_NAM , A.AUD_OBSERV AS AUDIT_OBS,D.FEEDBK_OBSERV AS FEEDBACK_OBS , E.ANALYSIS_OBS ,A.AUD_STATUS
FROM AUDIT_PROCESS A, MICC_AT_DATA B, MICC_AT_USER C, FEEDBACK_PROCESS D, MICC_AT_ANALISYS E, MICC_AT_ERROR F
WHERE B.DATA_MONTH = :P27_MONTH AND B.DATA_SR = A.AUD_SR AND C.ID = B.DATA_AUDITOR AND F.ERROR_ID = A.AUD_ERROR AND A.FEEDBACK_COD = D.FEEDBACK_COD AND D.FEEDBK_AGREE = N AND E.COD_ANALYSIS = A.COD_ANALYSIS ORDER BY AUDITOR');
APEX_MAIL.send(
p_to => '[email protected]',
p_from => '[email protected]',
p_body => p_collection_name ,
p_body_html => '',
p_SUBJ => 'hi',
p_cc => NULL,
p_bcc => NULL ,
p_replyto => NULL
END;
Error : ORA-20104: create_collection_from_query Error:ORA-20104: create_collection_from_query ParseErr:ORA-00904: "N": invalid identifier
If you can help me would be great, and if you see another mistake please let me know i have not may reach out the solution about it.
Thanks,
Pablo. -
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. -
Return multiple values from a function to a SELECT statement
I hope I've provided enough information here. If not, just let me know what I'm missing.
I am creating a view that will combine information from a few tables. Most of it is fairly straightforward, but there are a couple of columns in the view that I need to get by running a function within a package. Even this is fairly straightforward (I have a function named action_date in a package called rp, for instance, which I can use to return the date I need via SELECT rp.action_date(sequence_number).
Here's the issue: I actually need to return several bits of information from the same record (not just action_date, but also action_office, action_value, etc.) - a join of the tables won't work here as I'll explain below. I can, of course, run a separate function for each statement but that is obviously inefficient. Within the confines of the view select statement however, I'm not sure how to return each of the values I need.
For instance, right now, I have:
Table1:
sequence_number NUMBER(10),
name VARCHAR(30),
Table2:
Table1_seq NUMBER(10),
action_seq NUMBER(10),
action_date DATE,
action_office VARCHAR(3),
action_value VARCHAR(60),
I can't simply join Table1 and Table2 because I have to do some processing in order to determine which of the matching returned rows I actually need to select. So the package opens a cursor and processes each row until it finds the one that I need.
The following works but is inefficient since all of the calls to the package will return columns from the same record. I just don't know how to return all the values I need into the SELECT statement.
CREATE VIEW all_this_stuff AS
SELECT sequence_number, name,
rp.action_date(sequence_number) action_date,
rp.action_office(sequence_number) action_office,
rp.action_value(sequence_number) action_value
FROM table1
Is there a way to return multiple values into my SELECT statement or am I going about this all wrong?
Any suggestions?
Thanks so much!Hi,
What you want is a Top-N Query , which you can do using the analytic ROW_NUMBER function in a sub-query, like this:
WITH got_rnum AS
SELECT action_seq, action_dt, action_office, action_type, action_value
, ROW_NUMBER () OVER ( ORDER BY action_date
, action_seq
, action_serial
) AS rnum
FROM table2
WHERE action_code = 'AB'
AND action_office LIKE 'E' -- Is this right?
SELECT action_seq, action_dt, action_office, action_type, action_value
FROM got_rnum
WHERE rnum = 1
;As written, this will return (at most) one row.
I suspect you'll really want to get one row for each group , where a group is defined by some value in a table to which you're joining.
In that case, add a PARTITION BY clause to the ROW_NUMBER function.
If you'd post a little sample data (CREATE TABLE and INSERT statements), I could show you exactly how.
Since I don't have your tables, I'll show you using tables in the scott schema.
Here's a view that has data from the scott.dept table and also from scott.emp, but only for the most senior employee in each department (that is, the employee with the earliest hiredate). If there happens to be a tie for the earliest hiredate, then the contender with the lowest empno is chosen.
CREATE OR REPLACE VIEW senior_emp
AS
WITH got_rnum AS
SELECT d.deptno
, d.dname
, e.empno
, e.ename
, e.hiredate
, ROW_NUMBER () OVER ( PARTITION BY d.deptno
ORDER BY e.hiredate
, e.empno
) AS rnum
FROM scott.dept d
JOIN scott.emp e ON d.deptno = e.deptno
SELECT deptno
, dname
, empno
, ename
, hiredate
FROM got_rnum
WHERE rnum = 1
SELECT *
FROM senior_emp
;Output:
. DEPTNO DNAME EMPNO ENAME HIREDATE
10 ACCOUNTING 7782 CLARK 09-JUN-81
20 RESEARCH 7369 SMITH 17-DEC-80
30 SALES 7499 ALLEN 20-FEB-81
By the way, one of the conditions in the query you posted was
action_office LIKE 'E'which is equivalent to
action_office = 'E'(LIKE is always equivalent to = if the string after LIKE doesn't contain any wildcards.)
Did you mean to say that, or did you mean something like this:
action_office LIKE 'E%'instead? -
Return multiple links (href)
Hi,
I am customizing a software application using Stored Procedure and XML to display information on multiple links (a href tag). My scenario is as follows.
I am accepting SP parameters and returning reference cursor for 1 or more records (depending on the condition). I am wondering how I can use multiple link values based on each record unique value (ID etc).
Can I test result of reference cursor using IDE (PL/SQL developer, Oracle sql developer).
My stored procedure works fine without links.
PROCEDURE GetLinkValues (
resultData OUT SYS_REFCURSOR
) AS
BEGIN
OPEN resultData FOR
select
id, name, '<a href GetDetails.dll' a.id || '</a>' as MultipleLinks
from Test
where {Filter Recrods}
END GetLinkValues;
Any help is appreciated.
Thanks
SamThe calling program must set this flag, not your search-help.
On a select-option field, don't press F4 but the yellow arrow right, the multiple line selection screen is displayed, there you press the "multi-selection" box.
Regards -
SQL Command returns multiple records, but I see only one record in report
I work with Crystal Reports XI R2 SP3 and Oracle 10g R2 database.
I have an SQL Command that returns multiple records. Command name is "CommDivisionNames" and it returns column "CommDivisionNames.DIVISION_NAME". When I place this field into report details section of the report, I can see all 10 records returned and this is how it should be. I actually need this field to be placed in the report header section, and when I place the field there, then I see only the first record. I set that field as "can grow = true". When I do "browse field data" for this field, I see that all 10 records are there, but only the first one is displayed in report header section.
I thought that I can place SQL Command field anywhere on the report (page header, footer, details) and that it will always show all records that it returns from the database. Can that be done?
My "main part" of the report returns different set of records, and that's what I have in "report details" section. I need this list of divisions to be in the report header section, so user can see that the report was executed for DivA, DivC, DivE.
Thank you,
Milansharonamt:
Users select divisions from parameter, but the parameter multi values are division_numbers (1,5,10), not division_names. Division_names are visible in parameter_prompt_window as description, but parameter remembers only numbers and I don't know how I can reuse division_names later in formula.
I do join for division_numbers and make them into one string variable and pass to sub-report, but I think that I can only get these division_names by calling an SQL command or calling stored procedure.
If I try to do join({MySQLcommand.DIVISION_NAME}) I get error message "A string array is required here".
Carl:
I'm playing with cross-tab and I can use it to see all division_names in the report-header section. Since I need them in only one column or only one row, I have to edit cross-tab object and turn all unneeded border lines to white to make them look invisible. So, cross-tab could be a solution for my problem here.
Another option could be to re-write my SQL command. Since I've read here that SQL command could be written in the same way as I would write a stored procedure, then I could use a bit more complex code to get all multiple division names from the database table into a local cursor, and then use do-while loop to concatenate them into one string, and then to return that string as one record (like 'DivA, DivB, DivC'), and then it should not be a problem to display only that one record/string in report header. It is my understanding that Crystal Reports can call stored procedure that works with many cursors/recordsets and CR will use only the last recordset from the stored procedure. Do you think it could be done this way?
Thank you,
Milan -
Calling stored procedure and returning multiple resultsets
Hello,
Is it possible to create a procedure that return multiple result sets?
e.g.
procedure GetDataFromTables() is
begin
select * from table_one;
select * from table_two;
end GetDataFromTables;
And I want to call this procedure that returns multiple resultsets (one for table_one and another for table_two)
I have referred to the OCCI sample occiproc.cpp, but I am not sure how to handle multiple resultsets.
Your help is highly appreciated.Thank You,
Got the REF cursor in storedproc.cpp.
But as it is documented, getCursor() gets the REF CURSOR value of an OUT parameter as a ResultSet.
So, is it true that if I have to write a procedure that selects * from 50 tables (50 SQL statements) , I have to set 50 OUT parameters to get the result sets.?
Is there any better way of doing this?
e.g. in DB2, we can open multiple cursors in the procedure body and then get the result set one after another.
CREATE PROCEDURE get_staging_data ()
RESULT SETS 1 <no. of result sets>
LANGUAGE SQL
BEGIN ATOMIC
DECLARE L_SQL varchar(5000);
DECLARE c CURSOR WITH RETURN TO CLIENT FOR L_STMT;
SET L_SQL = '';
SET L_SQL = 'SELECT * FROM ';
SET L_SQL = L_SQL || IN_Tab_Name ;
SET L_SQL = L_SQL || ' WHERE VERIFY_FLAG=''S'' FOR READ ONLY OPTIMIZE FOR 2000 ROWS' ;
PREPARE L_STMT FROM L_SQL;
OPEN c; < can open multiple cursors in the prodedure body>
END -
Stored procedure returning multiple records without using SYS_REFCURSOR
Hello,
I am new to oracle stored procedures, have done stored procs in SQL server in past. I am trying to write single stored proc which will return multiple records. I have the stored proc as below and that is compiled without any errors.
We don't want to use SYS_REFCURSOR as output param b'coz the place from which this proc is gonna call, that system doesn't support SYS_REFCURSOR param.
create or replace
PROCEDURE p_get5500DATA_MB (
IN_plan_ID IN T_5500DATA_QWP.Plan_ID%TYPE,
IN_plan_ID_col OUT T_5500DATA_QWP.Plan_ID%TYPE,
p_SEQNUM OUT T_5500DATA_QWP.SEQNUM%TYPE,
p_HEADER_CD OUT T_5500DATA_QWP.HEADER_CD%TYPE,
p_VALUE1 OUT T_5500DATA_QWP.VALUE1%TYPE,
p_VALUE2 OUT T_5500DATA_QWP.VALUE2%TYPE
) AS
BEGIN
SELECT
Plan_ID,
SEQNUM,
HEADER_CD,
VALUE1,
VALUE2
INTO
IN_plan_ID_col,
p_SEQNUM,
p_HEADER_CD,
p_VALUE1,
p_VALUE2
FROM TRS1DBO.T_5500DATA_QWP
WHERE Plan_ID = IN_plan_ID
ORDER BY SeqNum;
-- EXCEPTION
-- WHEN OTHERS THEN
-- RAISE_APPLICATION_ERROR(-210001, 'Error in fetching data from T_5500DATA_QWP....');
END;
Error:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "TRS1DBO.P_GET5500DATA_MB", line 10
ORA-06512: at line 11
My questions is:
- What would be the best practice for this type of simple stored procedures?
- Is there any alternate or is there anything i can fix in above stored proc which return multiple records?
Thank you,
VimalJust out of curiosity, what are you using for API or driver that doesn't support a ref cursor? Ref cursors are pretty much the defacto standard for passing multiple records out of an Oracle procedure. Oracle's ODP.NET, OLEDB, ODBC, JDBC, OCI, all support ref cursors. Chances are that if the driver you're using doesn't support something as basic/fundamental as a ref cursor, it's probably also not going to support something else either.
You'll most likely want to check with the driver/api vendor on their recommended approach. -
Stored procedure that returns multiple tables
Hello everyone,
I was wondering if there's a way to write a stored procedure that returns multiple result set as in sql server. for example, in sql server, you can write 2 select statements and when loading them in c#, u can get two data tables.
I am not sure having a single ref cursor for each select is the only solution. I might need to return a variable number of tables per procedure call (based on a certain criteria).
Any ideas?
thanks for your timeSure. Ref cursor is the only easier answer for your problem.
satyaki>
satyaki>select * from v$version;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for 32-bit Windows: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
Elapsed: 00:00:01.43
satyaki>
satyaki>create or replace procedure ref_gen_arg(choice in int,b in out sys_refcursor)
2 is
3 str varchar2(500);
4 begin
5 if choice = 1 then
6 str := 'select * from emp';
7 elsif choice = 2 then
8 str := 'select * from dept';
9 end if;
10
11 open b for str;
12 exception
13 when others then
14 dbms_output.put_line(sqlerrm);
15 end;
16 /
Procedure created.
Elapsed: 00:00:04.38
satyaki>
satyaki>
satyaki>declare
2 rec_x emp%rowtype;
3 rec_y dept%rowtype;
4 w sys_refcursor;
5 begin
6 dbms_output.enable(1000000);
7 ref_gen_arg(1,w);
8 loop
9 fetch w into rec_x;
10 exit when w%notfound;
11 dbms_output.put_line('Employee No: '||rec_x.empno||' - '||
12 'Name: '||rec_x.ename||' - '||
13 'Job: '||rec_x.job||' - '||
14 'Manager: '||rec_x.mgr||' - '||
15 'Joining Date: '||rec_x.hiredate||' - '||
16 'Salary: '||rec_x.sal||' - '||
17 'Commission: '||rec_x.comm||' - '||
18 'Department No: '||rec_x.deptno);
19 end loop;
20 close w;
21
22 ref_gen_arg(2,w);
23 loop
24 fetch w into rec_y;
25 exit when w%notfound;
26 dbms_output.put_line('Department No: '||rec_y.deptno||' - '||
27 'Name: '||rec_y.dname||' - '||
28 'Location: '||rec_y.loc);
29 end loop;
30 close w;
31 exception
32 when others then
33 dbms_output.put_line(sqlerrm);
34 end;
35 /
Employee No: 9999 - Name: SATYAKI - Job: SLS - Manager: 7698 - Joining Date: 02-NOV-08 - Salary: 55000 - Commission: 3455 - Department No: 10
Employee No: 7777 - Name: SOURAV - Job: SLS - Manager: - Joining Date: 14-SEP-08 - Salary: 45000 - Commission: 3400 - Department No: 10
Employee No: 7521 - Name: WARD - Job: SALESMAN - Manager: 7698 - Joining Date: 22-FEB-81 - Salary: 1250 - Commission: 500 - Department No: 30
Employee No: 7566 - Name: JONES - Job: MANAGER - Manager: 7839 - Joining Date: 02-APR-81 - Salary: 2975 - Commission: - Department No: 20
Employee No: 7654 - Name: MARTIN - Job: SALESMAN - Manager: 7698 - Joining Date: 28-SEP-81 - Salary: 1250 - Commission: 1400 - Department No: 30
Employee No: 7698 - Name: BLAKE - Job: MANAGER - Manager: 7839 - Joining Date: 01-MAY-81 - Salary: 2850 - Commission: - Department No: 30
Employee No: 7782 - Name: CLARK - Job: MANAGER - Manager: 7839 - Joining Date: 09-JUN-81 - Salary: 4450 - Commission: - Department No: 10
Employee No: 7788 - Name: SCOTT - Job: ANALYST - Manager: 7566 - Joining Date: 19-APR-87 - Salary: 3000 - Commission: - Department No: 20
Employee No: 7839 - Name: KING - Job: PRESIDENT - Manager: - Joining Date: 17-NOV-81 - Salary: 7000 - Commission: - Department No: 10
Employee No: 7844 - Name: TURNER - Job: SALESMAN - Manager: 7698 - Joining Date: 08-SEP-81 - Salary: 1500 - Commission: 0 - Department No: 30
Employee No: 7876 - Name: ADAMS - Job: CLERK - Manager: 7788 - Joining Date: 23-MAY-87 - Salary: 1100 - Commission: - Department No: 20
Employee No: 7900 - Name: JAMES - Job: CLERK - Manager: 7698 - Joining Date: 03-DEC-81 - Salary: 950 - Commission: - Department No: 30
Employee No: 7902 - Name: FORD - Job: ANALYST - Manager: 7566 - Joining Date: 03-DEC-81 - Salary: 3000 - Commission: - Department No: 20
Department No: 10 - Name: ACCOUNTING - Location: NEW YORK
Department No: 20 - Name: RESEARCH - Location: DALLAS
Department No: 30 - Name: SALES - Location: CHICAGO
Department No: 40 - Name: LOGISTICS - Location: CHICAGO
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.73
satyaki>Regards.
Satyaki De. -
Multiple cursors and xmlforest
This is my first time working with XML in PLSQL. I'm trying to parse values from a plsql procedure into a Word document using XML.
My procedure looks something like:
CREATE OR REPLACE PROCEDURE GET_XML_FA
(PP_ID IN VARCHAR2,
PP_PERIOD IN VARCHAR2
IS
result CLOB;
result1 clob;
CURSOR my_cur_1 IS
SELECT XMLForest(to_char(sysdate,'fmMonth DD, YYYY') "sysdate",
INITCAP(TRIM(p.p_name))||' ('||p.p_id||')' "person",
p_period "period",
(SELECT DISTINCT INITCAP(TO_CHAR(det.detail_date,'fmMonth DD,YYYY'))
FROM details_table det, abc_table abc, people p
WHERE det.fa_seq_num = abc.fa_seq_num
AND p.p_seq_num = abc.p_seq_num
AND p.p_id LIKE pp_id
AND REPLACE((TO_CHAR(abc.from_period,'fmMonth YYYY'))||'-'||INITCAP(TO_CHAR(abc.thru_period,'fmMonth YYYY')),' ','') LIKE pp_period
AND det.dtl_code = 'bill'
) "bill_date"
) xrow
FROM PEOPLE p
WHERE p.p_id = PP_ID;
CURSOR my_cur_2 IS
select XMLForest
(Initcap(to_char(det.detail_date,'fmMonth DD,YYYY')) "payment_date",
det.detail_amt "payment_amt") xrow
from details_table det, abc_table abc, people p
where det.fa_seq_num = abc.fa_seq_num
and p.p_seq_num = abc.p_seq_num
and p.p_id = pp_id
AND replace((TO_CHAR(abc.from_period,'fmMonth YYYY'))||'-'||INITCAP(TO_CHAR(abc.thru_period,'fmMonth YYYY')),' ','') like pp_period
and det.dtl_code = 'payment';
BEGIN
htp.print('<?xml version="1.0" ?>');
htp.print('<DOCUMENT DOCNAME="My_Letter'||pp_id||'_'||pp_period||'.doc" DESTINATION="'||get_const_value('FA_TRACK_DIR')||'" SOURCE="'||get_const_value('DOCBUILDER_DIR')||'" LOGFILE="'||get_const_value('FA_TRACK_DIR')||'">');
htp.print('<NOTE FNAME="My_Letter.doc">');
for my_rec_1 in my_cur_1 loop
result := my_rec_1.xrow.getClobVal();
htp.print(result);
end loop;
for my_rec_2 in my_cur_2 loop
result1 := my_rec_2.xrow.getClobVal();
htp.print(result1);
end loop;
htp.print('</NOTE>');
htp.print('</DOCUMENT>');
END;my_cur_1 returns a single row of data whereas my_cur_2 returns multiple rows. However, while parsing values into my word document, my_cur_2 passes only the first row and doesn't pass the remaining rows.
I'm not able to understand what I am doing wrong. Can anyone help?
Note: get_const_value is our custom function that determines directory path based on server.
Let me know if more details are required.Hi Scorpio,
my point was very simple. XMLAgg function pre-aggregates the result elements in one row. See example below with simulated dual data.
select XMLForest
(rownum "payment_date", 'a' "payment_amt" ) xrow
from dual connect by level <= 2
XROW
<payment_date>1</payment_date><payment_amt>a</payment_amt>
<payment_date>2</payment_date><payment_amt>a</payment_amt>
2 rows selected
select XMLAgg(XMLForest
(rownum "payment_date", 'a' "payment_amt" )) xrow
from dual connect by level <= 2
XROW
<payment_date>1</payment_date><payment_amt>a</payment_amt><payment_date>2</payment_date><payment_amt>a</payment_amt>
1 rows selected
If this doesn't help I'd suggest - simplify the example (consider only the cursor causing problem, use the dual table etc) and post the Oracle version.
Regards,
Jaromir -
Using XI - RFC table and an Oracle stored procedure that returns a cursor.
I need to create an interface using XI between an RFC table and an Oracle stored procedure that returns a cursor. We are on oarcle 9.2 and SP12.
My stored procedure looks something like this:
CREATE OR REPLACE
PROCEDURE testproc_xi2 (p_recordset1 OUT SYS_REFCURSOR,
in_quoteid IN varchar2 )
AS
BEGIN
OPEN p_recordset1 FOR
SELECT q.quote_id,
q.modified_by,
q.quote_status,
q.total_cost
FROM quote q
WHERE q.quote_id = in_quoteid
AND q.total_cost > 0 ;
END testproc_xi2 ;
My RFC has table and one import parameter .
I wanted to know how to create the data type for the ref cursor? and also for the table type in the RFC?
CAN XI handle multi rows coming from a Stored procedure? Are there any other alternative methods if this is not supported?Any pointers to this would be helpful.
I have called a Oracle SP from an RFC before, but that interface had one input parameter going to the stored procedure from the RFC and about 6 o/p parameters coming from the Stored procedure. This works fine.
Thanks for the help.
MalaMala,
i dont think there is anything called an rfc table...RFC stands for remote function call. That in essence would imply you need a rfc to jdbc connection.
yes XI can handle multiple rows cooming from the the stored procedure if you have them mapped appropriately.
Now as to how to create the data type within xi , you need to know what fields are going to be returned and whether they are nested and then just create them as you would for an xml
for ex
<Details>
<FirstName>
<LastName>
</Details>
that in xi would be smthing like
Details type of data occurence
FirstName type of data occurence
LastName type of data occurence.
Hope that helps.
If it does dont forget the points..:-) -
Select function that returns multiple columns.
Currently I have a function that will return 1 column and I can use that in a select statement. What I need is to return multiple columns from a table. In the function I have I return the street address from a table that holds information about dealers, I need to be able to also return the columns that contain the city, state, and zip code so it can be used in an sql select statement. How would I do this?
My function:
FUNCTION GET_ADDRESS(dealer_id IN number)
RETURN tbl_dealer_info.c_street%TYPE AS
v_rc tbl_dealer_info.c_street%TYPE;
CURSOR get_dealer_cur IS
SELECT c_street
FROM tbl_dealer_info
WHERE n_dealer_id = dealer_id;
BEGIN
v_rc := NULL;
OPEN get_dealer_cur;
FETCH get_dealer_cur INTO v_rc;
IF get_dealer_cur%NOTFOUND THEN
NULL;
END IF;
CLOSE get_dealer_cur;
RETURN v_rc;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END GET_ADDRESS;
My select statement:
select GET_ADDRESS(1205) Street, DI.n_inactive_flag, DI.n_onhold_flag
from tbl_dealer_info DI
where DI.n_dealer_id = 1205;
I would like to be able to select the street, city, state, and zip all in this select statement from the GET_ADDRESS function.
Thanks,
Lori Neirynck"The reality is you've probably already put your blinders on and you won't learn the best approach to solving your problem because you insist on asking a courtroom style question (just "yes" or "no" please)."
Actually, I asked this question because I was looking for the best approach to my problem. I have an SQL statement that correctly selects everything it needs to from all 15 tables. The thing of it is it is very long and difficult to read. I wanted to try using functions so that I could change 12 AND/OR statements into 3 IF statements so everything is easier to read. I have received a couple of different ways to do this from other forums that assumed I knew what I was doing. I have gotten one to work, the other I'm still working on. I'll post the one that worked for others that want to know.
SQL> insert into dealer_info values (1,'Me','13 success street', 'Wonder Town','Wonderland','1313');
SQL> commit;
SQL> create type t_address as object (
2 street varchar2(100),
3 city varchar2(30),
4 state varchar2(30),
5 zip varchar2(10));
6 /
Type created.
SQL> create or replace function get_address (p_id number) return t_address
2 is
3 ret t_address := t_address(null,null,null,null);
4 rec dealer_info%rowtype;
5 begin
6 select * into rec from dealer_info where id=p_id;
7 ret.street := rec.street;
8 ret.city := rec.city;
9 ret.state := rec.state;
10 ret.zip := rec.zip;
11 return ret;
12 end;
13 /
Function created.
SQL> col name format a10
SQL> col address format a70
SQL> select name, get_address(id) address from dealer_info;
NAME ADDRESS(STREET, CITY, STATE, ZIP)
Me T_ADDRESS('13 success street', 'Wonder Town', 'Wonderland', '1313')
1 row selected.
-Lori -
PLSQL web service returning multiple records
Hello,
I am trying to create a web service using oracle 11g which should be able to return multiple records.
Based on hints and code samples found on the internet here is my code :
CREATE OR REPLACE TYPE test_rec is OBJECT (
s_nume_adre NUMBER ,
c_eta_civi VARCHAR2(4 BYTE),
l_nom1_comp VARCHAR2(40 BYTE),
l_nom2_comp VARCHAR2(40 BYTE),
l_nom3_comp VARCHAR2(40 BYTE),
l_pren_comp VARCHAR2(30 BYTE),
d_date_nais DATE);
CREATE OR REPLACE TYPE test_array AS TABLE OF test_rec;
CREATE OR REPLACE PACKAGE test_pkg AS
function get_rows(snume_adre in number) return test_array;
END;
CREATE OR REPLACE PACKAGE BODY test_pkg AS
function get_rows(snume_adre in number) return test_array is
v_rtn test_array := test_array(null);
v_first boolean := true;
cursor c_get_rows(snume_adre in number) is
SELECT a.s_nume_adre,
nvl(a.c_eta_civi, '') c_eta_civi,
nvl(a.l_nom1_comp, '') l_nom1_comp,
nvl(a.l_nom2_comp, '') l_nom2_comp,
nvl(a.l_nom3_comp, '') l_nom3_comp,
nvl(a.l_pren_comp, '') l_pren_comp,
nvl(a.d_date_nais, to_date('01.01.1900', 'dd.mm.yyyy')) d_date_nais
FROM bro.z45 a
where a.s_nume_adre = snume_adre or snume_adre is null;
begin
for rec in c_get_rows(snume_adre) loop
if v_first then
v_first := false;
else
v_rtn.extend;
end if;
v_rtn(v_rtn.last) := test_rec(rec.s_nume_adre, rec.c_eta_civi, rec.l_nom1_comp, rec.l_nom2_comp,
rec.l_nom3_comp, rec.l_pren_comp, rec.d_date_nais);
end loop;
return v_rtn;
end;
END;
--select * from table (test_pkg.get_rows(null));
I am able to retrieve the data using the select.
However when I try to access its wsdl I get an error :
<soap:Envelope>
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Error processing input</faultstring>
<detail>
<OracleErrors></OracleErrors>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
If I comment the function call in the package declaration I get a "correct" wsdl :
<definitions name="GET_ROWS" targetNamespace="http://xmlns.oracle.com/orawsv/TEST/TEST_PKG/GET_ROWS" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://xmlns.oracle.com/orawsv/TEST/TEST_PKG/GET_ROWS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema targetNamespace="http://xmlns.oracle.com/orawsv/TEST/TEST_PKG/GET_ROWS" elementFormDefault="qualified">
<xsd:element name="GET_ROWSInput">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
<xsd:element name="GET_ROWSOutput">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="GET_ROWSInputMessage">
<part name="parameters" element="tns:GET_ROWSInput"/>
</message>
<message name="GET_ROWSOutputMessage">
<part name="parameters" element="tns:GET_ROWSOutput"/>
</message>
<portType name="GET_ROWSPortType">
<operation name="GET_ROWS">
<input message="tns:GET_ROWSInputMessage"/>
<output message="tns:GET_ROWSOutputMessage"/>
</operation>
</portType>
<binding name="GET_ROWSBinding" type="tns:GET_ROWSPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GET_ROWS">
<soap:operation soapAction="GET_ROWS"/>
<input>
<soap:body parts="parameters" use="literal"/>
</input>
<output>
<soap:body parts="parameters" use="literal"/>
</output>
</operation>
</binding>
<service name="GET_ROWSService">
<documentation>Oracle Web Service</documentation>
<port name="GET_ROWSPort" binding="tns:GET_ROWSBinding">
<soap:address location="http://server.domain.ch:8080/orawsv/TEST/TEST_PKG/GET_ROWS"/>
</port>
</service>
</definitions>
Any hint as how to create and access pl sql web service returning multiple rows?
I don't use java and don't have access to tools like JDeveloper.
Thanks!The actual issue is that collection types are not supported for return parameters.
The solution is to wrap the collection into another object.
Here's a working example based on your settings :
CREATE OR REPLACE TYPE test_rec is OBJECT (
empno number(4)
, ename varchar2(10)
, hiredate date
CREATE OR REPLACE TYPE test_array AS TABLE OF test_rec;
CREATE OR REPLACE TYPE test_array_wrapper is OBJECT ( arr test_array );
CREATE OR REPLACE PACKAGE test_pkg AS
function get_rows(p_deptno in number) return test_array_wrapper;
END;
CREATE OR REPLACE PACKAGE BODY test_pkg AS
function get_rows(p_deptno in number) return test_array_wrapper is
results test_array;
begin
select test_rec(empno, ename, hiredate)
bulk collect into results
from scott.emp
where deptno = p_deptno;
return test_array_wrapper(results);
end;
END;
The wsdl is then generated correctly :
SQL> select httpuritype('http://DEV:dev@localhost:8080/orawsv/DEV/TEST_PKG/GET_ROWS?wsdl').getxml() from dual;
HTTPURITYPE('HTTP://DEV:DEV@LOCALHOST:8080/ORAWSV/DEV/TEST_PKG/GET_ROWS?WSDL').GETXML()
<definitions name="GET_ROWS" targetNamespace="http://xmlns.oracle.com/orawsv/DEV/TEST_PKG/GET_ROWS" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://xmlns.oracle.com/orawsv/DEV/TEST_PKG/GET_
ROWS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema targetNamespace="http://xmlns.oracle.com/orawsv/DEV/TEST_PKG/GET_ROWS" elementFormDefault="qualified">
<xsd:element name="CTEST_ARRAY_WRAPPER-GET_ROWSInput">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="P_DEPTNO-NUMBER-IN" type="xsd:double"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GET_ROWSOutput">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="RETURN" type="tns:TEST_ARRAY_WRAPPERType"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="TEST_ARRAY_WRAPPERType">
<xsd:sequence>
<xsd:element name="TEST_ARRAY_WRAPPER">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ARR">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="TEST_REC" type="tns:TEST_REC_IntType" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TEST_REC_IntType">
<xsd:sequence>
<xsd:element name="EMPNO" type="xsd:double"/>
<xsd:element name="ENAME">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="10"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="HIREDATE" type="xsd:date"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</types>
<message name="GET_ROWSInputMessage">
<part name="parameters" element="tns:CTEST_ARRAY_WRAPPER-GET_ROWSInput"/>
</message>
<message name="GET_ROWSOutputMessage">
<part name="parameters" element="tns:GET_ROWSOutput"/>
</message>
<portType name="GET_ROWSPortType">
<operation name="GET_ROWS">
<input message="tns:GET_ROWSInputMessage"/>
<output message="tns:GET_ROWSOutputMessage"/>
</operation>
</portType>
<binding name="GET_ROWSBinding" type="tns:GET_ROWSPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GET_ROWS">
<soap:operation soapAction="GET_ROWS"/>
<input>
<soap:body parts="parameters" use="literal"/>
</input>
<output>
<soap:body parts="parameters" use="literal"/>
</output>
</operation>
</binding>
<service name="GET_ROWSService">
<documentation>Oracle Web Service</documentation>
<port name="GET_ROWSPort" binding="tns:GET_ROWSBinding">
<soap:address location="http://localhost:8080/orawsv/DEV/TEST_PKG/GET_ROWS"/>
</port>
</service>
</definitions>
Maybe you are looking for
-
Transfering ppurchased music to other computer
i purchased several albums from itune store to my laptop. and burnd audio CD to import to tower computer. when put CD in tower, it's said "song names not be found online." and playlist information did not show, shows only track number. why music info
-
SAP_BS_FND addon was not selected as part of the stack xml
We are in a process of upgrading production system (SAP NW 7.0) to EhP1, we have components SEM-BW,FINBASIS installed in the Netweaver system, we have added the system under Netweaver We have generated the stack xml file using solution manager MoPZ b
-
IPhotos - Shared iCloud vs My Photo Stream????
In my iPhoto I have a "RECENT - My Photo Stream" item that contains 194 photos and a "SHARED iCloud" item that contains 402 photos. Some of these photos in the two "albums" are the same. Question: What is the difference between "My Photo Stream" and
-
Bluetooth on MacBook Pro not working!
How can I fix my MacBook Pro 15" Bluetooth connection? When paired with wireless mouse and/or wireless keyboard, the signal doesn't hold. Most of the time I can't get it to recognize them. How do I fix this?
-
How to break up a huge XML file and generate serialized JSP pages
I have a huge xml file, with about 100 <item> nodes. I want to process this xml file with pagination and generate jsp pages. For example: Display items from 0 to 9 on page 1 page1.jsp , 10 to 19 on page2.jsp, and so on... Is it possible to generate J