Need assistance with IF Exists then Insert - sql

im trying to get this to run but cant figure out why its not. I am trying to create a pl/sql block that will read in 2 codes and make sure they exist before inserting:
declare
v_old_atty_id in atty_rules.attorney_id%type;
v_new_atty_id in atty_rules.attorney_id%type;
type rule_array is varray(10000) of number;
v_rule rule_array;
begin
select distinct rule_id
bulk collect into v_rule
from atty_rules
where attorney_id = v_old_atty_id
and date_activated <= sysdate
and sysdate < nvl(date_deactivated, sysdate+1);
if exists (select attorney_id
from ORG_ATTYS
where attorney_id = v_new_atty_id)
for indx in 1..v_rule.count
loop
insert into atty_rules (attorney_id,rule_id)
values (v_new_atty_id, v_rule(indx));
end loop
else
dbms_output.put_line('Doesnt exist')
end if;
end;
Any direction will help a lot, thank you.

Try this way:
select count(attorney_id)
into v_count
from ORG_ATTYS
where attorney_id = v_new_atty_id
if v_count > 0 then
for indx in 1..v_rule.count
loop
insert into atty_rules (attorney_id,rule_id)
values (v_new_atty_id, v_rule(indx));
end loop
else
dbms_output.put_line('Doesnt exist')
end if;

