Why no results when executing PLSQL procedure? - sql

I have written the following PLSQL procedure:
create or replace procedure lrt_bericht (current_date in VARCHAR2, last_date in VARCHAR2) as
calendar_week VARCHAR2(10);
BEGIN
calendar_week := EXTRACT(YEAR FROM sysdate)||'_'||to_char(to_date(current_date,'DD.MM.YYYY'),'IW');
delete from astrid_liste_history
where link_to_uts is null;
insert into astrid_liste_bericht
(Link_to_UTS,Incident_Number,CI_Plus,Site_ID,Anzahl_CI_ID,Anzahl_Zellen,Status_690,Service_Affecting,Incident_Work_Info_Notes,Target_Date,Incident_Work_Info_Summary,Assigned_Group,Submit_Date_max,Last_Modified_Day,Region_CI_Plus,WEATHERMAP_LONGTERM,Incident_Summary,Reported_Date,Status,Company,Incident_Notes,Supercluster,CI_Plus_Cons_Top65,CI_Plus_Cons_Region,CI_Plus_Cons_Year,Last_LRI_Update,Link_to_ATEA,Bereich_Gruppe,Connect_Prio,Connect_Pop_Rank,Categorization_Tier_1,Categorization_Tier_2,Categorization_Tier_3,Date_Import,Time_Import)
select *
from astrid_liste_history
where astrid_liste_history.date_import = current_date;
update astrid_liste_bericht
set Closed_In_CW = calendar_week
where
incident_number in
(select incident_number from astrid_liste_bericht where date_import = last_date
and INCIDENT_WORK_INFO_SUMMARY like '%Volker%'
minus
select incident_number from astrid_liste_bericht where date_import = current_date)
;
update astrid_liste_bericht
set Closed_In_CW = NULL
where date_import not in (last_date)
and Closed_In_CW = calendar_week;
update astrid_liste_bericht
set ADPW = 'Yes'
where
closed_in_cw = calendar_week
and upper(INCIDENT_SUMMARY) like '%ADPW%';
update astrid_liste_bericht
set ADPW = 'No'
where
closed_in_cw = calendar_week
and upper(INCIDENT_SUMMARY) not like '%ADPW%';
COMMIT;
END lrt_bericht;
It compiles sucessfully but after trying to execute it:
begin
lrt_bericht('10.11.2019','03.11.2019');
end;
there is no data written into the astrid_liste_bericht table.
However, if I execute manually every step in the procedure, at the end I can see the data being added/updated in the astrid_liste_bericht table.
Do you have any idea why this happens and what should I do in oder to make the data be updated in the astrid_liste_bericht table via the procedure?

This looks to me like an issue with date mismatch. What is the column type of astrid_liste_history.date_import.
Can you run this query and confirm if data comes back from sql prompt
select *
from astrid_liste_history
where astrid_liste_history.date_import = current_date ;
Replace this current_date with whatever date you are passing to Proc.
Adding test script
CREATE OR REPLACE PROCEDURE temp_proc
(
current_date1 IN VARCHAR2
,last_date IN VARCHAR2
) AS
calendar_week VARCHAR2(10);
BEGIN
calendar_week := extract(YEAR FROM SYSDATE) || '_' ||
to_char(to_date(current_date, 'DD.MM.YYYY'), 'IW');
INSERT INTO temp
(temp1)
SELECT 1 FROM temp2 WHERE temp2.date_import = current_date1;
COMMIT;
END temp_proc;
/
CREATE TABLE temp(temp1 VARCHAR2(100));
/
CREATE TABLE temp2(date_import VARCHAR2(100));
/
INSERT INTO temp2 VALUES('10.11.2019')
SELECT 1 FROM temp2 WHERE temp2.date_import = '10.11.2019';
SET serveroutput ON
BEGIN
temp_proc('10.11.2019', NULL);
END;
/
select *
from temp;

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 procedure insert into table from another table

