PROCEDURE Warning: execution completed with warning - sql

I'm having a problem with this procedure. The error I keep receiving is:
dbms_warning.set_warning_setting_string 'ENABLE:ALL', succeeded.
PROCEDURE promo_ship_sp compiled
Warning: execution completed with warning
I have tried setting error reporting on so I would get a little bit more information, but nothing else shows up. SELECT * FROM BB_PROMOLIST; shows results in 0 rows fetched so it can't be an insert id issue can it? I have commited it, and it still fails to compile successfully.
set serveroutput on;
CALL DBMS_WARNING.set_warning_setting_string ('ENABLE:ALL', 'SESSION');
create or replace procedure promo_ship_sp
(
tmp_id in date
)
IS
v_dt date := tmp_id;
v_Promo_flag bb_promolist.promo_flag%type;
cursor cur_select is
select idshopper, dtcreated
from bb_basket
where dtcreated < v_dt
order by idshopper;
BEGIN
for rec_something in cur_select loop
insert into bb_promolist (idshopper, month, year, promo_flag, used) values
(rec_something.idshopper, 'JAN', '2010', 1, 'N');
dbms_output.put_line(rec_something.idshopper || ' ' ||rec_something.dtcreated);
end loop;
END;
/
show errors;
execute promo_ship_sp('15-FEB-07');
GOOD Catch on the stack overflow, but that wasn't it on my actual code. I disabled the constraints and then compiled without warnings and then enabled the constraints again and can execute it as many times as I please. Kinda wierd bug. Hope this helps someone.
set serveroutput on;
CALL DBMS_WARNING.set_warning_setting_string ('ENABLE:ALL', 'SESSION');
create or replace procedure promo_ship_sp
(
tmp_id in date
)
IS
v_dt date := tmp_id;
v_Promo_flag bb_promolist.promo_flag%type;
cursor cur_select is
select idshopper, dtcreated
from bb_basket
where dtcreated < v_dt
order by idshopper;
BEGIN
delete from bb_promolist;
for rec_something in cur_select loop
insert into bb_promolist (idshopper, month, year, promo_flag, used) values
(rec_something.idshopper, to_char(rec_something.dtcreated, 'MON'), to_char(rec_something.dtcreated, 'YYYY'), 1, 'N');
end loop;
END;
/
show errors;
execute promo_ship_sp('15-FEB-07');

Not an answer to your question but too long for a comment.
Please replace the cursor, the cursor for loop and the insert ... values with:
insert into bb_promolist (idshopper, month, year, promo_flag, used)
select idshopper, to_char(dtcreated, 'MON'), to_char(dtcreated, 'YYYY'), 1, 'N'
from bb_basket
where dtcreated < v_dt;
Include the order by clause only if you have a good reason, such as putting data with the same values on the same block:
insert into bb_promolist (idshopper, month, year, promo_flag, used)
select idshopper, to_char(dtcreated, 'MON'), to_char(dtcreated, 'YYYY'), 1, 'N'
from bb_basket
where dtcreated < v_dt
order by idshopper;

Related

Nested Loops In Oracle Not Work Correctly (Exceeds the maximum)

I wrote These Two queries For Sample Table to insert into "z_exp14_resualt" From "z_exp14_main ". The First Query Works Correctly (Null) But Second That For rows have due_date on the main table (Not Null), not works correctly! . I Think Problem is The loop. It started before the due date and even goes beyond that . For NOT Nulls Insert must start from today(year and monts from sysdate and day from opening_date) and continue until due_date
Calculate For Null DUE_DATES
declare
i number := 1;
BEGIN
for i in 1..12 loop
insert into z_exp14_resualt
select dep_id,ADD_MONTHS(ADD_MONTHS(opening_date,trunc( months_between (sysdate,opening_date))),i),rate*balance
from z_exp14_main
WHERE due_date IS null;
end loop;
END;
/
And For Not Null Due_dates
DECLARE
diff number;
x number :=1;
BEGIN
for i in (select * FROM z_exp14_main WHERE due_date IS NOT null) loop
diff :=trunc( months_between (sysdate,i.opening_date));
WHILE (ADD_MONTHS(ADD_MONTHS(i.opening_date,diff),x)<i.due_date) LOOP
insert into z_exp14_resualt
select dep_id,ADD_MONTHS(ADD_MONTHS(i.opening_date,diff),x),rate*balance
from z_exp14_main WHERE due_date is not null ;
x :=x+1;
end loop;
end loop;
end;
/
sample Date On Main (z_exp14_main)
--
DEP_ID
DUE_DATE
BALANCE
RATE
OPENING_DATE
--
20056634
null
283428
10
15-SEP-16
--
20056637
null
180222
10
07-NOV-14
--
20056639
null
58741
10
28-AUG-14
--
40000020
27-NOV-21
5000000
22
31-MAR-14
--
40000023
23-APR-21
63000000
22
25-AUG-18
The Problem Is In the "While" condition. I correct it And This Is Final Answer:
DECLARE
diff number;
x number ;
BEGIN
for i in (select * FROM z_exp14_main WHERE due_date IS NOT null) loop
diff :=trunc( months_between (sysdate,i.opening_date));
x:=0;
WHILE (add_months(sysdate,x)<i.due_date) LOOP
insert into z_exp14_resualt values (i.dep_id,ADD_MONTHS(ADD_MONTHS(i.opening_date,diff),x),(i.rate*i.balance) );
x :=x+1;
end loop;
end loop;
end;
/

