The below code is getting many errors. Just want to check if my code syntax is correct. The main logic behind the package is to get all the cases for particular review and spool it to a file using shell script. As of now, am concentrating on the package .
create or replace PACKAGE BODY PK_FCP_EXTRACT is
PROCEDURE sp_fcp_extract is
cursor Rev_cur is select * from t_uar_reviews where CREATED_DATE=trunc(sysdate) ;
r Rev_cur%rowtype;
cursor case_cur( c_revid IN t_uar_reviews.review_id%type )
is select *
from t_uar_cases where review_id= c_revid ;
c case_cur%rowtype;
begin
open Rev_cur;
loop
fetch Rev_cur into r;
exit when Rev_cur%notfound;
open case_cur( r.review_id );
loop
fetch case_cur into c;
exit when case_cur%notfound;
dbms_output.put_line(c.UAR_CASE_ID||','||c.UAR_REVIEW_ID||','||c.CASE_TYPE||','||c.CASE_NMBR||','||c.ACTIVE_FLAG||','|| c.CREATED_DATE);
end loop;
close case_cur;
end loop;
close Rev_cur;
end;
END PK_FCP_EXTRACT;
Your syntax is correct.
The following test code works correctly in an empty schema:
create table t_uar_reviews(
review_id number,
created_date date
)
/
create table t_uar_cases(
review_id number,
UAR_CASE_ID number,
UAR_REVIEW_ID number,
CASE_TYPE varchar2(10),
CASE_NMBR number,
active_flag varchar2(1),
created_date date)
/
create package PK_FCP_EXTRACT is
PROCEDURE sp_fcp_extract;
end;
/
create or replace PACKAGE BODY PK_FCP_EXTRACT is
PROCEDURE sp_fcp_extract is
cursor Rev_cur is select * from t_uar_reviews where CREATED_DATE=trunc(sysdate) ;
r Rev_cur%rowtype;
cursor case_cur( c_revid IN t_uar_reviews.review_id%type )
is select *
from t_uar_cases where review_id= c_revid ;
c case_cur%rowtype;
begin
open Rev_cur;
loop
fetch Rev_cur into r;
exit when Rev_cur%notfound;
open case_cur( r.review_id );
loop
fetch case_cur into c;
exit when case_cur%notfound;
dbms_output.put_line(c.UAR_CASE_ID||','||c.UAR_REVIEW_ID||','||c.CASE_TYPE||','||c.CASE_NMBR||','||c.ACTIVE_FLAG||','|| c.CREATED_DATE);
end loop;
close case_cur;
end loop;
close Rev_cur;
end;
END PK_FCP_EXTRACT;
Possible causes of trouble:
Make sure that the package spec has been created first (CREATE PACKAGE)
Ensure that the package is created in the schema that owns t_uar_reviews and t_uar_cases, or in a schema that has a direct SELECT grant on the tables (not via a role).
Make sure all of the columns you reference in the package exist in the tables.
If those are all done, it should work.
To simplify things, try using this alternate syntax for your cursor loops:
for r in Rev_cur loop
for c in Case_cur(r.review_id) loop
...do something..
end loop;
end loop;
By using this method, you do not need to define the record r or c; they are implicitly created, and you do not to open/fetch/check/close the cursors.
Related
Calling another procedure with insert query(same package).
Procedure 2 is parametized with array as input for manipulation
Approaches Tried:
1-exec CreateShipmentLines(p_result);
2-CreateShipmentLines(p_result);
Compiled sucessfully but record did not get inserted into table.
CREATE or REPLACE package WSH_Delivery_Detail_Shipment is
type Result IS VARRAY(8) OF INTEGER;
p_result Result:=Result();
PROCEDURE CreateShipment(p_delivery_detail_interface_id IN
WSH_DEL_DETAILS_INTERFACE.DELIVERY_DETAIL_INTERFACE_ID%TYPE,p_status OUT
String);
PROCEDURE CreateShipmentLines(p_result IN RESULT);
END WSH_Delivery_Detail_Shipment;
/
CREATE OR REPLACE package body WSH_Delivery_Detail_Shipment as
PROCEDURE CreateShipment(p_delivery_detail_interface_id IN
WSH_DEL_DETAILS_INTERFACE.DELIVERY_DETAIL_INTERFACE_ID%TYPE,p_status OUT
String)
IS
CURSOR wddi_cur IS SELECT * FROM WSH_DEL_DETAILS_INTERFACE WHERE
DELIVERY_DETAIL_INTERFACE_ID=p_delivery_detail_interface_id;
wddi_record WSH_DEL_DETAILS_INTERFACE%ROWTYPE;
p_result Result:=Result(1,1,1,1,1,1,1,1);
BEGIN
OPEN wddi_cur;
LOOP
FETCH wddi_cur into wddi_record;/* Validation2 : Check if Organization Id
exists and store Organization_Id corresponding to Organization_Code*/
EXIT when wddi_cur%NOTFOUND;
>>>>>CODE>>>>>
CreateShipmentLines(p_result); // Calling Procedure 2 for insertion
END LOOP;
CLOSE wddi_cur;
END CreateShipment;
procedure CreateShipmentLines(p_result IN RESULT)
is
BEGIN
INSERT INTO WSH_DELIVERY .......
COMMIT;
END CreateShipmentLines;
END WSH_Delivery_Detail_Shipment;
/
//Program to generate a patient details report based on the input given by the //user
CREATE or REPLACE procedure XX_TEAM18_PROc2
(Admit_date in date,
Bill_amt in number,
action in varchar2)
is
cursor c
is
SELECT P.Patient_name,ph.Symptom_issue Symptom,ph.Consulted_dr Doctor,ph.Diagnosis,ph.Bill_Amount
FROM
XX_Patient_Master_Team18 P,XX_Patient_History_Team18 ph
WHERE
p.Patient_Id=ph.Patient_id
AND
bill_amount action bill_amount;
rec c%rowtype;
cursor c1
is
SELECT P.Patient_name,ph.Symptom_issue Symptom,ph.Consulted_dr Doctor,ph.Diagnosis,ph.Admitted_date Admitted_date
FROM
XX_Patient_Master_Team18 P,XX_Patient_History_Team18 ph
WHERE
p.Patient_Id=ph.Patient_id
AND
Admitted_date action admit_date ;
rec1 c1%rowtype;
begin
open c;
dbms_output.put_line(' records belongs to '||Bill_Amt);
fetch c into rec ;
loop
exit when c%notfound;
dbms_output.put_line(rec.Symptom||' '||rec. Doctor||' '||rec.Diagnosis||' '||rec.bill_Amount);
end loop;
close c;
open c1;
dbms_output.put_line(' records belongs to given '||Admit_date);
fetch c1 into rec1 ;
loop
exit when c1%notfound;
dbms_output.put_line(rec1.Symptom||' '||rec1.Doctor||' '||rec1.Diagnosis||' '||rec1.Admitted_date);
end loop;
close c1;
end ;
You must use dynamic SQL as parameter action cannot be used in a fixed SQL statement within PL/SQL. Parameters can only be used as substitution values, not as column names or operators unless you are using dynamic SQL.
You will need to create a varchar2 variable to hold the SQL statement, then use the DBMS_SQL package to create the cursor. DBMS_SQL has pretty good documentation within it, don't forget to close the cursor when you are done using it.
I don't know how to iterate and update from a query result inside the loop. Is it possible to loop again from the query inside my first loop? Here is my code:
CREATE OR REPLACE PROCEDURE "myTEST" (sp_type in char)
IS
CURSOR c1 IS
SELECT SP_ID FROM CI_SP
WHERE SP_TYPE_CD = sp_type;
sp_id char(10);
item_id_eq CI_SP_EQ.ITEM_ID_EQ%type;
BEGIN
FOR sp_rec in c1
LOOP
DBMS_OUTPUT.PUT_LINE(sp_rec.sp_id);
SELECT ITEM_ID_EQ INTO item_id_eq FROM CI_SP_EQ
WHERE SP_ID = sp_rec.sp_id;
DBMS_OUTPUT.PUT_LINE('item id eq :' || item_id_eq);
-- iterate here for each item_id_eq
-- execute update for each item_id_eq also
END LOOP;
END myTEST;
Instead of looping twice you could just do a join between CI_SP & CI_SP_EQ and get it done in one shot:
CREATE OR REPLACE PROCEDURE "myTEST"(sp_type IN CHAR) IS
BEGIN
FOR item IN (SELECT item_id_eq
FROM ci_sp_eq JOIN ci_sp USING (sp_id)
WHERE sp_type_cd = sp_type) LOOP
-- do your stuff.
NULL;
END LOOP;
END mytest;
I think you wouldn't even need a PL/SQL block, just a simple UPDATE will do, but I don't exactly know what you're trying to do.
Some other comments:
Don't create objects enclosed in "quotes", the object name is now case sensitive. In your case, the compilation will fail because you've created procedure name as "myTEST" and end it with mytest, which Oracle will treat it as "MYTEST" and you'll get compile error because of syntax check fail
Use VARCHAR2 instead of CHAR, CHAR will pad spaces if the input doesn't match the length specifier and will lead to further problems
Let's have a look on my source code:
CREATE OR REPLACE PROCEDURE MAKE_COPY_OF_CLASSROOMS AUTHID CURRENT_USER AS
TYPE classrooms_table_type IS TABLE OF classrooms%ROWTYPE INDEX BY PLS_INTEGER;
classrooms_backup classrooms_table_type;
CURSOR classrooms_cursor IS
SELECT *
FROM classrooms
WHERE year = 1
ORDER BY name;
v_rowcnt PLS_INTEGER := 0;
BEGIN
OPEN classrooms_cursor;
FETCH classrooms_cursor
BULK COLLECT INTO classrooms_backup;
CLOSE classrooms_cursor;
EXECUTE IMMEDIATE 'CREATE TABLE classrooms_copy AS (SELECT * FROM classrooms WHERE 1 = 2)';
--COPY ALL STORED DATA FROM classrooms_backup TO classrooms_copy
END MAKE_COPY_OF_classrooms;
I'm stucked for hours on trying to insert data from "classrooms_backup" into the table "classrooms_copy", which is created by EXECUTE IMMEDIATE command. It's necessary to create table "classrooms_copy" via EXECUTE IMMEDIATE command. I tried to create another EXECUTE command with for loop in it:
EXECUTE IMMEDIATE 'FOR i IN classrooms_backup.FIRST..classrooms_backup.LAST LOOP
INSERT INTO classrooms_copy(id,room_id,year,name)
VALUES(classrooms_backup(i).id,classrooms_backup(i).room_id,classrooms_backup(i).year,classrooms_backup(i).name);
END LOOP;';
But it's road to the hell. I'm retrieving an invalid SQL statement error.
Thanks for your help!
There's no need for much PL/SQL here. Also, try to avoid the keyword CURSOR - there's almost always a better way to do it.
create or replace procedure make_copy_of_classrooms authid current_user as
begin
execute immediate '
create table classrooms_copy as
select *
from classrooms
where year = 1
order by name
';
end make_copy_of_classrooms;
/
I am getting
Error(68,3): PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL.
Please help me out with this.
My code is : -
create or replace PACKAGE BODY FIBRE_TOOLS AS
g_package_name varchar2(30):='FIBRE_TOOLS';
g_proc_name varchar2(30);
..
..
..
procedure prc_purge(p_nb_month IN number default 210) is
reqSelec VARCHAR2(4000);
reqDELDES VARCHAR2(4000);
reqDELINS VARCHAR2(4000);
TYPE Curseur IS REF CURSOR;
c_desinscription Curseur;
TYPE selREC IS RECORD (
EMAIL desinscription.EMAIL%type,
IDRA desinscription.IDRA%type,
D_DATE desinscription.desinscription_date%type
);
TYPE selTABLE IS TABLE OF selREC;
ListeFIB selTABLE;
BEGIN
reqSelec :='select EMAIL,IDRA,desinscription_date from desinscription where desinscription_date < trunc(add_months(sysdate,-'||p_nb_month||'))';
reqDELDES := 'DELETE FROM DESINSCRIPTION WHERE EMAIL=:1 AND IRDA=:2';
reqDELINS := 'DELETE FROM INSCRIPTION WHERE EMAIL=:1 AND IDRA=:2 AND INSCRIPTION_DATE < TRUNC(:3)';
prc_log('Begining of purging procedure');
open c_desinscription for reqSelec;
LOOP
fetch c_desinscription bulk collect into ListeFIB LIMIT 10000;
EXIT WHEN ListeFIB.count = 0;
FORALL i in ListeFIB.first.. ListeFIB.last
EXECUTE IMMEDIATE reqDELDES USING ListeFIB.EMAIL,ListeFIB.IRDA;
EXECUTE IMMEDIATE reqDELINS USING ListeFIB.EMAIL,ListeFIB.IDRA,ListeFIB.D_DATE;
COMMIT;
EXIT WHEN c_desinscription%NOTFOUND;
END LOOP;
close c_desinscription;
COMMIT;
prc_log('Ending of purging procedure');
end prc_purge;
end FIBRE_TOOLS;
I am trying to delete data from two tables based on the two columns getting selected on a criteria I.e. nb_months.
I think problem is with table type and record type. I am confused which way it can be done. As per my knowledge record type shall be used with FORALL. kindly help me on this, as it is very critical.
You're using a DML statement with a FORALL but without binding the collection used - Oracle doesn't allow for that.
Replace execute immediates with the binded collection, should work
EXECUTE IMMEDIATE reqDELDES USING ListeFIB(i).EMAIL,ListeFIB(i).IRDA;
EXECUTE IMMEDIATE reqDELINS USING ListeFIB(i).EMAIL,ListeFIB(i).IDRA,ListeFIB(i).D_DATE;
See more examples in these articles:
Oracle Magazine
Oracle Documentation