I have this code from trigger and now i need to create procedure because i cant use trigger.
CREATE OR REPLACE TRIGGER LIVE_MATCHES_TO_MATCHES
instead of insert ON LIVE_MATCHES
for each row
declare
p_priority number:= 1;
p_sport number:=0;
begin
insert into matches(sub_list , priority , sport, created)
select :new.comp_name , p_priority, p_sport,sysdate
from dual
where not exists (
select 1 from matches
where sub_list = :new.comp_name);
end;
this is procedure :
CREATE OR REPLACE PROCEDURE LIVE_MATCHES_SOCCER_T IS
p_priority number := 1;
p_sport number:=0;
begin
INSERT INTO matches("sub_list","priority","sport","created")
SELECT LIVE_MATCHES.COMP_NAME,p_priority,p_sport, sysdate
FROM LIVE_MATCHES WHERE LIVE_MATCHES.COMP_NAME <> matches.SUB_LIST;
commit;
end;
but I m getting error that matches.sub_list is invalid identifier.
How will i create procedure that will insert into table only if sub_list is different from comp_name.. I will set up job that will call this procedure every 5 minutes..
You can use MERGE statement
CREATE OR REPLACE
PROCEDURE PR_INSRT_INTO_MATCHES
IS
P_PRIORITY NUMBER := 1;
P_SPORT NUMBER := 0;
BEGIN
MERGE INTO MATCHES M USING
(SELECT DISTINCT COMP_NAME AS COMP_NAME FROM LIVE_MATCHES
) LM ON (LM.COMP_NAME=M.SUB_LIST)
WHEN NOT MATCHED THEN
INSERT
(
M.SUB_LIST,
M.PRIORITY,
M.SPORT,
M.CREATED
)
VALUES
(
LM.COMP_NAME,
P_PRIORITY,
P_SPORT,
SYSDATE
)
COMMIT;
END;
I think you want:
INSERT INTO matches("sub_list","priority","sport","created")
SELECT lm.COMP_NAME, lm.p_priority, lm.p_sport, sysdate
FROM LIVE_MATCHES lm
WHERE NOT EXISTS (SELECT 1
FROM matches m
WHERE lm.COMP_NAME <> m.SUB_LIST
);
Unless your column names are lower-case (which can only be done in Oracle by using quotes when you create them - and which is not a particularly good idea in any case), then your stored procedure won't work, as you're quoting lower-case identifiers in it. Try this instead:
CREATE OR REPLACE PROCEDURE LIVE_MATCHES_SOCCER_T IS
p_priority number := 1;
p_sport number := 0;
begin
INSERT INTO matches
( sub_list, priority, sport, created )
SELECT LIVE_MATCHES.COMP_NAME, p_priority, p_sport, sysdate
FROM live_matches
WHERE NOT EXISTS ( SELECT 1 FROM matches WHERE LIVE_MATCHES.COMP_NAME = matches.SUB_LIST );
commit;
end;

oracle cursor parameter as collection

it works like:
create or replace procedure back_end_proc(p_rc OUT SYS_REFCURSOR) is
v_script VARCHAR2(4000); begin
v_script := 'select sysdate data from dual where ''a'' = :a union all select sysdate-1 data from dual where ''b'' = :b';
open p_rc for v_script using 'a','b'; end;
when calling the procedure:
DECLARE
rc SYS_REFCURSOR;
BEGIN
victom.back_end_proc2(:rc );
END;
will have an output rows:
DATA
27.06.2017 11:25:02
26.06.2017 11:25:02
THE QUESTION IS:
how to modify the using 'a','b' params into one array or some collection data that will contain 'a','b' as one string or smth like one single value?
If your target query looked like this ...
select * from whatever
where id in ( .... )
it would be quite simple to pass a collection.
create or replace type tt1 as table of varchar2(1);
/
create or replace procedure back_end_proc(
p_ids in tt1
, p_rc OUT SYS_REFCURSOR) is
begin
open p_rc for
'select * from whatever
where id member of :1'
using p_ids;
end;
However, your posted case is slightly more complicated because you want to assign specific values from the collection in each sub-query. This means you need to use a VARRAY because that is the only collection type which guarantees ordering. So:
create or replace type va1 as varray(10) of varchar2(1);
/
create or replace procedure back_end_proc(
p_ids in va1
, p_rc OUT SYS_REFCURSOR) is
begin
open p_rc for
'select sysdate from dual where ''a'' = :1
union all
select sysdate-1 from dual where ''b'' = :2'
using p_ids(1), p_ids(2);
end;