global temporary table in db2 stored procedure

Just getting into DB2, and have decided to use global temporary table in my stored proc for my task.
The task would be the next:
just populate some data for each day (during for example 5 days), selecting random rows from the other table
I'm getting my date like:
select id from (
select id, rand() rnd from source_table)
where rnd>0
order by rnd
fetch first 1000 rows only
I wanted to store somewhere that list of int to reuse them. The idea was the next -
create table test (id int, dt date);
create or replace procedure proc1 ()
begin
declare v_start date default '2018-05-25';
declare v_end date default '2018-05-30';
declare v_dml varchar(8000);
/* this part so far doesn't work
declare global temporary table
session.temp_tab(id int)
not logged on commit preserve;
insert into session.temp_tab(id)
select id from my_table;*/
while v_start <= v_end DO
set v_dml = 'insert into test (id, dt)
with t as (
select 1 id, '''||v_start||''' dt from sysibm.dual
union
select 2 id, '''||v_start||''' dt from sysibm.dual
union
select 3 id, '''||v_start||''' dt from sysibm.dual)
select *
from t
where id in (1,3)';
/*instead of 1,3 I would like to have list of values in some temp
table/array..., which I'll get
from the other table and can just use duriing this proc
I don't want to use sub select, because I'll get every time some random
data. But also I need that list for filter in several insert/update
statements*/
set v_start = v_start +1 day;
execute immediate v_dml;
commit;
end while;
end
P.S. I use DB2 LUW v10.5.0.7
UPD_1:
I would like to do DDL and DML operation in one loop. For example I want to add partititon and then insert the data to the same table. like this:
create or replace procedure proc1 (
in in_rep int)
begin
declare v_dt date;
declare v_end_dt date;
declare v_add_part varchar(1024);
declare v_id int;
declare v_next_id int;
select max(id), max(dt)
into v_id, v_dt
from test;
set v_end_dt = v_dt + in_rep day;
while v_dt < v_end_dt DO
set v_dt = v_dt +1 day;
set v_next_id = v_id+1;
set v_add_part = 'alter table TEST
add PARTITION part_'||v_next_id||'
starting from '||v_next_id||' ending at '||v_next_id;
execute immediate v_add_part;
insert into test (id, dt)
select v_next_id, v_dt
from sysibm.dual;
end while;
end
In this case I would get an error, SQLCODE=-327, SQLSTATE=22525
THE ROW CANNOT BE INSERTED BECAUSE IT IS OUTSIDE THE BOUND OF THE PARTITION RANGE FOR THE LAST PARTITION.
Cause of I'm trying to alter table and insert in the same time, not step by step. But can't really get how to do it step by step excep of replace insert with dynamic sql, like:
set v_add_part = 'alter table TEST
add PARTITION part_'||v_next_id||'
starting from '||v_next_id||' ending at '||v_next_id;
set v_ins = 'insert into test (id, dt)
select '||v_next_id||','''||v_dt||'''
from sysibm.dual';
execute immediate v_add_part;
execute immediate v_ins;
Here is an example of using the RAND() function to populate the session table.
Notice that the insert statement gets compiled only one time, but executed as many times as the date-range.
For production use you should add relevant error-handling.
create or replace procedure proc1 ()
language sql
specific proc1
begin
declare v_start date default '2018-05-25';
declare v_end date default '2018-05-30';
declare v_dml varchar(8000);
declare global temporary table
session.temp_tab(id int not null)
with replace not logged on commit preserve rows;
insert into session.temp_tab(id)
select int(rand()*1000) as random
from my_table order by random fetch first 1000 rows only;
set v_dml = 'insert into test (id, dt)
select t.id ,cast(? as date) from session.temp_tab as t ' ;
prepare s1 from v_dml;
while v_start <= v_end do
execute s1 using v_start;
set v_start = v_start + 1 day;
end while;
commit;
end
If you use Data Studio, that will parse your code locally and hi-light any syntax errors. The procedure creates for me (on Db2 11.1 anyway) once I added the work ROWS after PRESERVE
create or replace procedure proc1 ()
begin
declare v_start date default '2018-05-25';
declare v_end date default '2018-05-30';
declare v_dml varchar(8000);
-- this part so far doesn't work
declare global temporary table
session.temp_tab(id int)
not logged on commit preserve rows;
insert into session.temp_tab(id)
select id from my_table;
while v_start <= v_end DO
set v_dml = 'insert into test (id, dt)
with t as (
select 1 id, '''||v_start||''' dt from sysibm.dual
union
select 2 id, '''||v_start||''' dt from sysibm.dual
union
select 3 id, '''||v_start||''' dt from sysibm.dual)
select *
from t
where id in (1,3)';
/*instead of 1,3 I would like to have list of values in some temp
table/array..., which I'll get
from the other table and can just use duriing this proc
I don't want to use sub select, because I'll get every time some random
data. But also I need that list for filter in several insert/update
statements*/
set v_start = v_start +1 day;
execute immediate v_dml;
commit;
end while;
end
BTW your code would be better (IMHO) using a variable and static SQL rather than dynamically building a SQL statement. Also you can use VALUES with multiple rows, no need to select from a dummy DUAL tables.
I'm not sure what your task is, but I'm not sure you are close to the best solution here... ;-)

