I need to continue my loop whenever any select statement in my cursor loop does not fetch data. I want to handle the exception for the same. This procedure inserts data whenever it finds it in continuity but as soon as o.id selected by the cursor does not hold the related data it exists the loop and only inserts data for the previously fetched records and does not continue the loop.
CREATE OR REPLACE procedure order_violation1(
p_type number,
p_code varchar2,
p_submit_from date,
p_submit_to date,
p_approved_from date,
p_approved_to date,
p_flag number,
p_status varchar2
) is
pp_type varchar2(100);
pp_company varchar2(50);
pp_code varchar2(20);
pp_ord_num varchar2(50);
pp_status varchar2(50);
SUBMIT_DATE date;
APPROVAL_DATE date;
ORDERING_RATIO_FLAG number;
pp_submit_date date;
pp_app_date date;
pp_package varchar2(3000);
pp_flag NUMBER;
cursor pp_id is
select distinct o.id
from orders o,
partnerprofile pp
where type_id=p_type
and o.ordering_ratio_flag=p_flag
and pp.id=o.to_partner_id
and decode(P_CODE,null,'1',pp.code) = decode(P_CODE,null,'1',p_code)
and decode(p_submit_from,null, to_date('01/01/01','dd/mm/yy'),
to_date(submit_date,'dd/mm/yy')) between
decode(p_submit_from ,null,
to_date('01/01/01','dd/mm/yy'),p_submit_from) and
decode(p_submit_to,null,to_date('01/01/01','dd/mm/yy'),'05-JUL-14')
and decode(p_approved_from,null,
to_date('01/01/01','dd/mm/yy'),
to_date(submit_date,'dd/mm/yy')) between
decode(p_approved_from,null,
to_date('01/01/01','dd/mm/yy'),p_approved_from) and
decode(p_approved_to,null,to_date('01/01/01','dd/mm/yy'),'05-JUL-14')
and decode(p_status,null,'1',o.status) = decode(p_status,null,'1',p_status);
begin
FOR r_partner IN pp_id
loop
select name
into pp_type
from partnertype
where id=p_type;
select code,
company_name
into pp_code,
pp_company
from partnerprofile pp,
orders o
where o.id=r_partner.id
and pp.id=o.to_partner_id;
select ORDER_NUMBER,
STATUS,
SUBMIT_DATE,
APPROVAL_DATE,
ORDERING_RATIO_FLAG
into pp_ord_num,
pp_status,
pp_submit_date,
pp_app_date,
pp_flag
from orders
where id=r_partner.id;
select distinct
rtrim (xmlagg (
xmlelement (e, pk.name||'='||
nvl(oln.total_amount,0) || '||')
).extract ('//text()'), ',')
into pp_package
from package pk,
orderlineitem oln
where oln.package_id=pk.id
and oln.order_id=r_partner.id
GROUP BY oln.order_id;
insert into order_violation_tab1
values (pp_type, pp_code, pp_company, pp_ord_num,
pp_status, pp_submit_date, pp_app_date,
pp_flag, null, null);
--pp_package);
END;
As Nicholas pointed out previous method will not work here. You will have to use exception handling inside loop like below to handle this.
LOOP
BEGIN
-- select code
exception
when no_data_found then
continue;
END;
-- insert code
END LOOP;
Also continue; is feature of 11gr1 and up, for older ones you will have to use goto.
LOOP
BEGIN
-- select code
exception
when no_data_found then
goto label1;
END;
-- insert code
<<label1>>
null;
END LOOP;
Related
I have a table in my oracle DB which has a column with random values. Screenshot is attached below :
I had manually updated the first row to "V0001". Is there any way I can update the rest of the rows to "V0002", "V0003" and so on without manual intervention.
You could use a sequence for this. Create a sequence, convert the sequence's .NEXTVAL to a string, use CONCAT() and UPDATE eg:
Table
create table demo
as
select dbms_random.string( 'x', 11 ) as vehicleid
from dual
connect by level <= 100 ;
select * from demo fetch first 10 rows only ;
-- output
VEHICLEID
LS23XFRNH5N
47DUDNOIRO9
POS5GQSQLMO
BBEEZJMQZI4
2Q8QE30HM2E
S7M5V40YNTD
N2X1YN0OIE3
...
Sequence
create sequence vehicleid_seq start with 1 increment by 1 ;
Update
update demo
set vehicleid = concat( 'V', to_char( vehicleid_seq.nextval, 'FM00000' ) ) ;
Result
select * from demo order by vehicleid fetch first 10 rows only ;
VEHICLEID
V00001
V00002
V00003
V00004
V00005
V00006
V00007
V00008
V00009
V00010
dbfiddle
The identifier code of a table is recommended to be a numeric data, what you could do is an extra field that works as a second code, perhaps called secondary_code. You can do it with Stored Procedure, I give you a small example:
DELIMITER$$
DROP PROCEDURE IF EXISTS sp_genwrar_code$$
CREATE PROCEDURE sp_genwrar_code(
OUT p_secondary_code VARCHAR(4)
)
BEGIN
DECLARE accountant INT;
BEGIN
SET accountant = (SELECT COUNT(*)+1 FROM product);
IF(accountant <10)THEN
SET p_secondary_code= CONCAT('V00',accountant );
ELSE IF(accountant<100) THEN
SET p_secondary_code= CONCAT('V0',accountant);
ELSE IF(accountant<1000)THEN
SET p_secondary_code= CONCAT('V',accountant );
END IF;
END IF;
END IF;
END;
END$$
With that you can generate codes as you need with the structure 'V001'
Write a pl sql block to fetch distinct department idsenter image description here
That would be something like this (read comments within code).
Though, the exercise is just the opposite of what I'd expect because - normally - departments exist, but nobody works in them. With enforced referential integrity constraint, you couldn't have situation as described in the exercise. After all, that's what your homework text suggests.
set serveroutput on
declare
l_dept_name dept.dept_name%type;
begin
-- loop through all distinct DEPT_ID values in the EMP table
for cur_r in (select distinct e.dept_id
from emp e
)
loop
-- starting inner BEGIN-EXCEPTION-END block so that
-- loop goes on in case of an error
begin
-- retrieve department details
select d.dept_name
into l_dept_name
from dept d
where d.dept_id = cur_r.dept_id;
-- display department info (because SELECT returned something for CUR_R.DEPT_ID)
dbms_output.put_line('Dept ID: ' || cur_r.dept_id || ' is ' || l_dept_name);
-- handle errors (because SELECT didn't return anything for CUR_R.DEPT_ID)
exception
when no_data_found then
dbms_output.put_line('Dept ID: ' || cur_r.dept_id ||': no additional info');
end;
end loop;
end;
/
I need to load some queries into vectors to avoid temporary tables in a function:
create table mytable
( eref serial primarykey,
edia date,
eimpte numeric);
---
CREATE OR REPLACE FUNCTION peps(rseller integer)
RETURNS void AS
$BODY$
declare
dep_dia date[] := '{}';
dep_impte numeric[]:= '{}';
dep_ref integer[]:= '{}';
ndepositos integer :=0;
rec record;
begin
for rec in
select eref, edia, eimpte from mytable order by edia, eimpte
loop
ndepositos:=ndepositos+1;
dep_dia[ndepositos] :=edia;
dep_impte[ndepositos]:=eimpte;
dep_ref[ndepositos] :=eref;
end loop;
raise notice ' ndeps %', ndepositos;
end
$BODY$
language plpgsql volatile;
it does not work:
ERROR: column "edia" does not exist
LINE 1: SELECT edia
^
what am I doing wrong?
Thanks in advance
Don't loop! Postgres provides a great function for this:
SELECT array_agg(eref), array_agg(edia), array_agg(eimpte)
FROM (SELECT * from mytable order by edia, eimpte) AS foo
INTO your variables
By putting the order by in a subquery, the aggregate functions will get the values in the order you want. This should be faster than looping.
You are not having edia column while creating the table. Looking at reamining code, I feel your create table query should be like following:
create table mytable
( edia serial primarykey,
eref date,
eimpte numeric);
I have to do an SQL Server Statement that have to return an empty row when is null, and data otherwhise.
I am trying to do a Select from (if exisits) but have an error on parent table.
I Simplify it. But the meaning, is to retrieve a couple of fields when condition is null and other fields when it is not null.
It Works fine when I do not clouse it in another select.... I need to retrieve it as a table to do an inner Join with other clouse.
How can i resolved it?
Here is my code..
select * from
(
if exists(select isnull(SECTOR_ID_DESTINO_BAD,-1)
from workflow_Compras_detalle w
where w.id=2)
begin
select null as Sector,null as sector_id_origen
end
else
begin
select top 1 isnull(ws.sector,'') sector, wd.sector_id_origen
from workflow_Compras_detalle wd
where orden < 10
end
)Table
you should try to insert the data into a temporary table or Table Variable, then get the data from that table, here is an example with a Table Variable, if you need something more persistent you may use a #Temp Table, i recommend you take a look to this: difference between var table and #Temp Table
DECLARE #VAR_TABLE AS TABLE(
Sector varchar(25),
sector_id_origen int
)
if exists(select isnull(SECTOR_ID_DESTINO_BAD,-1)
from workflow_Compras_detalle w
where w.id=2)
begin
INSERT INTO #VAR_TABLE
Select null as Sector,null as sector_id_origen
End
Else
begin
INSERT INTO #VAR_TABLE
select top 1 isnull(ws.sector,'') sector, wd.sector_id_origen
from workflow_Compras_detalle wd
where orden < 10
End
SELECT * FROM #VAR_TABLE
I just wonder if anyone knows how to automatize views creation after running DROP ... CASCADE?
Now I'm trying to drop view at first with classic DROP VIEW myview statement and if I cannot drop the view because other objects still depend on it then checking out all the objects names that postgres lists and save their creates and then I run drop with cascade. Sometimes it's like over a dozen objects. But maybe you have got some idea to handle this issue in more automated way?
Maybe anybody has got some function?
Next step... (continuation of my previous answer).
function save_views(objectname text) stores views depending on objectname (view or table) in table saved_views.
function restore_views() restores views from table saved_views.
create or replace function save_views_oid(objectid oid)
returns void language plpgsql as $$
declare
r record;
begin
for r in
select distinct c.oid, c.relname, n.nspname
from pg_depend d
join pg_rewrite w on w.oid = d.objid
join pg_class c on c.oid = w.ev_class
join pg_namespace n on n.oid = c.relnamespace
where d.refclassid = 'pg_class'::regclass
and d.classid = 'pg_rewrite'::regclass
and d.refobjid = objectid
and c.oid <> objectid
loop
insert into saved_views values (
'CREATE VIEW ' || r.nspname || '.' || r.relname ||
' AS ' || pg_get_viewdef(r.oid, 'f'));
perform save_views_oid(r.oid);
end loop;
end; $$;
create or replace function save_views(objectname text)
returns void language plpgsql as $$
begin
create table if not exists saved_views(viewbody text);
truncate saved_views;
perform save_views_oid(objectname::regclass);
end; $$;
create or replace function restore_views()
returns void language plpgsql as $$
declare
viewtext text;
begin
for viewtext in
select viewbody from saved_views
loop
execute viewtext;
end loop;
drop table saved_views;
end; $$;
Test:
select save_views('my_view'); -- may be save_views('my_schema.my_view');
select * from saved_views;
Use:
select save_views('my_view');
drop view my_view cascade;
create view my_view as ...
select restore_views();
Table pg_depend contains all necessary informations, but it is not so easy to interpret them. Here you have sketch recursive function to retrieve dependencies of pg_class object in text format. You can tune up the function to your needs (and show us results:).
create or replace function dependency
(class_id regclass, obj_id regclass, obj_subid integer, dep_type "char")
returns setof text language plpgsql as $$
declare
r record;
begin
return query
select pg_describe_object(class_id, obj_id, obj_subid)
|| ' ('|| dep_type|| ')';
for r in
select classid, objid, objsubid, deptype
from pg_depend
where class_id = refclassid
and obj_id = refobjid
and (obj_subid = refobjsubid or obj_subid = 0)
loop
return query select dependency(r.classid, r.objid, r.objsubid, r.deptype);
end loop;
end; $$;
use:
select dependency('pg_class'::regclass, 'my_view'::regclass, 0, ' ');
select dependency('pg_class'::regclass, 'my_table'::regclass, 0, ' ');