Using Instr in Cursors or Loops...?
Can anyone suggest me how to use "Instr" to find one parameter string in another parameter string, finding if one string is present in another using loops..??
Edited by: user11339127 on Jul 1, 2009 11:04 PM
You can use INSRT to find the position of your string in a given string.
e.g: select instr('navnit','av') from dual; --sql
PL/SQL--
declare
pos number;
begin
pos := instr('<string1>','<string2'>; or you can write in case of forms as pos:=instr('<:datablock>.<item>','<string to found');
if pos = <some value> then
<do something
end if;
end;
{coe}
Similarly , you can extend your code.
Hope it helps.
+Please mark answer as helpful / correct, if it helps you+
Navnit
Similar Messages
-
Hi,
can anybody suggest what kind of report and in what way I have to use if I want to write query using cursors within loops?
Thanks!
Karina.Hi,
I found the solution. I just rewrite all cursors within one SQL statement and it works.
Karina. -
How can i use the same cursor in a loop fro multipletimes.
I am using two cursors.One to fetch sites and the other to fetch participants under each site.I am performing some job with that participants data.Now the problem is i am using the 2nd cursor in a loop.So it fetches the data of participants falling under one state.But when it comes to the second state,as the second cursor is already open it is unable to fetch the records.Please help me .How can i use the same cursor in a loop fro multipletimes.
I am sending the code which i have written in When-Button-Pressed-Trigger...
declare
sid number;
pid number;
cursor csid is select distinct(site_id) from cyber_ppt;
cursor cpid is select pc_id,st_dt,ed_dt from cyber_ppt where site_id = sid;
stdt varchar2(10);
eddt varchar2(10);
nom number;
stmonth varchar2(10);
edmonth varchar2(10);
cjan number:=0;
cfeb number:=0;
cmar number:=0;
capr number:=0;
cmay number:=0;
cjun number:=0;
cjul number:=0;
caug number:=0;
csep number:=0;
coct number:=0;
cnov number:=0;
cdec number:=0;
i number:=1;
begin
open csid ;
loop
fetch csid into sid;
exit when csid %notfound;
message(sid);
open cpid;
loop
fetch cpid into pid,stdt,eddt ;
exit when cpid %notfound;
message(sid||'-'||pid);
stmonth:=substr(stdt,4,3);
edmonth:=substr(eddt,4,3);
nom:= months_between(eddt,stdt);
while i <= round(nom)
loop
stmonth:=substr(stdt,4,3);
if stmonth='JAN' then
cjan:=cjan+1;
elsif stmonth='FEB' then
cfeb:=cfeb+1;
elsif stmonth='MAR' then
cmar:=cmar+1;
elsif stmonth='APR' then
capr:=capr+1;
elsif stmonth='MAY' then
cmay:=cmay+1;
elsif stmonth='JUN' then
cjun:=cjun+1;
elsif stmonth ='JUL' then
cjul:=cjul+1;
elsif stmonth ='AUG' then
caug:=caug+1;
elsif stmonth ='SEP' then
csep:=csep+1;
elsif stmonth ='OCT' then
coct:=coct+1;
elsif stmonth ='NOV' then
cnov:=cnov+1;
elsif stmonth ='DEC' then
cdec:=cdec+1;
end if;
stdt:=add_months(stdt,1);
i:=i+1;
end loop;
end loop;
end loop;
end;
try this /* untested */
DECLARE
sid NUMBER;
pid NUMBER;
CURSOR csid IS SELECT DISTINCT(site_id) FROM cyber_ppt;
CURSOR cpid(nSid NUMBER) is SELECT pc_id,st_dt,ed_dt FROM cyber_ppt WHERE site_id = nSid;
stdt VARCHAR2(10);
eddt VARCHAR2(10);
nom NUMBER;
stmonth VARCHAR2(10);
edmonth VARCHAR2(10);
cjan NUMBER:=0;
cfeb NUMBER:=0;
cmar NUMBER:=0;
capr NUMBER:=0;
cmay NUMBER:=0;
cjun NUMBER:=0;
cjul NUMBER:=0;
caug NUMBER:=0;
csep NUMBER:=0;
coct NUMBER:=0;
cnov NUMBER:=0;
cdec NUMBER:=0;
i NUMBER:=1;
BEGIN
FOR rec IN csid
LOOP
sid := rec.csid;
FOR cRec IN cpid(sid)
LOOP
pid := cRec.pc_id;
stdt := cRec.st_dt;
eddt := cRec.ed_dt;
stmonth:= SUBSTR(stdt,4,3);
edmonth:= SUBSTR(eddt,4,3);
nom:= months_between(eddt,stdt);
WHILE i <= round(nom)
LOOP
stmonth := SUBSTR(stdt,4,3);
IF stmonth='JAN'
THEN
cjan:=cjan+1;
ELSIF stmonth='FEB' THEN
cfeb:=cfeb+1;
ELSIF stmonth='MAR' THEN
cmar:=cmar+1;
ELSIF stmonth='APR' THEN
capr:=capr+1;
ELSIF stmonth='MAY' THEN
cmay:=cmay+1;
ELSIF stmonth='JUN' THEN
cjun:=cjun+1;
ELSIF stmonth ='JUL' THEN
cjul:=cjul+1;
ELSIF stmonth ='AUG' THEN
caug:=caug+1;
ELSIF stmonth ='SEP' THEN
csep:=csep+1;
ELSIF stmonth ='OCT' THEN
coct:=coct+1;
ELSIF stmonth ='NOV' THEN
cnov:=cnov+1;
ELSIF stmonth ='DEC' THEN
cdec:=cdec+1;
END IF;
stdt:=add_months(stdt,1);
i:=i+1;
END LOOP;
END LOOP;
END LOOP;
END; -
How to optimize the select query that is executed in a cursor for loop?
Hi Friends,
I have executed the code below and clocked the times for every line of the code using DBMS_PROFILER.
CREATE OR REPLACE PROCEDURE TEST
AS
p_file_id NUMBER := 151;
v_shipper_ind ah_item.shipper_ind%TYPE;
v_sales_reserve_ind ah_item.special_sales_reserve_ind%TYPE;
v_location_indicator ah_item.exe_location_ind%TYPE;
CURSOR activity_c
IS
SELECT *
FROM ah_activity_internal
WHERE status_id = 30
AND file_id = p_file_id;
BEGIN
DBMS_PROFILER.start_profiler ('TEST');
FOR rec IN activity_c
LOOP
SELECT DISTINCT shipper_ind, special_sales_reserve_ind, exe_location_ind
INTO v_shipper_ind, v_sales_reserve_ind, v_location_indicator
FROM ah_item --464000 rows in this table
WHERE item_id_edw IN (
SELECT item_id_edw
FROM ah_item_xref --700000 rows in this table
WHERE item_code_cust = rec.item_code_cust
AND facility_num IN (
SELECT facility_code
FROM ah_chain_div_facility --17 rows in this table
WHERE chain_id = ah_internal_data_pkg.get_chain_id (p_file_id)
AND div_id = (SELECT div_id
FROM ah_div --8 rows in this table
WHERE division = rec.division)));
END LOOP;
DBMS_PROFILER.stop_profiler;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
WHEN TOO_MANY_ROWS
THEN
NULL;
END TEST;The SELECT query inside the cursor FOR LOOP took 773 seconds.
I have tried using BULK COLLECT instead of cursor for loop but it did not help.
When I took out the select query separately and executed with a sample value then it gave the results in a flash of second.
All the tables have primary key indexes.
Any ideas what can be done to make this code perform better?
Thanks,
Raj.As suggested I'd try merging the queries into a single SQL. You could also rewrite your IN clauses as JOINs and see if that helps, e.g.
SELECT DISTINCT ai.shipper_ind, ai.special_sales_reserve_ind, ai.exe_location_ind
INTO v_shipper_ind, v_sales_reserve_ind, v_location_indicator
FROM ah_item ai, ah_item_xref aix, ah_chain_div_facility acdf, ah_div ad
WHERE ai.item_id_edw = aix.item_id_edw
AND aix.item_code_cust = rec.item_code_cust
AND aix.facility_num = acdf.facility_code
AND acdf.chain_id = ah_internal_data_pkg.get_chain_id (p_file_id)
AND acdf.div_id = ad.div_id
AND ad.division = rec.division;ALSO: You are calling ah_internal_data_pkg.get_chain_id (p_file_id) every time. Why not do it outside the loop and just use a variable in the inner query? That will prevent context switching and improve speed.
Edited by: Dave Hemming on Dec 3, 2008 9:34 AM -
PL/SQL block to create temporary table + load via cursor for loop
Assume I have a table that contains a subset of data that I want to load into a temporary table within a cursor for-loop. Is it possible to have a single statement to create the table and load based on the results of the fetch?
I was thinking something like:
Declare CURSOR xyz is
CREATE TABLE temp_table as
select name, rank, serial number from
HR table where rank = 'CAPTAIN'
BEGIN
OPEN xyz
for name in xyz
LOOP
END LOOP
What I see wrong with this is that the table would be created multiple times which is why this syntax is not acceptable. I'd prefer not to have to define the temporary table then load in two sepearte SQL statements and am hoping a single statement can be used.
Thanks!What is the goal here?
If you're just going to iterate over the rows that are returned in a cursor, a temporary table is unnecessary and only adds complexity. If you truly need a temporary table, you would declare it exactly once, at install time when you create all your other tables. You'd INSERT data into the temp table and the data would only be visible to the session that inserted it.
Justin -
while i was studying about cursor for loop i found this statement in the web
"A cursor FOR loop implicitly declares its loop index as a %ROWTYPE record"
for example an emp table contain following columns empno,ename,sal,hiredate,deptno
and let us consider an cursor for loop as
for rec in select empno,sal from emp loop
if cursor for loop declare loop index as a %rowtype our cursor statement should include all the columns and follow the data type compatabulity.
But here our cursor statement includes only few columns,if we use %rowtype we have to select all columns but here we are not doing this.
Can anyone please explain what is happening in cursor for loop?for loop cursor is also like the simple explicite cursor..
the cursor variable will hold only the columns that are given in select statement of the cursor..
if u declare a cursor as %rowtype, then it should include all the columns of that particular table..
otherwise u should use only %type for each and every column seperately only... -
Hello.
I need help creating a cursor and loop that will update a column based on data from another column. I keep getting the following errors. Any suggestions? These identifiers are valid tables in columns in my data base.
SQL> DECLARE
2
3 CURSOR c1 IS
4 SELECT SectionID, Coursename, StudentID, FinalGrade from Registration, Section, Grade WHERE registration.sectionid = grade.sectionid and registrationid.studentid = grade.studentid;
5
6 v_SectionID number(10);
7 v_CourseName varchar(20);
8 v_StudentID number(10);
9 v_FinalGrade varchar2(5);
10
11 BEGIN
12
13 OPEN c1;
14
15 LOOP
16 FETCH c1
17 INTO v_SectionID, v_CourseName, v_StudentID, v_FinalGrade;
18 EXIT WHEN c1%NOTFOUND;
19
20 update grade
21
22 SET FinalGrade = translate(substr(v_CourseName,-1,1),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','AAAAAABBBBBCCCCCDDDDEEEEEE')
23
24 where Grade.StudentID = Registration.StudentID;
25
26 END LOOP;
27 CLOSE c1;
28 END;
29 /
SELECT SectionID, Coursename, StudentID, FinalGrade from Registration, Section, Grade WHERE registration.sectionid = grade.sectionid and registrationid.studentid = grade.studentid;
ERROR at line 4:
ORA-06550: line 4, column 140:
PL/SQL: ORA-00904: "REGISTRATIONID"."STUDENTID": invalid identifier
ORA-06550: line 4, column 3:
PL/SQL: SQL Statement ignored
ORA-06550: line 24, column 27:
PL/SQL: ORA-00904: "REGISTRATION"."STUDENTID": invalid identifier
ORA-06550: line 20, column 3:
PL/SQL: SQL Statement ignored863737 wrote:
I am taking a intro course online so I am trying to teach myself this. The most basic rule for designing and writing good Oracle code that will perform and will scale is to use SQL for what it is good at and using PL/SQL for what it is good at. And between the two, SQL is by far superior when it comes to crunching data in the database.
The simple maxim is Maximize SQL. Minimize PL/SQL.
What you want to do with that PL/SQL code can be done using SQL only. And since you are learning SQL and PL/SQL, it is very important that you learn the correct way to do this.
Have a look at Oracle® Database SQL Language Reference guide.
The update syntax supports:
UPDATE <dml_expression_clause>
Where this +<dml_expression_clause>+ is a SELECT statement (aka an in-line view) - that can contain joins.
Simple example. You join tables t1 and t2 to identify the rows in t1 to update. The +<dml_expression_clause>+ will define this join. The actual update part (using the SET clause) will update the relevant rows in t1.
This is also called an updatable view - though the +<dml_expression_clause>+ does not need to use an actual view.
Have a look at AskTom for a discussion on this. Also note that you can also create a view and define an "instead-of" trigger on the view - this particular feature enhances the ability to update DML expressions - but is not a prerequisite.
Note that there can be very significant performance degradation by NOT using an UPDATE on a +<dml_expression_clause>+ and instead coding that manually via PL/SQL.
So do yourself a favour and learn the CORRECT way to resolve the type of UPDATE problem you have. -
Commit after every three UPDATEs in CURSOR FOR loop
DB Version: 11g
I know that experts in here despise the concept of COMMITing inside loop.
But most of the UPDATEs being fired by the code below are updating around 1 million records and it is breaking our UNDO tablespace.
begin
for rec in
(select owner,table_name,column_name
from dba_tab_cols where column_name like 'ABCD%' and owner = p_schema_name)
loop
begin
execute immediate 'update '||rec.owner||'.'||rec.table_name||' set '||rec.column_name|| ' = '''||rec.owner||'';
end;
end loop;
end;We are not expecting ORA-01555 error as these are just batch updates.
I was thinking of implementing something like
FOR i IN 1..myarray.count
LOOP
DBMS_OUTPUT.PUT_LINE('event_key at' || i || ' is: ' || myarray(i));
INSERT INTO emp
empid,
event_id,
dept,
event_key
VALUES
v_empid,
3423,
p_dept,
myarray(i)
if(MOD(i, p_CommitFreq) = 0) --- When the loop counter becomes fully divisible by p_commit_frequency, it COMMITs
then
commit;
end if;
END LOOP;(Found from an OTN thread)
But i don't know how to access the loop counter value in a CURSOR FOR loop.To be fair, what is really despised is code that takes an operation that could have been performed in a single SQL statement and steps through it in the slowest possible way, committing pointlessly as it goes along (exactly like the example you found). Your original version doesn't do that - it looks more like some sort of one-off migration where you have to set every value of every column that matches some naming standard pattern to a constant. If that's the case, and if there are huge volumes involved and you can't simply add a bit more undo, then I don't see much wrong with committing after each update, especially if you track how far you've got so you can restart cleanly if it fails.
If you really want an incrementing counter in an unnamed cursor, apart from the explicit variable others have suggested, you could add rownum to the cursor (alias it to something that isn't an Oracle keyword), although it could complicate the ORDER BY that you might be considering for the restart logic. You could have that instead of the redundant 'owner' column in your example which is always the same as the constant p_schema_name.
Another approach would be to keep track of SQL%ROWCOUNT after each update by adding it to a variable, and commit when the total number of rows updated so far reaches, say, a million.
Could the generated statement use a WHERE clause, or does it really have to update every row in every table it finds?
Could there be more than one column to update per table? If so it might be worth generating one multi-column update statement per table, although it'll complicate things a bit.
btw you don't need the inner 'begin' and 'end' keywords, and whoever supplied the MOD example you found should know that three or four spaces usually make a good indent and you don't need brackets around IF conditions. -
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 -
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". -
Cursor for loop vs bind variable efficiency
PL/SQL
I am going to need to execute many sqls within a cursor for loop.
Note: This is pseudo pl/sql code
for csr_rec in cursor
loop
insert into tablea
select [whateever] from tableb
where column_name = csr_rec.field
versus
execute immediate
'insert into table a select ... where column_name = :1' using csr_rec.field
So the question is whether the first insert statement will be treated as a separate sql statement and need to be parsed each iteration? If so, then I'd likely be much better of using the bind variable approach. (2nd) insert statement.
Thanks!The first statement (static) will be re-used - PL/SQL variables (csr_rec.field in this case) will be used as a bind variable.
-
Cursor For Loop SQL/PL right application? Need help with PL Performance
I will preface this post by saying that I am a novice Oracle PL user, so an overexplanation would not be an issue here.
Goal: Run a hierarchial query for over 120k rows and insert output into Table 1. Currently I am using a Cursor For Loop that takes the first record and puts 2 columns in "Start" section and "connect by" section. The hierarchial query runs and then it inserts the output into another table. I do this 120k times( I know it's not very efficient). Now the hierarchial query doesn't take too long ( run by itself for many parts) but this loop process is taking over 9 hrs to run all 120k records. I am looking for a way to make this run faster. I've read about "Bulk collect" and "forall", but I am not understanding how they function to help me in my specific case.
Is there anyway I can rewrite the PL/SQL Statement below with the Cursor For loop or with another methodology to accomplish the goal significantly quicker?
Below is the code ( I am leaving some parts out for space)
CREATE OR REPLACE PROCEDURE INV_BOM is
CURSOR DISPATCH_CSR IS
select materialid,plantid
from INV_SAP_BOM_MAKE_UNIQUE;
Begin
For Row_value in Dispatch_CSR Loop
begin
insert into Table 1
select column1
,column2
,column3
,column4
from( select ..
from table 3
start with materialid = row_value.materialid
and plantid = row_value.plantid
connect by prior plantid = row.value_plantid
exception...
end loop
exception..
commitBluShadow:
The table that the cursor is pulling from ( INV_SAP_BOM_MAKE_UNIQUE) has only 2 columns
Materialid and Plantid
Example
Materialid Plantid
100-C 1000
100-B 1010
X-2 2004
I use the cursor to go down the list 1 by 1 and run a hierarchical query for each row. The only reason I do this is because I have 120,000 materialid,plantid combinations that I need to run and SQL has a limit of 1000 items in the "start with" if I'm semi-correct on that.
Structure of Table it would be inserted into ( Table 1) after Hierarchical SQL Statement runs:
Materialid Plantid User Create Column1 Col2
100-C 1000 25 EA
The Hierarchical query ran gives the 2 columns at the end.
I am looking for a way to either just run a quicker SQL or a more efficient way of running all 120,000 materialid, plantid rows through the Hierarchial Query.
Any Advice? I really appreciate it. Thank You. -
Problem in executing cursor for loop
hi all,
I am facing following problem.
We are using cron utility on unix to run pl/sql stored procedure.
This procedure in turn calls separate procedures. However any one of the procedure does not end in pl/sql even though it has completed its intended processing.
We are using cursor for loop for data processing and also using database link to fetch data from other instance.
Can anyone help me on possible reasons for this problemThe proc only needs a single 'open s_cursor for ...' statement where the query is a join between all the tables involved. You have obfuscated your query so much in the post that I can't construct it for you (your second select doesn't even join to the 's' table), but the point is that you don't need a cursor loop, just a single query.
-
Urgent help in cursor for loop. PLS HELP HELP HEP
suppose i got table_a, in table_a i've got abc_id and bcd_name. the data as below:
abc_id bcd_name
1 a
1 b
1 c
1 d
in stored procedure as the statement below, i can only select 1 record into a local variable:
select bcd_name
into l_bcd_name
where abc_id = i_abc_id;
how am i going to select all the records? i know it's going to use a cursor for-loop statement but i dont know how to use. any1 can help?
Message was edited by:
babyekcHi,
You can do like this.
Just write the following code in ur Stored Procedure.
CURSOR C1 IS SELECT ABC_ID, BCD_NAME FROM TABLE_A;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO TEMP_ABCID, TEMP_BCDNAME;
EXIT WHEN C1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ABC ID is ' || TEMP_ABCID);
DBMS_OUTPUT.PUT_LINE('BCD NAME is ' || TEMP_BCD_NAME);
END LOOP;
CLOSE C1;
END;
Before declaring the cursor, declare the variables TEMP_ABCID, TEMP_BCDNAME.
Thanks.
Maybe you are looking for
-
I am getting a warning message when i am trying to create a host-named sitecollection.
Hi guys, I am trying to create a host-named site collection. I have created the root site collection. After that i have tried to create customer root site. I have doing this process with the guidance of this link. http://technet.microsoft.com/e
-
Load balancing between two routers
I have two routers connected through the LAN connection. The first one is using as routing protocol EIGRP, the other one is part of the managed service and I do not have access to it. I would like to make a load balancing between the two of them by r
-
HOW TO DEFINE THIS ATTRIBUTE AT SCREEN.
DATA gc_custom_control_name TYPE scrfname VALUE 'CC_ALV'. THANKS VARU.
-
Crash when adding new multi-word event to month view
Recently updated(?) to Leopard from 10.4.11. Now, adding a new event to iCal when in month view often causes a crash. Sequence is: 0) click in desired date box to start new event 1) type first word of event, type space, start typing second word 2) in
-
Internal order and g/l number trying to give in miro screen
hi experts i am facing a problem in miro screen. i want to change the internal order and g/l a/c in miro screen. is it possible to change in miro?as i know this internal order and g/l a/c is generally given at the time of po and grn. but my cleint wa