ORA-01403 - no data found -- even though cursor SELECT statement is running fine

declare
CURSOR C1 IS
Select to_date(DateRange,'dd-mm-rrrr') DateRange
from (select to_date('01-JAN-2016','DD-MON-RRRR') - 1 + level as DateRange
from DUAL
where (TO_DATE('01-JAN-2016', 'DD-MON-RRRR') - 1 + level) <= LAST_DAY(TO_DATE('31-DEC-2016', 'DD-MON-RRRR'))
connect by level<=366)
where substr(to_char(DateRange,'DAY'),1,3) in ('SUN','SAT');
begin
if not c1%ISopen
then
open C1;
end if;
dbms_output.put_line("Cursor is created and number of affected rows are: " || c1%rowcount);
close c1;
end;
/
Even though the select statement used in Creating Cursor is running fine, but when i am trying to execute the code it is throwing error -- ORA-01403 - no data found
You open the cursor, but do not fetch it.
From documentation:
%ROWCOUNT Attribute A cursor attribute that can be appended to the
name of a cursor or cursor variable. When a cursor is opened,
%ROWCOUNT is zeroed. Before the first fetch, cursor_name%ROWCOUNT
returns 0. Thereafter, it returns the number of rows fetched so far.
The number is incremented if the latest fetch returned a row.
The code should be something like this:
DECLARE
CURSOR C1
IS
SELECT TO_DATE (DateRange, 'dd-mm-rrrr') DateRange
FROM ( SELECT TO_DATE ('01-JAN-2016', 'DD-MON-RRRR') - 1 + LEVEL
AS DateRange
FROM DUAL
WHERE (TO_DATE ('01-JAN-2016', 'DD-MON-RRRR') - 1 + LEVEL) <=
LAST_DAY (TO_DATE ('31-DEC-2016', 'DD-MON-RRRR'))
CONNECT BY LEVEL <= 366)
WHERE SUBSTR (TO_CHAR (DateRange, 'DAY'), 1, 3) IN ('SUN', 'SAT');
a DATE;
BEGIN
IF NOT c1%ISOPEN
THEN
OPEN C1;
END IF;
LOOP
FETCH c1 INTO a;
EXIT WHEN C1%NOTFOUND;
END LOOP;
DBMS_OUTPUT.put_line (
'Cursor is created and number of affected rows are: ' || c1%ROWCOUNT);
CLOSE c1;
END;
/
Your select statement is not right. Replace to_date with to_char.
declare
CURSOR C1 IS
select to_char(DateRange,'dd-mm-rrrr') DateRange --replaced to_date with to_char
from
(
select to_date('01-JAN-2016','DD-MON-RRRR') - 1 + level as DateRange
from DUAL
where (TO_DATE('01-JAN-2016', 'DD-MON-RRRR') - 1 + level) <= LAST_DAY(TO_DATE('31-DEC-2016', 'DD-MON-RRRR'))
connect by level<=366
)
where substr(to_char(DateRange,'DAY'),1,3) in ('SUN','SAT');
begin
if not c1%ISopen
then
open C1;
end if;
dbms_output.put_line("Cursor is created and number of affected rows are: " || c1%rowcount);
close c1;
end;
/
From inner query you are returning a date but in the main select clause you are using to_date on a date which might be why you are not getting desired result.

unable to create Procedure

