Using Implicit REF Cursor in Oracle DB 12c
For those interested in using ODP.NET implicit REF Cursors in Oracle DB 12c, the syntax is different from what was available in Oracle 11g. Here's a 12c-specific example:
=======================
Create or Replace PROCEDURE GetEmpAndDept
AS
EMPS sys_refcursor;
DEPTS sys_refcursor;
BEGIN
OPEN EMPS for SELECT empno, ename from emp;
dbms_sql.return_result(EMPS);
OPEN DEPTS for SELECT deptno, dname from dept;
dbms_sql.return_result(DEPTS);
END;
=======================
// C#
OracleConnection conn = new OracleConnection("User Id=scott; Password=tiger);
conn.Open(); // Open the connection to the database
// Create the command object for executing cmdTxt
OracleCommand cmd = new OracleCommand("GetEmpAndDept", conn);
cmd.CommandType = CommandType.StoredProcedure;
OracleDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
Console.WriteLine("{0}\t{1}", rdr.GetInt32(0), rdr.GetString(1) );
rdr.NextResult();
while(rdr.Read())
Console.WriteLine("{0}\t{1}", rdr.GetInt32(0), rdr.GetString(1) );
i am using Oracle.ManagedDataAccess.dll v4.121.1.0
Oracle Data Base 12c
Visual Studio 2012 .net framework 4
But if I use Unmanaged Dll I get implicit results in my .net application.
Similar Messages
-
Using plsql table and ref cursor in oracle forms 10g
Hi all,
Can anyone give me an example of a scenario where we need to create a form manually based on a database stored procedures.
And in that procedure i have created a pl/sql table and a ref cursor in data base level.
CREATE OR REPLACE PACKAGE SCOTT.BONUS_PKG IS TYPE bonus_rec
IS RECORD(
empno bonus_EMP.empno%TYPE,
ename bonus_EMP.ename%TYPE,
job bonus_EMP.job%TYPE,
sal bonus_EMP.sal%TYPE,
comm bonus_EMP.comm%TYPE);
TYPE b_cursor IS REF CURSOR RETURN bonus_rec;
TYPE bontab IS TABLE OF bonus_rec INDEX BY BINARY_INTEGER;
PROCEDURE bonus_refcur(bonus_data IN OUT b_cursor);
PROCEDURE bonus_query(bonus_data IN OUT bontab);
END bonus_pkg;
CREATE OR REPLACE PACKAGE BODY SCOTT.BONUS_PKG IS
PROCEDURE bonus_query(bonus_data IN OUT bontab) IS
ii NUMBER;
CURSOR bonselect IS
SELECT empno, ename, job, sal, comm FROM bonus_EMP ORDER BY empno;
BEGIN
OPEN bonselect;
ii := 1;
LOOP
FETCH bonselect INTO
bonus_data( ii ).empno,
bonus_data( ii ).ename,
bonus_data( ii ).job,
bonus_data( ii ).sal,
bonus_data( ii ).comm;
EXIT WHEN bonselect%NOTFOUND;
ii := ii + 1;
END LOOP;
END bonus_query;
PROCEDURE bonus_refcur(bonus_data IN OUT b_cursor) IS
BEGIN
OPEN bonus_data FOR SELECT empno, ename, job, sal, comm FROM bonus_EMP ORDER BY empno;
END bonus_refcur;
END bonus_pkg;
i want to populate the data in forms manually not using forms data block wizard and programmatically.
please reply...Can anyone give me an example of a scenario where we need to create a form manually based on a database stored procedures.Typically, you would use a procedure based block when you have a collection of data from multiple tables presented in a Form and your user needs to be able to update the information displayed.
From your code example, it looks like you are using Oracle Support document "Basing a Block on a Stored Procedure - Sample Code [ID 66887.1]". If this is the case, keep following the document - it walks you through all of the steps. There is no need to Manually configure things that the Data Block Wizard will perform for you!
i want to populate the data in forms manually not using forms data block wizard and programmatically. Why? Let the Data Block Wizard take care of configuring your block based on a procedure for you. There is no need to manually loop through the data! I've actually done what you are attempting and it was more work than was needed. Let Forms do the work for you. :)
If you absolutely must do things manually, I recommend you use the PROCEDURE bonus_query(bonus_data IN OUT bontab) instead of the bonus_refcur(bonus_data IN OUT b_cursor) . Then, in your code create a variable of type BONTAB and then call the bonus_query procedure. Then it is a simple case of looping through the table of records returned by the bonus_query procedure. For example:
DECLARE
t_bonus bonus_pkb.bontab;
BEGIN
bonus_pkg.bonus_query(t_bonus);
FOR i in 1 .. t_bonus.count LOOP
:YOUR_BLOCK.EMPLOYEE_NUMBER := t_bonus(i).empno;
:YOUR_BLOCK.EMPLOYEE_NAME := t_bonus(i).ename;
:YOUR_BLOCK.EMPLOYEE_JOB := t_bonus(i).job;
:YOUR_BLOCK.EMPLOYEE_SALARY := t_bonus(i).sal;
:YOUR_BLOCK.EMPLOYEE_COMMISSION := t_bonus(i).comm;
END LOOP;
END;This code sample demonstrates the basics, but as it is sample code - you will have to adapt it to your situation.
Also, I strongly recommend you look at the article InoL listed. This is a very comprehensive discussion on REF CURSORs. If you are set on using a procedure based data source - it is more efficient to pass the table of records back to your form than it is to pass a ref cursor. Using a ref cursor, you might as well just using a standard named cursor and loop through your named cursor. The effect is the same (one row returned at a time creating lots of network traffic). Using the table of records is more efficient because the entire data set is returned so network traffic is reduced.
Hope this helps,
Craig B-)
If someone's response is helpful or correct, please mark it accordingly. -
Problem declaring and using a REF CURSOR
I'm having a real problem using a REF CURSOR type
Here's the DECLARE and the start of the BEGIN I've so far developed.
DECLARE
TYPE r1 IS RECORD (
szvcapc_pidm szvcapc.szvcapc_pidm%TYPE,
szvcapc_term_code szvcapc.szvcapc_term_code%TYPE,
szvcapc_request_no szvcapc.szvcapc_request_no%TYPE);
szvcapc_rec r1;
TYPE cursor_1 IS REF CURSOR RETURN r1;
szvcapc_cv cursor_1;
TYPE r2 IS RECORD (
stvests_code stvests.stvests_code%TYPE
stvests_rec r2;
TYPE cursor_2 IS REF CURSOR RETURN stvests_rec;
stvests_cv cursor_2;
BEGIN
OPEN szvcapc_cv FOR
SELECT szvcapc_pidm, szvcapc_term_code, szvcapc_request_no
FROM szvcapc
WHERE szvcapc_passed_ind = 'Y'
AND szvcapc_award_credits = 'N';
LOOP
FETCH szvcapc_cv INTO szvcapc_rec;
EXIT WHEN szvcapc_cv%NOTFOUND;
END LOOP;
OPEN stvests_cv FOR
SELECT stvests_code
FROM stvests
WHERE stvests_eff_headcount = 'Y';
LOOP
FETCH stvests_cv INTO stvests_rec;
EXIT WHEN stvests_cv%NOTFOUND;
END LOOP;
SELECT *
FROM (
<snip>
INNER JOIN stvests_rec
ON SFBETRM.SFBETRM_ESTS_CODE = stvests_rec.STVESTS_CODE
<snip>
I later try to use the stvests_rec and szvcapc_rec in the main SELECT statement it doesn't recognise stvests_rec and szvcapc_rec as a "Table or View".
I have to use a REF CURSOR as this code is ultimately for use in Oracle Reports.
What am I doing wrong?> The reason I'm trying to use a REF CURSOR is that I was told that you
couldn't use CURSORs in Oracle Reports.
That does not change anything ito what happens on the Oracle server side. A cursor is a cursor is a cursor.
Every single SQL winds up as a cursor. Each cursor has a reference handle to access and use. HOW this handle is used in the language differs. But that is a language issue and not an Oracle RDBMS issue.
For example. An EXECUTE IMMEDIATE in PL/SQL creates a cursor handle and destroys it after use - automatically. An implicit cursor works the same. An explicit cursor you have the handle fetch from it and close from it when done.
A ref cursor is simply a handle that can be returned to an external client - allowing that application to use the handle to fetch the rows.
Do not think that a ref cursor is any different from the RDBMS side than any other cursor. The RDBMS does not know the difference. Does not care and nor should it.
> I'm trying to reduce the hits on the database from nested selects by
removing the dataset from the main SELECT statement and performing it only
once outside and then referencing this previously collected dataset inside the
main SELECT statement.
Good stuff that you are considering SQL performance. But you need to make sure that you
a) identify the performance inhibitor issue correctly
b) address this issue correctly
And you need to do that within SQL. Not PL/SQL. PL/SQL will always be slower at crunching data than SQL. For example, wanting to cache the data somehow to reduce the read overhead - that is exactly what the DB buffer cache does. It caches data. That is also exactly what the CBO will attempt - reduce the amount of data that needs to be read and processed.
Not saying that the RDBMS can do it all. It needs help from you - in the form of a SQL that instructs it to process only the minimum amount of data required to get the required results. In the form of a sound physical design that provides optimal usage of data storage and access (like indexing, partitioning, clustering, etc).
Bottom line - you cannot use a REF CURSOR to make a SQL go faster. A REF CURSOR is simply a cursor in the SQL Engine. A cursor is nothing but the "compiled-and-executable" code of a SQL "source program". -
Hi,
Can some one help.
I am getting string more than 32767 char so I want to use CLOB but I am unable to use in ref Cursor.
CREATE OR REPLACE PROCEDURE PM.PROC_CURSOR_BTDCS (P_QUERY IN varchar2, P_batchid out Number) AS
P VARCHAR2(32767);
P_CURSOR_QUERY SYS_REFCURSOR;
X_JOBID varchar2(30);
X_BATCHID VARCHAR2(1000);
X_CREF VARCHAR2(10000);
X_CLIENTREF VARCHAR2(10000);
X_CLIENTID NUMBER;
X_USERID NUMBER;
X_RDATE varchar2(40);
X_DDATE varchar2(40);
X_STAGE NUMBER;
X_DIFF NUMBER;
X_CLIENTDUEDATE varchar2(40);
X_ASSETID NUMBER;
X_MODEID NUMBER;
p_o_error VARCHAR2(100);
p_o_status NUMBER;
BEGIN
P := 'SELECT DISTINCT JOBID,CLID,USERID,STAGE,
GET_CSV_DATA(CURSOR (SELECT CREF FROM ('|| P_QUERY ||') WHERE jobid =A.JOBID AND CLID=A.CLID AND USERID=A.USERID AND RDATE=A.RDATE AND DDATE=A.DDATE AND STAGE=A.STAGE AND ASSETID=A.ASSETID AND CLDATE=A.CLDATE AND DIFF=A.DIFF)) C_CREF,
GET_CSV_DATA(CURSOR (SELECT BATCHID FROM ('|| P_QUERY ||') WHERE jobid =A.JOBID AND CLID=A.CLID AND USERID=A.USERID AND RDATE=A.RDATE AND DDATE=A.DDATE AND STAGE=A.STAGE AND ASSETID=A.ASSETID AND CLDATE=A.CLDATE AND DIFF=A.DIFF)) C_BATCH,
GET_CSV_DATA(CURSOR (SELECT Crefname FROM ('|| P_QUERY ||') WHERE jobid =A.JOBID AND CLID=A.CLID AND USERID=A.USERID AND RDATE=A.RDATE AND DDATE=A.DDATE AND STAGE=A.STAGE AND ASSETID=A.ASSETID AND CLDATE=A.CLDATE AND DIFF=A.DIFF)) C_CLIENTREF
,DIFF,cldate,ASSETID
,RDATE,DDATE,MODEID
FROM('||P_QUERY||') A';
--INSERT INTO FROG VALUES(P,sysdate);
OPEN P_CURSOR_QUERY FOR P;
LOOP
FETCH P_CURSOR_QUERY INTO X_JOBID
,X_CLIENTID,X_USERID,X_STAGE,
X_CREF,X_BATCHID,X_CLIENTREF,X_DIFF,
X_CLIENTDUEDATE,
X_assetid,X_RDATE,X_DDATE,X_MODEID;
EXIT WHEN P_CURSOR_QUERY%NOTFOUND;
-- INSERT INTO FROG VALUES (X_CREF);
Proc_batchchangestage_upd (X_JOBID,X_BATCHID,X_CREF,X_CLIENTREF,X_userid,X_clientid,X_RDATE,
X_DDATE,
X_stage,
X_CLIENTDUEDATE,
X_diff,
X_assetid,X_MODEID,p_batchid,
p_o_error,
p_o_status);
END LOOP;
CLOSE P_CURSOR_QUERY;
COMMIT;
END;It would be helpful to indicate the error you're getting and the line where you're getting the error.
I will assume that your goal is to construct a SQL query > 32k, store that query in p, and open a cursor using p. In order to do that, you'd have to use the DBMS_SQL package, which is going to complicate your life rather significantly.
That said, it's far from obvious to my why the SQL statement needs to exceed 32k. At a minimum, concatentaing P_QUERY three times would seem unnecessary. If the text of P_QUERY exceeds 10,000 characters, I would really tend to suspect that you've done something wrong there and would benefit from simplifying the query or at least using a couple views.
Justin -
I have a function that I created and am trying to use it to output data using a ref cursor. My function call is
declare
ret_cursor crsiweb.types.cursorType;
type output_rec_type is record(
location varchar2(100),
client varchar2(100),
number_in long,
number_out long,
total_cost varchar2(100),
total_charge varchar2(100),
net varchar2(100),
average varchar2(100)
output output_rec_type;
begin
ret_cursor := all_db.net_profit.net_profit(to_date(:P1_Date_Chart,'DD-Mon-RR'));
fetch ret_cursor into output;
dbms_output.put_line('Location' || ',' || 'Company'|| ',' || 'In' ||
','|| 'Out'|| ',' || 'Cost'|| ',' || 'Charge'
|| ',' || 'Net' || ',' || '30 Day Average');
while ret_cursor%FOUND loop
dbms_output.put_line(output.location || ',' || output.client || ',' || output.number_in ||
','|| output.number_out || ',' || output.total_cost || ',' || output.total_charge
|| ',' || output.net || ',' || output.average);
fetch ret_cursor into output;
end loop;
close ret_cursor;
end;
i have it as a PL/SQL Procedure (anonymous block) in a region. When executed I get the following error:
"ORA-06550: line 15, column 25: PLS-00904: insufficient privilege to access object ALL_DB.NET_PROFIT ORA-06550: line 15, column 4: PL/SQL: Statement ignored"
The function is as follows: ( I created the function in OEM)
create or replace procedure all_db.net_profit.net_profit
as
function net_profit(sdate IN date) return crsiweb.types.cursortype as
ret_cursor crsiweb.types.cursortype;
begin
open ret_cursor for select 'a_chase' "Location",a."Client" "Client", sum(nvl(b."In",0)) "In", sum(nvl(a."Out",0)) "Out", to_char(sum(nvl(a."Cost",0)
+ nvl(b."Cost",0)),'FM$9999999990.00PR') "Cost",
to_char(sum(nvl(a."Charge",0) + nvl(b."Charge",0)),'FM$9999999990.00PR') "Charge", to_char(sum(nvl(a."Net",0)
+ nvl(b."Net",0)),'FM$9999999990.00PR') "Net",
to_char(sum(nvl("Average",0)),'FM$9999999990.00PR') "30 Day Average"
-- Get Out, Cost, Net by date_out
from (select client_name "Client", count(date_sent) "Out",
round(sum(nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0)),2)"Cost",
round(sum(nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)),2) "Charge",
round(sum((nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)) - (nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0))),2) "Net"
from a_chase.jim a
inner join a_chase.clients b
on a.clientid = b.clientid
where trunc(date_sent) = trunc(sdate)
group by client_name) a
--Get In, Cost, Net by date_In
left outer join (select client_name "Client", count(date_in) "In",
round(sum(nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0)),2)"Cost",
round(sum(nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)),2) "Charge",
round(sum((nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)) - (nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0))),2) "Net"
from a_chase.jim a
inner join a_chase.clients b
on a.clientid = b.clientid
where trunc(date_in) = trunc(sdate)
group by client_name) b
on a."Client" = b."Client"
-- Get 30 Day Average
inner join (select client_name, round(avg("Net"),2) "Average" from
(select trunc(date_in) "In", client_name, round(sum((nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)) - (nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0))),2) "Net"
from a_chase.jim a
inner join a_chase.clients b
on a.clientid = b.clientid
where trunc(date_in) between (trunc(sdate) - 30) and trunc(sdate)
group by trunc(date_in), client_name)
group by client_name) c
on a."Client" = c.client_name
group by a."Client"
union --BU_TS
select 'bu_ts' "Location",a."Client" "Client", sum(nvl(b."In",0)) "In", sum(nvl(a."Out",0)) "Out", to_char(sum(nvl(a."Cost",0)
+ nvl(b."Cost",0)),'FM$9999999990.00PR') "Cost",
to_char(sum(nvl(a."Charge",0) + nvl(b."Charge",0)),'FM$9999999990.00PR') "Charge", to_char(sum(nvl(a."Net",0)
+ nvl(b."Net",0)),'FM$9999999990.00PR') "Net",
to_char(sum(nvl("Average",0)),'FM$9999999990.00PR') "30 Day Average"
-- Get Out, Cost, Net by date_out
from (select client_name "Client", count(date_sent) "Out",
round(sum(nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0)),2)"Cost",
round(sum(nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)),2) "Charge",
round(sum((nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)) - (nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0))),2) "Net"
from bu_ts.jim a
inner join bu_ts.clients b
on a.clientid = b.clientid
where trunc(date_sent) = trunc(sdate)
group by client_name) a
--Get In, Cost, Net by date_In
left outer join (select client_name "Client", count(date_in) "In",
round(sum(nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0)),2)"Cost",
round(sum(nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)),2) "Charge",
round(sum((nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)) - (nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0))),2) "Net"
from bu_ts.jim a
inner join bu_ts.clients b
on a.clientid = b.clientid
where trunc(date_in) = trunc(sdate)
group by client_name) b
on a."Client" = b."Client"
-- Get 30 Day Average
inner join (select client_name, round(avg("Net"),2) "Average" from
(select trunc(date_in) "In", client_name, round(sum((nvl(product_fee,0) + nvl(copy_fee,0) + nvl(afee1,0) + nvl(afee2,0)+ nvl(afee3,0)
+ nvl(afee4,0)+ nvl(afee5,0)+ nvl(afee6,0)+ nvl(afee7,0)+ nvl(afee1,8)+ nvl(afee1,9)
+ nvl(afee1,10)) - (nvl(product_cost,0) + nvl(acost1,0) + nvl(acost2,0) + nvl(acost3,0) +
nvl(acost4,0) + nvl(acost5,0) + nvl(acost6,0) + nvl(acost7,0)
+ nvl(acost8,0) + nvl(acost9,0) + nvl(acost10,0))),2) "Net"
from bu_ts.jim a
inner join bu_ts.clients b
on a.clientid = b.clientid
where trunc(date_in) between (trunc(sdate) - 30) and trunc(sdate)
group by trunc(date_in), client_name)
group by client_name) c
on a."Client" = c.client_name
group by a."Client"
union --BU
select 'BU' "Location", a."Company" "Client", sum(nvl(b."In",0)) "In", sum(nvl(a."Out",0)) "Out", to_char(sum(nvl(a."Cost",0)
+ nvl(b."Cost",0)),'FM$9999999990.00PR') "Cost",
to_char(sum(nvl(a."Charge", 0) + nvl(b."Charge",0)),'FM$9999999990.00PR') "Charge", to_char(sum(nvl(a."Net",0)
+ nvl(b."Net",0)),'FM$9999999990.00PR') "Net",
to_char(sum(nvl("Average",0)),'FM$9999999990.00PR') "30 Day Average"
from
(--Out Query
select b.clcompanyname "Company", count(*) "Out",
round(sum(nvl(cost1,0) + nvl(cost2,0) + nvl(cost3,0) + nvl(cost4,0) + nvl(cost5,0) + nvl(costx1,0)
+ nvl(costx2,0)+ nvl(costx3,0)+ nvl(costx4,0)+ nvl(costx5,0)+ nvl(costy1,0)+ nvl(costy2,0)+ nvl(costy3,0)
+ nvl(costy4,0)+ nvl(costy5,0)),2) "Cost",
round(sum(nvl(fee1,0) + nvl(fee2,0) + nvl(fee3,0) + nvl(fee4,0) + nvl(fee5,0) + nvl(feex1,0)
+ nvl(feex2,0)+ nvl(feex3,0)+ nvl(feex4,0)+ nvl(feex5,0)+ nvl(feey1,0)+ nvl(feey2,0)+ nvl(feey3,0)
+ nvl(feey4,0)+ nvl(feey5,0)),2) "Charge",
round( sum(nvl(fee1,0) + nvl(fee2,0) + nvl(fee3,0) + nvl(fee4,0) + nvl(fee5,0) + nvl(feex1,0)
+ nvl(feex2,0)+ nvl(feex3,0)+ nvl(feex4,0)+ nvl(feex5,0)+ nvl(feey1,0)+ nvl(feey2,0)+ nvl(feey3,0)
+ nvl(feey4,0)+ nvl(feey5,0) - nvl(cost1,0) - nvl(cost2,0) - nvl(cost3,0) - nvl(cost4,0) - nvl(cost5,0) - nvl(costx1,0)
- nvl(costx2,0)- nvl(costx3,0)- nvl(costx4,0)- nvl(costx5,0)- nvl(costy1,0)- nvl(costy2,0)- nvl(costy3,0)
- nvl(costy4,0)- nvl(costy5,0)),2) "Net"
from [email protected] a
inner join [email protected] b
on a.clientid = b.clientid
where trunc(compdate1) = trunc(sdate)
or trunc(compdate2) = trunc(sdate)
or trunc(compdate3) = trunc(sdate)
or trunc(compdate4) = trunc(sdate)
or trunc(compdate5) = trunc(sdate)
group by b.clcompanyname) a
--in Query
left outer join (select b.clcompanyname "Company", count(a.loandatein) "In",
round(sum(nvl(cost1,0) + nvl(cost2,0) + nvl(cost3,0) + nvl(cost4,0) + nvl(cost5,0) + nvl(costx1,0)
+ nvl(costx2,0)+ nvl(costx3,0)+ nvl(costx4,0)+ nvl(costx5,0)+ nvl(costy1,0)+ nvl(costy2,0)+ nvl(costy3,0)
+ nvl(costy4,0)+ nvl(costy5,0)),2) "Cost",
round(sum(nvl(fee1,0) + nvl(fee2,0) + nvl(fee3,0) + nvl(fee4,0) + nvl(fee5,0) + nvl(feex1,0)
+ nvl(feex2,0)+ nvl(feex3,0)+ nvl(feex4,0)+ nvl(feex5,0)+ nvl(feey1,0)+ nvl(feey2,0)+ nvl(feey3,0)
+ nvl(feey4,0)+ nvl(feey5,0)),2) "Charge",
round( sum(nvl(fee1,0) + nvl(fee2,0) + nvl(fee3,0) + nvl(fee4,0) + nvl(fee5,0) + nvl(feex1,0)
+ nvl(feex2,0)+ nvl(feex3,0)+ nvl(feex4,0)+ nvl(feex5,0)+ nvl(feey1,0)+ nvl(feey2,0)+ nvl(feey3,0)
+ nvl(feey4,0)+ nvl(feey5,0) - nvl(cost1,0) - nvl(cost2,0) - nvl(cost3,0) - nvl(cost4,0) - nvl(cost5,0) - nvl(costx1,0)
- nvl(costx2,0)- nvl(costx3,0)- nvl(costx4,0)- nvl(costx5,0)- nvl(costy1,0)- nvl(costy2,0)- nvl(costy3,0)
- nvl(costy4,0)- nvl(costy5,0)),2) "Net"
from [email protected] a
inner join [email protected] b
on a.clientid = b.clientid
where trunc(a.loandatein) = trunc(sdate)
group by b.clcompanyname) b
on a."Company" = b."Company"
--Avg Query
inner join (select "Company", round(avg("Net"),2) "Average" from
(select trunc(loandatein) "In", b.clcompanyname "Company",
round( sum(nvl(fee1,0) + nvl(fee2,0) + nvl(fee3,0) + nvl(fee4,0) + nvl(fee5,0) + nvl(feex1,0)
+ nvl(feex2,0)+ nvl(feex3,0)+ nvl(feex4,0)+ nvl(feex5,0)+ nvl(feey1,0)+ nvl(feey2,0)+ nvl(feey3,0)
+ nvl(feey4,0)+ nvl(feey5,0) - nvl(cost1,0) - nvl(cost2,0) - nvl(cost3,0) - nvl(cost4,0) - nvl(cost5,0) - nvl(costx1,0)
- nvl(costx2,0)- nvl(costx3,0)- nvl(costx4,0)- nvl(costx5,0)- nvl(costy1,0)- nvl(costy2,0)- nvl(costy3,0)
- nvl(costy4,0)- nvl(costy5,0)),2) "Net"
from [email protected] a
inner join [email protected] b
on a.clientid = b.clientid
where trunc(loandatein) between (trunc(sdate) - 30) and trunc(sdate)
group by trunc(loandatein), b.clcompanyname)
group by "Company") c
on a."Company" = c."Company"
group by a."Company";
return(ret_cursor);
end;
end;
I also have given htmldb_public_user grant/execute privileges on this function. Any help would be greatly appreciated.
Thanks,
Scottthanks, lalit. that's almost correct. htmldb_public_user is the username through which the mod_plsql DAD connects to the database. he has just the privs he needs to serve that function. the htmldb engine compiles into a FLOWS_010500 schema in the production release. having said that, lalit's suggestion is correct. you need to make sure your htmldb application schema (identified by the application-level attribute "Default Parsing Schema") has been directly granted privileges (directly as opposed to coming through a role rant) to run the objects it's calling.
hope this helps,
raj -
What are the advantages to using a REF cursor
When would I want to use a REF cursor?
REF CURSORs are not cursors, they're references to cursors. This means they're dynamic. So you can completely change the query executed by the cursor.
For example you can use a REF CURSOR to select from one of a number of tables (depending on an input parameter or other sort of flag). The results are fetched into the same resultset holder and hence you only need a single lot of code to process the results.
Also you can also pass a REF CURSOR as a argument to other PL/SQL procedures and functions.
rgds, APC -
Passing Ref Cursor to Oracle Stored Procedure Via C#
Hi all,
I am new to oracle and stuck with an issue. I have three insert stored procedures for three different tables. Two of them have multiple rows to be inserted, which is currently done via iterating through each row and insert to db in C# code. My requirement is to merge these three procedures in one and instead of iterating from C# code send table rows as (ref cursor or collection) to procedure and the procedure will handle the rest.
I read that ref cursor only works if you're data is in database as it reference the memory but in my case data is build on client side.
I am using Oracle 11i and ASP.Net 2.0
Can any help me on this please?
Edited by: 929463 on Apr 23, 2012 12:38 AM929463 wrote:
I am new to oracle and stuck with an issue. I have three insert stored procedures for three different tables. Two of them have multiple rows to be inserted, which is currently done via iterating through each row and insert to db in C# code. My requirement is to merge these three procedures in one and instead of iterating from C# code send table rows as (ref cursor or collection) to procedure and the procedure will handle the rest.Why a single procedure? How is the procedure to determine the target table to insert the data into? And please - no dynamic SQL as that is 99% of the time wrong.
A ref cursor is something that PL/SQL creates - with the purpose of passing the cursor handle to your code. This enables the actual SQL statement for that cursor to be moved from client code, into a PL/SQL stored proc. It abstracts the client from having to understand SQL, understand the data model and so on. All clients use the same PL/SQL proc and thus the same code for creating that cursor. Thus no issue of some clients getting it half right or half wrong and dealing with data inconsistencies between clients.
The PL/SQL proc can be tuned and optimised, modified for catering for data model changes and so on. Without your client code having to be even recompiled as it is isolated against these server changes.
For all other interaction (running PL/SQL code, doing insert/update/delete/etc SQL statements), you need to create the cursor yourself in your code.
Also, the SQL engine only sees cursors. There are no differences between cursors. The client (e.g. PL/SQL) can call it a reference cursor, or an implicit cursor, or a DBMS_SQL cursor.. the SQL engine does not know that and does not care.
A ref cursor is simply a special type of client interface to a SQL cursor, allowing PL/SQL to create that SQL cursor and then pass the handle of that SQL cursor to other code to consume that cursor.
Okay, so if you want to insert data, you need in your code to create a cursor. This can be a SQL INSERT cursor - the actual insert statement. Or it can be a PL/SQL call - an anonymous PL/SQL code block that calls a stored proc that performs the insert (after applying validation and business logic).
The cursor will have one or more bind variables. Your client will pass values for these variables and the server-side code (SQL or PL/SQL) will be executed using this as variable data.
You can for example create a cursor as follows:
begin
DoFunkyInsert( :1, :2, :3 );
end;
{code}
3 bind variables are expected. You can now in the client build an array for each of these variables, containing a 100 values each (total of a 100 rows to insert). Do a single execute of the cursor, and tell Oracle that the bind is actually a 100 element array.
The complete array ships to Oracle - Oracle opens a loop and execute the cursor for each element in the array.
This is called bulk binding.
An alternative approach is to define the bind variable as a collection (a non-scalar value). And then code the PL/SQL procedure to open a loop and iterate through the collection/array, inserting a row per iteration.
The binding itself is more complex as your code know needs to understand Oracle object types and be able to define an array/collection that is a valid Oracle non-scalar data type.
The +Oracle Call Interface+ (OCI) is quite flexible in this regard. However, as you work via an abstraction layer (e.g. ADO, OleDB, ODBC, etc) your code is subject to whatever functionality this abstraction layer makes available to your code. And this is seldom includes all the power, functionality and flexibility of the (more complex) OCI itself. -
Help on CAST function, defining TYPE TABLE and using a REF cursor
Hi,
I have written a procedure (lookup) inside a package (lookup_pkg) as shown below.
Procedure has an output variable of type PL/SQL TABLE which is defined in the package.
I want to write a wrapper procedure lookupref to the procedure lookup to return a ref cursor.
CREATE OR REPLACE PACKAGE lookup_pkg AS
TYPE t_lookup_refcur IS REF CURSOR;
CURSOR c_lookup IS
Select columns1,2,3,....100
FROM A, B, C, D, E
WHERE ROWNUM < 1;
TYPE t_lookup IS TABLE OF c_lookup%ROWTYPE;
Procedure lookup(id Number, o_lookup OUT t_lookup);
End lookup_pkg;
CREATE OR REPLACE PACKAGE BODY lookup_pkg As
Procedure lookup(id Number, o_lookup OUT t_lookup) IS
BEGIN
END lookup;
Procedure lookupref(id Number, o_lookupref OUT t_lookup_refcur) IS
o_lookup t_lookup;
BEGIN
lookup(id, o_lookup t_lookup);
OPEN t_lookup_refcur FOR
SELECT *
FROM TABLE(CAST(o_lookup AS t_lookup));
Exception
End lookupref;
END lookup_pkg;
When I compile this procedure, I am getting invalid datatype Oracle error and
cursor points the datatype t_lookup in the CAST function.
1. Can anyone tell me what is wrong in this. Can I convert a PL/SQL collection (pl/sql table in this case) to PL/SQL datatype table or does it need to be a SQL datatype only (which is created as a type in database).
Also, to resolve this error, I have created a SQL type and table type instead of PL/SQL table in the package as shown below.
create or replace type t_lookuprec as object
(Select columns1,2,3,....100
FROM A, B, C, D, E
WHERE ROWNUM < 1);
create or replace type t_lookup_tab AS table of t_lookuprec;
CREATE OR REPLACE PACKAGE BODY lookup_pkg As
Procedure lookup(id Number, o_lookup OUT t_lookup) IS
BEGIN
END lookup;
Procedure lookupref(id Number, o_lookupref OUT t_lookup_refcur) IS
o_lookup t_lookup;
BEGIN
lookup(id, o_lookup t_lookup);
OPEN t_lookup_refcur FOR
SELECT *
FROM TABLE(CAST(o_lookup AS t_lookup_tab));
Exception
End lookupref;
END lookup_pkg;
When I compile this package, I am getting "PL/SQL: ORA-22800: invalid user-defined type" Oracle error and
points the datatype t_lookup_tab in the CAST function.
2. Can anyone tell me what is wrong. Can I create a type with a select statement and create a table type using type created earlier?
I have checked the all_types view and found that
value for Incomplete column for these two types are YES.
3. What does that mean?
Any suggestions and help is appreciated.
Thanks
Srinivascreate or replace type t_lookuprec as object
(Select columns1,2,3,....100
FROM A, B, C, D, E
WHERE ROWNUM < 1);You are correct that you need to use CREATE TYPE to use the type in SQL.
However unless I am mistaken you appear to have invented your own syntax for CREATE TYPE, suggest you refer to Oracle documentation. -
How to open a Ref cursor in Oracle Reports
I have a stored procedure that returns a ref cursor as an output parameter. I want to call this stored procedure in Oracle Reports After Form trigger. I am having trouble with the syntax of the output parameter. Event_record is the name of the cursor.
After Form Trigger
pkg_DEAL_WHITESHEET_CONCERTS.prc_Event_Information(:p_field_6,event_record);
Error: Event_record must be declaredRe-Write the procedure as Package Spec and Body. Declare the REFCursor in the Package Spec. Probably that helps.
-
Pro*C program to use a REF CURSOR returned by a DB Function
Hi,
Please help me with this.
I have a pro*c program that should call a
database function which returns a ref cursor.
This is the sample code i have :-
EXEC SQL BEGIN DECLARE SECTION;
SQL_CURSOR emptycabin_cursor;
int cabinid;
EXEC SQL END DECLARE SECTION;
EXEC SQL ALLOCATE :emptycabin_cursor;
EXEC SQL EXECUTE BEGIN
:emptycabin_cursor:=posremptycabin(:voy,:segid);
END;END-EXEC;
/* more_records = 1*/
while (more_records)
EXEC SQL FETCH :emptycabin_cursor INTO :cabinid;
if (SQLCODE==NOTFOUND)
{more_records=FALSE;break;}
EXEC SQL close :emptycabin_cursor;
When I execute I keep getting fetch out of sequence error.
Can someone let me know whats wrong with this code?
When I execute the function from sqlplus
variable ref_cur refcursor ;
exec :ref_cur:=posremptycabin(232,'CC');
print :ref_cur;
I get the data properly displayed.So nothing wrong with the function.
Thanks for your helpI know nothing about Pro*C, but Tom Kyte's Pro*C example for ref cursors fetches the cursor with a loop that looks like:
for( ;; )
EXEC SQL WHENEVER NOTFOUND DO break;
EXEC SQL FETCH :my_cursor INTO :ename, empno;
printf( "'%.*s', %d\n", ename.len, ename.arr, empno );
EXEC SQL CLOSE :my_cursor;http://asktom.oracle.com/~tkyte/ResultSets/index.html
Hope this helps. -
ORA-12714 error using NVARCHAR2, REF CURSOR and TABLE FUNCTION
Hello,
we have tested this simple script on all the following versions of Oracle: 9.2.0.3, 10.2.0.1.0 , 11.1.0.6.0 - but we got the same error in everyone of these.
CREATE OR REPLACE TYPE Rec_Prova IS OBJECT(
Id INTEGER,
NodeValue NVARCHAR2(50)
CREATE OR REPLACE TYPE Tab_Prova IS TABLE OF Rec_Prova;
DECLARE
CurProva SYS_REFCURSOR;
varTable Tab_Prova := Tab_Prova();
BEGIN
OPEN CurProva FOR
SELECT Id, NodeValue FROM TABLE(CAST(varTable AS Tab_Prova));
END;The error is: "ORA-12714: invalid national character set specified"
We know that changing the type of NodeValue from NVARCHAR2 to NCLOB it works, but the performances are very poor.
Therefore this solution is not acceptable for us.
We also know that if the character set of the database is set to unicode (NLS_NCHAR_CHARACTERSET = AL16UTF16) we can use the VARCHAR2 for store also the unicode characters and the problem is solved. But some of our customers can't change the settings of theirs databases... moreover, in this forum someone says:
"To all dba's who try to change the NLS_CHARACTERSET or NLS_NCHAR_CHARACTERSET by updating props$ . This is NOT supported and WILL corrupt your database. This is one of the best way's to destroy a complete dataset. Oracle Support will TRY to help you out of this but Oracle will NOT warrant that the data can be recoverd or recovered data is correct. Most likely you WILL be asked to do a FULL export and a COMPLETE rebuild of the database."
Is there any workaround except the two that I have mentioned?
Thank you in advance.
Edited by: user11929330 on 22-set-2009 7.50ORA-12714: invalid national character set specified
Cause: Only UTF8 and AL16UTF16 are allowed to be used as the national character set
Action: Ensure that the specified national character set is valid
So it looks like that you should change the character set or go for NCLOB (and if you're on version 11, maybe securefiles gives you the performance you want).
-Andy -
Dynamic Ref Cursor report in 6i
Hello,
I apologise that this question is so similar to many in this forum, but I haven't found a solution to my problem yet.
I've created a ref cursor query because I need to include a variable p_orgs in my WHERE clause, like so:
where e.org_id in ('||p_orgs||')
I've constructed the report as mentioned on this page:
www.dulcian.com
FAQs - SQL & PL/SQL FAQs - FAQ ID# 5:
"How can you use 'dynamic' ref cursors in Oracle Reports 3.0 / 6i?"
(Thanks to Zlatko Sirotic for the information).
I get a compile error when compiling the package body that holds my ref cursor open statement:
Error 103 Encountered the symbol ''select'' when expecting one of the following:
Select
Is there any way around this problem?
If I was to upgrade to Reports 9i would it work?
Many thanks,
HazelHello,
Just a remark : you don't need to use a Ref Cursor if you just want to use a "dynamic where clause".
You can use a lexical reference :
You can find examples at :
http://www.oracle.com/webapps/online-help/reports/10.1.2/topics/htmlhelp_rwbuild_hs/rwwhthow/whatare/dmobj/sq_a_lexical_references.htm
(This page is about Reports 10.1.2 but Lexical references are identical in Reports 6i and Reports 10.1.2)
Regards -
Using a strongly typed ref cursor doesn't enforce data type
I am trying to enforce the datatypes of the fields coming back from an oracle reference cursor by making it strongly typed. However, there seems to be no warning at compile time on the oracle side or exception in ODP.NET if the datatype coming back in the cursor does not match. For example here is my cursor and proc
create or replace
PACKAGE THIRDPARTY AS
type pricing_record is record
BaseIndexRate number(6,5),
BaseIndexRateType VARCHAR2(1 BYTE)
type cur_pricing2 IS ref CURSOR return pricing_record;
PROCEDURE getpricingbyappidtest(appid IN application.intid%TYPE, pricing OUT cur_pricing2);
END THIRDPARTY;
create or replace
PACKAGE BODY THIRDPARTY AS
PROCEDURE getpricingbyappidtest(appid IN application.appid%TYPE, pricing OUT cur_pricing2)
AS
BEGIN
OPEN pricing FOR
SELECT somevarcharfield, someothervarcharfield
FROM application
WHERE A.appid = appid;
END getpricingbyappidtest;
I would expect this wouldn't compile since i am putting a varchar into a number field. But it does. Also if i check the datatype in the reader on the .net side it also is a string. So odp doesn't seem to care what type the cursor is
here is that code and output
var schemaTable = reader.GetSchemaTable();
using (var file = new System.IO.StreamWriter("c:\\_DefinitionMap_" + cursorName + ".txt"))
file.WriteLine("COLUMN" + "\t" + "DATATYPE");
foreach (DataRow myField in schemaTable.Rows)
file.WriteLine(myField["ColumnName"] + "\t" + myField["DataType"]);
COLUMN DATATYPE
BaseIndexRate System.String
BaseIndexRateType System.String
Does anyone have an approach for enforcing datatypes in a ref cursor? Am I doing something wrong when defining the ref cursor?Hello,
By using a ref cursor you are really using a pointer to a cursor. There is no way I know of to make a compile check of the cursor check unless you want to create a SQL type and cast the cursor to this type and even this wouldn't work in all cases. For instance, I could have function call within my cursor select which could return a varchar (with a number always in the varchar) which would be horribly sloppy but legal and you would expect Oracle to compile it.
If you are worried about this I would suggest not using ref cursors and go to UDT instead, where there will be more checking (because of a C# equivalence generated object). Oh and BTW, yes the cursor will throw an exception if the data is incorrect, but only at runtime - just like normal Oracle PLSQL.
Cheers
Rob.
http://www.scnet.com.au -
Ref Cursor Problem in Oracle Forms 6i
Hi all.
In Oracle Forms 6i, can not I do this?
DECLARE
TYPE CUR_REF IS REF CURSOR;
CUR_PRODUCTS CUR_REF;
VAR_QUERY VARCHAR2(3000) := 'SELECT something FROM table';
BEGIN
OPEN CUR_PRODUCTS FOR VAR_QUERY;
END;
It generates error on opening that it expects a SELECT statement.
How can I open a dynamic ref cursor in Oracle Forms 6i??? The same thing works fine in PL/SQL.
Regards,
Zaaf
Thanks in advance.It could be like this:
PROCEDURE dynamic_cursor ( PC$Clause IN Varchar2 )
IS
cursor_number EXEC_SQL.CursType;
-- Variables for the data to be returned into
LC$ACTYPE Number;
-- Control variables
LN$count Number;
LC$sql_order Varchar2(256);
BEGIN
-- Open the cursor --
cursor_number := Exec_SQL.Open_cursor;
-- build the complete SQL order --
LC$sql_order := PC$clause ;
-- Parse the SQL order --
EXEC_SQL.PARSE(cursor_number, LC$sql_order);
-- Define the columns for the data to be returned --
EXEC_SQL.DEFINE_COLUMN(cursor_number,1,LC$ACTYPE);
-- Execute the Cursor --
LN$count := EXEC_SQL.EXECUTE(cursor_number);
-- Loop and fetch each row from the result set --
While EXEC_SQL.FETCH_ROWS(cursor_number) > 0 Loop
EXEC_SQL.COLUMN_VALUE(cursor_number,1,LC$ACTYPE);
begin
select chqfac, pasfac, indbcr ,
staxfl, excise, incchg, cat001 , trntyp , subtyp
into s_chkbok, s_pasbok, s_intber,
s_staxfl, s_excise, s_incchg, s_cat001 , ss_trntyp , ss_subtyp
from stfeacty
where brancd = s_brancd
and actype = LC$ACTYPE;
s_actype := LC$ACTYPE ;
exception
when no_data_found then
NULL;
when too_many_rows then
NULL;
end;
End Loop ;
-- Close the cursors
EXEC_SQL.CLOSE_CURSOR(cursor_number);
EXCEPTION
When EXEC_SQL.INVALID_CONNECTION Then
message('Unexpected Invalid Connection error from EXEC_SQL');
When EXEC_SQL.PACKAGE_ERROR Then
message('Unexpected error from EXEC_SQL: '||to_char(EXEC_SQL.LAST_ERROR_CODE)|| EXEC_SQL.LAST_ERROR_MESG);
If EXEC_SQL.IS_OPEN(cursor_number) Then
EXEC_SQL.CLOSE_CURSOR(cursor_number);
message('Exception - Cleaned up Cursor');
End if;
END; That you could call with the following:
dynamic_cursor('SELECT ac_type FROM SYSADM.SAVINGS');But, if the query is as simple with only the table name change, you could aslo use a simpliest solution based on a record group.
Francois -
How to write REF-CURSOR Query in Oracle Reports
Hello Guys!!
I have a form in which you can select regions/divisions/locations etc by the use of check boxes. And the selected values will be inserted into a table, and based on the selected values of the table the report is run.
The issue I have is with the query inside the Oracle reports(attached to this file).
The query works fine until the last two EXISTS conditions.
IF a region exists In the table report_param then it works fine but if there are no divisions in it , then the query returns no values, which is not correct.
Someone has advised me to use a ref-cursor query inside reports tool, which I am not aware off. So, anykind of suggestions or advises are welcome. Please let me know about it as it is very urgent issue for me. Anykind of help would be greatly
appreciated.
Thanks,
Vishal
-------------------------------------------------------Query in Oracle Reports---------------------------------------------------------
select c.key_segment, p.supplier_id,
decode(:in_col_nm, 'BRAND',nvl(p.product_brand,'<Unknown Brand>'), 'PLN',nvl(p.product_legal_name,'<Unknown Legal Name>')) COL_NM,
sum(a.ext_price) sales_dols,
sum(comp_allow_pkg.get_comp_allow_stddiv(a.control_loc_id, a.product_id, a.sold_to_customer_id,
a.doc_dt, a.ext_price, a.units)) cust_reb_dols,
sum(a.units) units,
sum(a.ext_cost) cost_dols
from sales a, key_segment_plns c, product p, rep_wrtr_dw_cust h
where a.doc_dt between :in_start_dt and :in_end_dt
and a.customer_oc = h.control_loc_id
and a.sold_to_customer_id = h.sold_to_cust_id
and a.ship_to_customer_id = h.ship_to_cust_id
and ((:in_dg_cd = 'B' and h.dealer_grower_cd in ('D','G')) or h.dealer_grower_cd = :in_dg_cd)
and a.product_id = p.product_id
and p.product_gl_class_cd = 'CHEM'
and p.product_legal_name = c.product_legal_name
and c.key_segment in ('GLYPHOSATE','PLANT HEALTH/RUST FUNGICIDES','PYRETHROIDS','STROBI FUNGICIDES')--&IN_KEY_SEGMENTS
-- and (:in_oc = 'ALL' or (a.control_loc_id in (select control_loc from control_loc_comb_ocs where control_loc_comb = :in_oc)))
-- SALES DATA FILTERS TO MATCH ACCUM_SALES_DG_MV
and a.sale_type_cd in ('02','08')
and a.document_type_cd in ('I','C','D')
and (substr(a.product_id,-1) in ('0','1') OR nvl(upper(trim(p.product_brand)),'X') = 'TECH FEE')
and a.units <> 0
and a.unit_cost <> 0
and a.unit_price <> 0
-- NEW FILTERS ADDED 9/11/07: LOCATION(BRANCH), BUSINESS TYPE, RSM/ASM/REP
and ((:in_loc = 'ALL') or (nvl(a.warehouse_id,'<blank>') in (SELECT param_value
FROM report_param
WHERE report_id = :IN_REPORT_ID
AND session_id= :IN_SESSION_ID
AND USER_ID = :IN_USER_ID
AND param_name='LOCATION_TYPE')))
and ((:in_uhs_ag = 'ALL') or (:in_uhs_ag = 'NA' and p.product_uhs_ag != 'A') or (p.product_uhs_ag = :in_uhs_ag))
and ((:in_sales_rep = 'ALL') or (nvl(a.territory_id,'<blank>') in (SELECT param_value
FROM report_param
WHERE report_id = :IN_REPORT_ID
AND session_id= :IN_SESSION_ID
AND USER_ID = :IN_USER_ID
AND param_name='SALES_REP_TYPE')))
and EXISTS
(SELECT '1'
FROM locations l, report_param rp
WHERE rp.report_id = :IN_REPORT_ID
AND rp.session_id= :IN_SESSION_ID
AND rp.user_id = :IN_USER_ID
AND rp.param_value = l.region
AND rp.param_name = 'REGION_TYPE'
AND a.warehouse_id = L.ARS_LOCATION)
and EXISTS
(SELECT '1'
FROM locations l, report_param rp
WHERE rp.report_id = :IN_REPORT_ID
AND rp.session_id= :IN_SESSION_ID
AND rp.user_id = :IN_USER_ID
AND rp.param_value = l.region
AND rp.param_name = 'DIVISION_TYPE'
AND a.warehouse_id = L.ARS_LOCATION)
group by c.key_segment, P.supplier_id,
decode(:in_col_nm, 'BRAND',nvl(p.product_brand,'<Unknown Brand>'), 'PLN',nvl(p.product_legal_name,'<Unknown Legal Name>'))Hi,
I need your help to create a report using Ref-Cursor. please see the below thread
Report using ref cursor or dynamic Sql
Maybe you are looking for
-
Hi everyone, I was doing File to IDOC Scenario and trying to post Multipe Records to the R/3 System. I tried sending Cremas03 details both as an XML file and also as a TXT file Using File Content Conversion from XI and i could not succeed
-
[CS3][VB] Bug in myPage.Duplicate :(
hi I try to duplicate page and get reference to object on newly duplicated page I do something like this - this procedure should place page from multipage-PDF to Labeled Rectangle on duplicated page - next page: Set myDestObject = FoundItem b = 1 Do
-
Smart View Ribbon not shown when Excel is invoked using VBA
Dear Hyperion Gurus, I am in need to invoke smartview refresh by calling excel using VBA from an excel module in another sheet(master template). But when I invloke Excel using VBA, smartview ribbon does not get activated, due to which the HypConnect,
-
Button onclick not working in the calculated field
Hi Everyone, I have to add the button in the calculated field through list definition. On click of button it should call the java script function. I can add the button but on click event is not working. this is my code: <Field Name="Accept" ID="{1F73
-
Can't change speed to Variable/grayed out
Hi, I tried searching this board under various speed terminologies including time remap and also the manual and FCP Help at apple.com but cannot find the answer. I want to use the time remap feature but variable speed is grayed out. If I try command