Maybe don't use bulk collet at all, just do it in a one SQL statement, something like this:
v_old_atty_id := ...
v_new_atty_id := ...
insert into atty_rules (attorney_id,rule_id)
select v_new_atty_id, rule_id
from (
select distinct rule_id
from atty_rules
where attorney_id = v_old_atty_id
and date_activated <= sysdate
and sysdate < nvl(date_deactivated, sysdate+1
)
WHERE exists (select attorney_id
from ORG_ATTYS
where attorney_id = v_new_atty_id);

Related

HOW TO DEAL WITH THESE ERROR ,PL/SQL Compilation unit analysis terminated & PSL-00201 : 'TABLE NAME' MUST BE DECLARED

I am creating a function in Oracle but it's not getting compiled and I am getting two errors
Error 1.
Error: PL/SQL: Compilation unit analysis terminated
Error 2.
Error(2,16): PLS-00201: identifier 'DIV_DUR_PRICE_TABLE' must be
declared
HERE IS THE CODE
CREATE OR REPLACE FUNCTION DIV_DAR(FID IN VARCHAR, DATE1 IN DATE, DATE2 IN DATE)
RETURN DIV_DUR_PRICE_TABLE PARALLEL_ENABLE AS
PRAGMA AUTONOMOUS_TRANSACTION;
CNT NUMBER;
V_RET DIV_DUR_PRICE_TABLE;
BEGIN;
EXECUTE IMMEDIATE 'DELETE from GTT_DIV_DUR_PRICE_TABLE';
Insert Into GTT_DIV_DUR_PRICE_TABLE
(select mydate, column1, column2, 0 as Final_value from tablename)
-- please refer my previous question to understand the code written ahead
declare
v_num integer := 1;
v_column1 number(8,2);
v_column2 number(8,2);
v_Final_value number(8,2);
begin
for rec in (select * from GTT_DIV_DUR_PRICE_TABLE order by mydate)
loop
if(v_num = 1) then
update tab set Final_value = column1 where mydate = rec.mydate;
else
if(rec.column2 is not null) then
update tab set Final_value =
v_Final_value * (v_column1/rec.column1) +
rec.column2 * (v_column1/v_Final_value) where mydate = rec.mydate;
else
update tab set Final_value =
v_Final_value * (rec.column1 / v_column1) where mydate = rec.mydate;
end if;
end if;
v_num:= v_num +1;
v_column1 := rec.column1;
v_column2 := rec.column2;
select final_value into v_Final_value from GTT_DIV_DUR_PRICE_TABLE
where mydate = rec.mydate;
end loop;
end;
SELECT
CAST(
MULTISET(
SELECT * FROM GTT_DIV_DUR_PRICE_TABLE order by P_DATE desc
)AS DIV_DUR_PRICE_TABLE
) INTO V_RET FROM DUAL;
COMMIT;
RETURN V_RET;
END DIV_DAR;

Error: Table or view does not exist in PL SQL package

I have a package called 'S_PKG' in schema 'A'. I want to migrate it into schema B. What I did was I copied the code and executed in B schema. Then I wanted to execute the following pl sql script in which the 'S_PKG' is used in schema B.
select to_char(sysdate,'YYYYMMDD - HH:MI:SS AM') date_time
from dual
/
insert into zzz_ccc
select zzz_ccc_seq.nextval,to_char(sysdate,'YYYYMMDD - HH:MI:SS AM'),
'Start S Load tab',8,user,(select * from global_name)
from dual
/
commit
/
insert into zzz
select zzz_seq.nextval,to_char(sysdate,'YYYYMMDD - HH:MI:SS AM'),
'Start S Load tab',
(select trim(ruser)||' '||trim(rdbase)
from zzz_ccc where ss = 8
and rr = (select max(rr) from zzz_ccc where ss = 8)),
null,null,null,null,null,null,
(select max(rr) from zzz_ccc where ss = 8)
from dual
/
commit
/
DECLARE
PV_PRD_ID VARCHAR2(5);
BEGIN
PV_PRD_ID := '3';
B.S_PKG.PR_MAIN (PV_PRD_ID);
COMMIT;
END;
/
commit
/
insert into tab_counts(created_dtm,
ora_database,ora_user,ora_table,cc,flg,
subj)
select sysdate,'ccenter','aim10_ccenter','s_package_run - rows',
no_of_rows,1,
'S Load Tab Run'
from s_package_run
where to_char(st_date,'YYYYMM-DD') = to_char(sysdate,'YYYYMM-DD')
and package_name = 'LOAD_TAB'
/
commit
/
insert into tab_counts(created_dtm,
ora_database,ora_user,ora_table,cc,flg,
subj)
select sysdate,'ccenter','aim10_ccenter','s_package_run - dur_min',
dur_min,2,
'S Load Tab Run'
from s_package_run
where to_char(st_date,'YYYYMM-DD') = to_char(sysdate,'YYYYMM-DD')
and package_name = 'LOAD_TAB'
/
insert into hrc_chk_mar14_24_1
select sysdate, 'B', 'COUNT 6 ', 's_load_tab',
null,null,null,null
from dual t1
/
insert into zzz
select zzz_seq.nextval,to_char(sysdate,'YYYYMMDD - HH:MI:SS AM'),
'End S Load tab',
(select trim(ruser)||' '||trim(rdbase)
from zzz_ccc where ss = 8
and rr = (select max(rr) from zzz_ccc where ss = 8)),
null,null,
null,null,null,null,
(select max(rr) from zzz_ccc where ss = 8)
from dual
/
commit
/
Then I got the following error.
ORA-00942: table or view does not exist
ORA-06512: at "B.S_PKG", line 109
ORA-06512: at "B.S_PKG", line 35
ORA-06512: at line 5
Then I searched for the package. But I could not find the exact table which gives me the error. Here is my package.
CREATE OR REPLACE PACKAGE BODY B.S_PKG is
PROCEDURE PR_Main(kseq number) IS
sql_stmnt varchar2(5000);
begin
select s_pkg_seq.nextval into dd from dual;
pkg_st_date := sysdate;
sql_stmnt:='truncate table s_msgs';
execute immediate sql_stmnt;
begin
for c_rec in (select * from s_test_1 where pkg_seq = kseq and
flg = 'as' order by pkg_ord)
loop
if substr(c_rec.run_sql,1,1) != '-' then
pkg_name := c_rec.run_sql;
PR_Msgs('*** '||c_rec.run_sql||' Started...', pkg_name||'.'||'pr_main');
else
PR_Msgs(c_rec.run_sql, pkg_name||'.'||'pr_main');
end if;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
PR_LOAD_PRODUCT3(1,kseq);
PR_LOAD_PRODUCT3(2,kseq);
PR_LOAD_PRODUCT3(3,kseq);
PR_LOAD_PRODUCT3(4,kseq);
PR_LOAD_PRODUCT3(5,kseq);
PR_LOAD_PRODUCT3(6,kseq);
PR_LOAD_PRODUCT3(7,kseq);
PR_LOAD_PRODUCT3(8,kseq);
PR_LOAD_PRODUCT3(9,kseq);
PR_LOAD_PRODUCT3(10,kseq);
PR_LOAD_PRODUCT3(11,kseq);
begin
for c_rec in (select * from s_test_1 where pkg_seq = kseq and
flg = 'ae' order by pkg_ord)
loop
if substr(c_rec.run_sql,1,1) != '-' then
PR_Msgs('*** '||c_rec.run_sql||' End OK...', pkg_name||'.'||'pr_main');
else
PR_Msgs(c_rec.run_sql, pkg_name||'.'||'pr_main');
end if;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
sql_stmnt:='insert into s_msgs_his select * from s_msgs where msg_ord > 0';
execute immediate sql_stmnt;
pkg_en_date := sysdate;
insert into s_package_run values (pkg_st_date,pkg_en_date,floor((pkg_en_date-pkg_st_date)*24*60),
(pkg_en_date-pkg_st_date)*24*60*60 - floor((pkg_en_date-pkg_st_date)*24*60)*60,gv_count,
pkg_name,null,dd);
end;
-- ==============================================================================================
-- ==============================================================================================
PROCEDURE PR_LOAD_PRODUCT3(pseq number, tseq number) is
sql_stmnt VARCHAR2(5000);
begin
prc_st_date := sysdate;
begin
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'bs' order by pkg_ord)
loop
prc_name := c_rec.run_sql;
PR_Msgs(c_rec.run_sql||' Started...', pkg_name||'.'||'pr_main');
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
begin
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'aa' order by pkg_ord)
loop
sql_stmnt := c_rec.run_sql;
execute immediate sql_stmnt;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
begin
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'be' order by pkg_ord)
loop
if substr(c_rec.run_sql,1,1) != '-' then
PR_Msgs(c_rec.run_sql||' End OK...', pkg_name||'.'||'pr_main');
else
PR_Msgs(c_rec.run_sql, pkg_name||'.'||'pr_main');
end if;
insert into s_test_3
values(sysdate,c_rec.run_sql,c_rec.pkg_seq,c_rec.pkg_ord,c_rec.prc_seq);
end loop;
end;
select cc into gv_count
from cr2_test_2;
prc_en_date := sysdate;
insert into s_procedure_run values (prc_st_date,prc_en_date,floor((prc_en_date-prc_st_date)*24*60),
(prc_en_date-prc_st_date)*24*60*60 - floor((prc_en_date-prc_st_date)*24*60)*60,gv_count,
prc_name,pkg_name,dd);
end;
-- ==============================================================================================
-- ==============================================================================================
PROCEDURE PR_Msgs(pv_msg varchar2, pv_point varchar2) as
cc number(5);
Begin
select s_pkg2_seq.nextval into cc from dual;
insert into s_msgs values (sysdate, pv_msg, pv_point, user, '','',cc);
commit;
End;
-- ==============================================================================================
-- ==============================================================================================
END S_PKG;
/
Can anyone help me to find the error as I am new to PL SQL packages?
As far as I can tell, if you compiled the package when connected as user B and it was successful, then the only "unknown" information at that time is this:
sql_stmnt:='truncate table s_msgs';
i.e. the table you're truncating using dynamic SQL. sql_stmnt's value is a string, compiler doesn't check what's in there. But, when you actually execute it, then it finds out that there's no table s_msgs in user B's schema.
The same goes for
sql_stmnt:='insert into s_msgs_his select * from s_msgs where msg_ord > 0';
and table s_msgs_his.
As you moved everything from A to B, I guess that you should do the same with those tables. Do that and then try to run your code again.
[EDIT]
This is line 109:
for c_rec in (select * from s_test_1 where pkg_seq = tseq and
prc_seq = pseq and flg = 'aa' order by pkg_ord)
loop
sql_stmnt := c_rec.run_sql;
execute immediate sql_stmnt; --> line 109
Check what's written in S_TEST_1. Looks like some statement that is supposed to be executed dynamically, but - the table involved into it doesn't exist in schema B (or that user doesn't have privileges to use it).

Oracle Insert Into If NOT Exist

I'm wirting and Pl_SQL Script to do some inserts if an condition not Exist
and its not working for me :(
this is my code
paramS in an CURSOR
FOR ps IN paramS LOOP
compteur := 5;
LOOP
IF NOT EXISTS
(SELECT *
FROM carp.Table1
WHERE FK_tab1 =ps.id_tab1
AND DIC_TYPE = compteur
)
BEGIN
INSERT
INTO carp.Table1
(
id,
FK_tab1,
DIC_TYPE
)
VALUES
(
id.nextval ,
ps.id_tab1 ,
compteur
)
END
compteur:=compteur-1;
commit;
EXIT WHEN compteur <0;
END LOOP;
END LOOP;
thanks in advance
Usually I use such checking , If not exists doesnt work on oracle (as far as I know)
DECLARE
CNT NUMBER(4);
BEGIN
SELECT COUNT(1) INTO CNT
FROM carp.Table1
WHERE FK_tab1 =ps.id_tab1
AND DIC_TYPE = compteur
IF CNT = 0 THEN
INSERT
INTO carp.Table1
(
id,
FK_tab1,
DIC_TYPE
)
VALUES
(
id.nextval ,
ps.id_tab1 ,
compteur
)
End IF;
END;
/
commit
/
You can use NO_DATA_FOUND exception
BEGIN
SELECT * FROM carp.Table1
WHERE FK_tab1 = ps.id_tab1
AND DIC_TYPE = compteur
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO carp.Table1 (id, FK_tab1, DIC_TYPE)
VALUES(id.nextval, ps.id_tab1, compteur);
COMMIT;
END
You can avoid count() using:
DECLARE FG_EXISTS NUMBER(1);
BEGIN
SELECT CASE WHEN EXISTS(SELECT 1
FROM CARP.TABLE1
WHERE FK_TAB1 =PS.ID_TAB1
AND DIC_TYPE = COMPTEUR
) THEN 1 ELSE 0 END INTO FG_EXISTS
FROM DUAL;
IF FG_EXISTS = 0 THEN INSERT ...

PL/SQL: ORA-00904: : invalid identifier

I am running the following SP but getting the error c1.pyid is invalid identifier. I am trying to use two different query results from one cursor. If there is any other way of using IF-else clause in a cursor, i am open to that too.
CREATE OR REPLACE
PROCEDURE FIX_DOCUMENT_RECORDS ( i_flag in varchar)
AS
Op_ID VARCHAR(8);
Op_Name VARCHAR(32);
skill VARCHAR(32);
temp_count VARCHAR(8);
temp_status VARCHAR(8):='Submitted';
QRYSTR VARCHAR2(400);
TYPE REF_CUR IS REF CURSOR;
c1 REF_CUR;
BEGIN
IF (i_flag='1') THEN
QRYSTR:='SELECT *
FROM dims_doc_master
WHERE concat_prod_id IS NULL
OR documenttypeid IS NULL
AND (pystatuswork = temp_status);';
ELSE
QRYSTR:='SELECT *
FROM dims_doc_master
WHERE (documentimageid IS NULL
AND p8id IS NULL)
AND (pystatuswork = temp_status);';
END IF;
open c1 FOR QRYSTR;
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('loop begin');
UPDATE DIMS_DOC_MASTER
SET pystatuswork ='Cancelled',
documentstatus ='Cancelled',
cancellationdate='31-JAN-14',
cancelledbysid = c1.pxcreateoperator,
cancelreason ='Cancelled due to corruption.'
WHERE pyid =c1.pyid;
DBMS_OUTPUT.PUT_LINE('After updation'||c1.pyid );
--Begin PC_DOCUMENT UPDATION
UPDATE PC_DOCUMENT
SET pystatuswork ='Cancelled',
cancellationdate='31-JAN-14'
WHERE pyid =c1.pyid;
--Begin insert into History
--Select Operator name and ID
SELECT skill
INTO skill
FROM operator_map_skill
WHERE pyuseridentifier=c1.pxcreateoperator
AND rownum =1;
INSERT
INTO DIMS_DOC_HIST
(
DIMS_DOC_ID,
DOC_CHG_USR,
DOC_CHG_DT,
DOC_NEW_STS,
DOC_CHG_CMNT,
CRE_TS,
ROLE,
RSN_DESC,
TARGETROLE,
DOC_CHG_USR_ID,
DOC_ASG_USR_ID,
DOC_ASG_USR,
PREVSTATUS,
PREVSTATUSDT,
ASSIGNEDTODT,
TODISPLAY,
ACTIVITY_NAME
)
VALUES
(
c1.pyid,
'DIMS',
systimestamp,
'Cancelled',
'Cancelled due to corruption',
'31-JAN-14',
skill,
NULL,
skill,
c1.pxcreateoperator,
c1.pxcreateoperator,
c1.pxcreateopname,
'Submitted',
NULL,
systimestamp,
'Y',
'Updation through Script'
);
dbms_output.put_line
(
'Document ID= '||c1.pyid
)
;
SELECT COUNT(*)
INTO temp_count
FROM PC_ASSIGN_WORKBASKET
WHERE pxrefobjectinsname=c1.pyid;
IF(temp_count IS NOT NULL) THEN
DELETE FROM PC_ASSIGN_WORKBASKET WHERE pxrefobjectinsname=c1.pyid;
ELSE
DELETE FROM PC_ASSIGN_WORKLIST WHERE pxrefobjectinsname=c1.pyid;
END IF;
COMMIT;
END;
END LOOP;
CLOSE c1;
END;
You seem confusing cursor and fetched row.
In your current procedure: you open a cursor, do a loop (which looks to be endless since there is no EXIT statement), and after the loop you close the cursor (but it looks it will never happen)
To fetch results from a cursor, do the following:
CREATE OR REPLACE PROCEDURE ...
...
c1 REF_CUR;
ddm_record dims_doc_master%rowtype;
BEGIN
...
OPEN c1;
LOOP
FETCH c1 INTO ddm_record;
EXIT WHEN c1%NOTFOUND;
...
DBMS_OUTPUT.PUT_LINE('Document ID= ' || ddm_record.pyid); -- not c1.pyid
END LOOP;
CLOSE c1;
END;
/
Inspired from examples here: http://plsql-tutorial.com/plsql-explicit-cursors.htm
Try embedding the flag in your where clause:
open c1 FOR
SELECT *
FROM dims_doc_master
WHERE (i_flag='1' AND
(concat_prod_id IS NULL
OR documenttypeid IS NULL
AND (pystatuswork = temp_status))
OR (i_flag<>'1' AND
(documentimageid IS NULL
AND p8id IS NULL)
AND (pystatuswork = temp_status));
The logic can probably be simplified but logically that would work.

How to get Numbers in number range by PL-Sql .?

here is my serial table.it has more than 1000 records.its with start number and end number.but between numbers not exist.
i need to add all number [start/between & end numbers] records in another temp table number by number
like below
EXIST TABLE
select concat(CARD_BULK_CODE,start_serial) startserial,concat(CARD_BULK_CODE,end_serial) endserial
from TSR_BULK_CARD_SERIALS
---------------------------
STARTSERIAL ENDSERIAL |
---------------------------
18126944 18126946 |
18141101 18141122 |
15150722 15150729 |
19069303 19069317 |
---------------------------
REQUIRED TABLE
-----------
SERIAL_NO |
-----------
18126944
18126945
18141101
18141102
....
-----------
seem its need pl-sql to implement this.
please help me to sort out this issue
I tried with below query with the help of dual.
but its very slow and not yet got results :-) running more than 1 Hour
select distinct concat(t.CARD_BULK_CODE,t.START_SERIAL)+level-1 SERIAL
from TSR_BULK_CARD_SERIALS t, dual
connect by level-1<=(concat(t.CARD_BULK_CODE,t.END_SERIAL ))-concat(t.CARD_BULK_CODE,t.START_SERIAL)
order by 1
EDIT :
Dear Alen & Dba.i tried with your ones and below error occured.
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (select concat(card_bulk_code, start_serial) startserial,concat(card_bulk_code, end_serial) endserial from tsr_bulk_card_serials)
LOOP
l_st := rec.startserial;
l_en := rec.endserial;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO temp(serial_no) values(rec1);
END LOOP;
END LOOP;
COMMIT;
END;
Error at line 1
ORA-01426: numeric overflow
ORA-06512: at line 9
Script Terminated on line 1.
One way to do it without resorting to plsql
WITH ranges AS
(
SELECT CONCAT(CARD_BULK_CODE, start_serial) startserial,
CONCAT(CARD_BULK_CODE, end_serial) endserial
FROM TSR_BULK_CARD_SERIALS
),
numbers(n) AS (
SELECT 0 n
FROM dual
UNION ALL
SELECT n + 1
FROM numbers
WHERE n <=
(
SELECT MAX(endserial - startserial)
FROM ranges
)
)
SELECT t.startserial + n.n SERIAL_NO
FROM ranges t JOIN numbers n
ON n.n <= t.endserial - t.startserial
ORDER BY SERIAL_NO
Here is SQLFiddle demo
Just write some PL/SQL - iterate through your table and insert rows in the temp table.
declare
l_start number;
l_end number;
begin
for r_rec in (select to_number(concat(card_bulk_code, start_serial)) startserial
, to_number(concat(card_bulk_code, end_serial)) endserial
from tsr_bulk_card_serials )
loop
l_start := r_rec.startserial;
l_end := r_rec.endserial;
for l_i in l_start..l_end loop
insert into your_temp_table;
end loop;
end loop;
end;
Try like this,
WITH t(ST, EN) AS
(
SELECT 18126944, 18126946 FROM dual
UNION
SELECT 18141101, 18141122 FROM dual
UNION
SELECT 15150722, 15150729 FROM dual
UNION
SELECT 19069303 , 19069317 FROM dual
)
SELECT DISTINCT st + LEVEL -1
FROM t
CONNECT BY LEVEL <= (SELECT en - st + 1 FROM DUAL)
ORDER BY 1;
/
Try something like this for PL/SQL,
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (SELECT * FROM t)
LOOP
l_st := rec.st;
l_en := rec.en;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO <your_tab>;
END LOOP;
END LOOP;
COMMIT;
END;
DECLARE
l_st NUMBER (20);
l_en NUMBER (20);
testnum NUMBER (4);
BEGIN
FOR rec IN (SELECT CONCAT (card_bulk_code, start_serial) startserial,CONCAT (card_bulk_code, end_serial) endserial FROM tsr_bulk_card_serials)
LOOP
l_st := TO_NUMBER (rec.startserial);
l_en := TO_NUMBER (rec.endserial);
testnum := l_en - l_st;
DBMS_OUTPUT.put_line (l_st);
DBMS_OUTPUT.put_line (l_en);
IF l_st < l_en
THEN
FOR rec1 IN 0 .. testnum
LOOP
l_st := l_st + 1;
INSERT INTO temp(serial_no) VALUES (l_st);
END LOOP;
END IF;
END LOOP;
COMMIT;
END;
above code helped me to sorted my issue
thanks all :-)