Table a:
PROTOCOL VARCHAR2(20)
Table b:
YEAR NUMBER(4)
MONTH VARCHAR2(20)
PROTOCOL VARCHAR2(20)
DATE1 DATE
My procedure code:
CREATE PROCEDURE his
#Year NUMBER(4),
#Month VARCHAR2(20)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION trninsert
DECLARE ##date DATE
SET ##date = sysdate;
INSERT INTO b (Year, month, date1, protocol)
(select #Year, #Month, ##date,* from a)
COMMIT TRANSACTION trninsert
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION trninsert
END CATCH
END
I am using plsql developer and it is showing errors in procedure.
you've written this a mysql type syntax.
oracle would be:
CREATE PROCEDURE his(p_year b.year%type,
p_month b.month%type)
AS
BEGIN
INSERT INTO b (Year, month, date1, protocol)
select p_year, p_month, sysdate, a.protocol
from a;
commit;
END;
though its bad form to commit in the procedure.
eg:
SQL> CREATE PROCEDURE his(p_year b.year%type,
2 p_month b.month%type)
3 AS
4 BEGIN
5 INSERT INTO b (Year, month, date1, protocol)
6 select p_year, p_month, sysdate, a.protocol
7 from a;
8 commit;
9 END;
10 /
Procedure created.
SQL> insert into a values('prot a');
1 row created.
SQL> exec his(2012, 10)
PL/SQL procedure successfully completed.
SQL> select * from b;
YEAR MONTH PROTOCOL DATE1
---------- -------------------- -------------------- ---------
2012 10 prot a 06-FEB-13
SQL>
Your procedure is not in a valid format: Change your entire structure with,
CREATE [OR REPLACE] PROCEDURE procedure_name
[ (parameter [,parameter]) ]
IS
[declaration_section]
BEGIN
executable_section
[EXCEPTION
exception_section]
END [procedure_name];
For more parameters: Click here
yeah you have not use the plsql syntax:
Code will be:
CREATE OR REPLACE PROCEDURE his
(Year b.year%type,
Month b.month%type)
AS
BEGIN
INSERT INTO b (Year, month, date1, protocol)
VALUES select Year, Month, sysdate,a.protocol from a ;
COMMIT;
END;

procedure to check if dates of new row overlaps with existing dates in the table

I am trying to write a procedure to check if parameters given (dates) lie between any of the existing dates in the table. And if not insert new row.
CREATE OR REPLACE PROCEDURE test(date1 IN DATE, date2 IN DATE) AS
ddate1 DATE;
ddate2 DATE;
quer VARCHAR2(50);
BEGIN
SELECT fdate, tdate INTO ddate1, ddate2 FROM dataHolder;
IF (ddate1 < date1) AND (ddate2 > date2) THEN
quer := 'invalid';
ELSE
INSERT INTO dataHolder VALUES (date1, date2);
quer := 'success';
END IF;
DBMS_OUTPUT.PUT_LINE(quer);
END;
/
I have tried something like this but when executed I get this error:
ORA-01422: exact fetch returns more than requested number of rows
You are getting that error because your select statement returns more than one record. To simplify the process you could use merge statement and rewrite your procedure as follows:
CREATE OR REPLACE PROCEDURE test(date1 IN DATE, date2 IN DATE) AS
BEGIN
merge into Dataholder dh
using dual
on ((date1 < dh.fdate) and (date2 < dh.tdate))
when not matched then
insert (dh.fdate, dh.tdate)
values(date1, date2);
if sql%rowcount > 0
then
dbms_output.put_line('success');
else
dbms_output.put_line('invalid');
end if;
END;
Your select statement fetches more than record whereas your code expects only one, since you're fetching into single-value variables. You could use BULK COLLECT and collect all the dates into a collection of dates, but I think you can improve on it with the code below:
CREATE OR REPLACE PROCEDURE test(date1 IN DATE, date2 IN DATE) AS
ddate1 DATE;
ddate2 DATE;
invalidRecords NUMBER := 0;
quer VARCHAR2(50);
BEGIN
SELECT COUNT(1) INTO invalidRecords FROM dataHolder WHERE fdate < date1 AND tdate > date2;
IF (invalidRecords > 0) THEN
quer := 'invalid';
ELSE
INSERT INTO dataHolder VALUES (date1, date2);
quer := 'success';
END IF;
DBMS_OUTPUT.PUT_LINE(quer);
END;
/
Since COUNT(1) will always return just one record, it will never throw an ORA-01422 error. Also, it will always return data, so you don't need to worry about NO_DATA_FOUND, as the value 0 will be fetched if there are no invalid records.
Some small optmization of Nuno Guerreiro's answer
SELECT COUNT(1) INTO invalidRecords
FROM dual
WHERE exists
(SELECT 1 FROM dataHolder WHERE fdate < date1 AND tdate > date2);
It will allow to keep out of counting.