check if values exist in table - trigger

I am trying to write trigger which will control if a record is already in table or not. If is the record already in table (compare for example by name), so current record set valid='False' and insert new. Is there any way?
This is my idea, but it doesn't work.
create or replace TRIGGER
Check_r
before insert on t$customer
FOR each ROW
declare
v_dup number;
v_com number;
v_id number;
v_id_new number;
begin
v_date:=SYSDATE;
select count(id) INTO v_dup from t$customer where surname=:NEW.surname ;
select count(id) INTO v_com from t$customer where firstname =:NEW.firstname and
address=:NEW.address;
select id into v_id from t$customer where surname=:NEW.surname;
if v_dup > 0 and v_com=0 then
v_id_new:= m$_GET_ID; -- get id
update t$customer set valid = 'False' where id = v_id;
insert into t$customer ( id, surname ,firstname, valid, address ) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address);
end if;
if v_dup = 0 then
v_id_new:= m$_GET_ID; -- get id
insert into t$customer ( id, surname ,firstname, valid , address) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address);
end if;
end;
You can use a compound trigger, for example:
CREATE OR REPLACE TRIGGER Check_r
FOR INSERT ON t$customer
COMPOUND TRIGGER
TYPE customerRecordType IS RECORD(
surname t$customer.surname%TYPE,
firstname t$customer.firstname%TYPE,
address t$customer.address%TYPE,
ID nubmer);
TYPE customerTableType IS TABLE OF customerRecordType;
customerTable customerTableType := customerTableType();
n NUMBER;
BEFORE STATEMENT IS
BEGIN
customerTable.DELETE; -- not requried, just for better understanding
END STATEMENT;
BEFORE EACH ROW IS
BEGIN
customerTable.EXTEND;
customerTable(customerTable.LAST).surname := :NEW.surname;
customerTable(customerTable.LAST).firstname := :NEW.firstname;
customerTable(customerTable.LAST).address := :NEW.address;
customerTable(customerTable.LAST).ID := m$_GET_ID;
:NEW.ID := customerTable(customerTable.LAST).ID;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR i IN customerTable.FIRST..customerTable.LAST LOOP
SELECT COUNT(*) INTO n
FROM t$customer
WHERE surname = customerTable(i).surname;
IF n > 1 THEN
UPDATE t$customer
SET valid = 'False'
WHERE surname = customerTable(i).surname;
END IF;
SELECT COUNT(*) INTO n
FROM t$customer
WHERE firstname = customerTable(i).firstname
AND address = customerTable(i).address;
IF n > 1 THEN
UPDATE t$customer
SET valid = 'False'
WHERE firstname = customerTable(i).firstname
AND address = customerTable(i).address
END IF;
END LOOP;
END AFTER STATEMENT;
END;
/
Please note, this solution is ugly and poor in terms of performance!
But it should give you an impression how it works.
In general you should put all this into a PL/SQL Procedure instead of a trigger.
First, this is trigger for insert. you don't need to write insert statement.
Second, you need to update old record. Just update it with your where clause.
CREATE OR REPLACE TRIGGER Check_r
before insert on t$customer
FOR each ROW
BEGIN
UPDATE t$customer set valid = 'False'
WHERE surname = :NEW.surname
AND firstname =:NEW.firstname;
:NEW.id := m$_GET_ID;
END;