TOAD Oracle SQL Return Row from UDF - plsql

have a function below that returns a cursor. However I need it to return just one row. I have read on google about returning the data as a %rowtype but I do not seem to be able to get it to work.
The reason I don't want a cursor returned is that when I select the function one cell is returned saying (cursor) instead of displaying one row with 4 columns of data.
create or replace function udf
(
i_ptf_code in varchar2
,i_begin_date in date
,i_end_date in date
)
return sys_refcursor
is
portf_code varchar2(50);
end_date date;
chain_linked_ptf_net float;
chain_linked_ptf_gross float;
chain_linked_bmk float;
end_mv float;
v_cursor sys_refcursor;
cursor c_return_series is
select p.portf_code
,gpr.end_date
,gpr.end_market_value
,gpr.portf_perf_gross as gross_ret
,gpr.portf_perf_net as net_ret
,(exp(sum(ln(1 + gpr.portf_perf_gross)) over (partition by p.portf_code order by end_date)) - 1) as chain_linked_ptf_gross
,(exp(sum(ln(1 + gpr.portf_perf_net)) over (partition by p.portf_code order by end_date)) - 1) as chain_linked_ptf_net
,(exp(sum(ln(1 + gpr.bmk_perf)) over (partition by p.portf_code order by end_date)) - 1) as chain_linked_bmk
from portfolio_returns gpr
inner join portfolio p on p.portf_id = gpr.portf_id and p.is_composite != 2 --2 means composite
where p.portf_code = i_ptf_code
and gpr.end_date between i_begin_date and i_end_date;
begin
select i_ptf_code, i_end_date into portf_code, end_date from dual;
for c1line in c_return_series loop
if c1line.end_date = i_end_date then
select c1line.chain_linked_ptf_gross
,c1line.chain_linked_ptf_net
,c1line.chain_linked_bmk
,c1line.end_market_value
into chain_linked_ptf_gross
,chain_linked_ptf_net
,chain_linked_bmk
,end_mv
from dual;
end if;
end loop;
open v_cursor for
select portf_code as portf_code
,end_date as end_date
,chain_linked_ptf_gross * 100 as period_ptf_gross
,chain_linked_ptf_net * 100 as period_ptf_net
,chain_linked_bmk * 100 as period_bmk
,end_mv * 100 as period_mv
from dual;
return v_cursor;
close v_cursor;
end;
/

I am a little lost but I think this is what you need:
[...]
open v_cursor for
select portf_code as portf_code
,end_date as end_date
,chain_linked_ptf_gross * 100 as period_ptf_gross
,chain_linked_ptf_net * 100 as period_ptf_net
,chain_linked_bmk * 100 as period_bmk
,end_mv * 100 as period_mv
from dual;
return v_cursor;
-- close v_cursor; -- not needed
end;
-
DECLARE
l_rc SYS_REFCURSOR;
l_portf_code VARCHAR2(30);
l_end_date VARCHAR2(30);
l_period_ptf_gross NUMBER;
l_period_ptf_net NUMBER;
l_period_bmk NUMBER;
l_period_mv NUMBER;
BEGIN
l_rc := udf; -- This returns an open cursor
fetch v_rc into l_portf_code, l_end_date, l_period_ptf_gross, l_period_ptf_net, l_period_bmk, l_period_mv;
DBMS_OUTPUT.PUT_LINE
(
l_portf_code || ' ' ||
l_end_date || ' ' ||
l_period_ptf_gross || ' ' ||
l_period_ptf_net || ' ' ||
l_period_bmk || ' ' ||
l_period_mv
);
CLOSE v_rc;
END;

Related

CREATE OR REPLACE PROCEDURE proc_video_search

Create a procedure called proc_video_search to search for a video and display the name, copy ID, format, and status of the video’s copies. In addition, the checkout dates and due dates are also displayed for unreturned copies. The damaged copies (Status = 'D') are excluded in your output. Sort your output by the video name (Name) and then the copy ID (CopyID).
$ CREATE OR REPLACE PROCEDURE proc_video_search (
p_VideoName VARCHAR2,
p_FormatName VARCHAR2 DEFAULT NULL) as
v_Count NUMBER;
v_TotalCopies NUMBER; v_Avalb NUMBER;v_FormatName VARCHAR2(100);
v_VideoName VARCHAR2(100); v_CopyID VARCHAR2(100);v_DueDate DATE;
v_Status VARCHAR2(100); v_CheckoutDate DATE;
CURSOR asdf IS
SELECT T_VIDEO.Name, T_COPY.CopyID, Status,T_VIDEO_FORMAT.NAME
FROM T_VIDEO
INNER JOIN T_COPY ON T_VIDEO.VideoID = T_COPY.VideoID
INNER JOIN T_VIDEO_FORMAT ON T_VIDEO_FORMAT.FormatID =
T_VIDEO.FormatID
WHERE Status !='D' AND UPPER(T_VIDEO.Name) like '%' ||
UPPER(p_VideoName) || '%'
OR UPPER(T_VIDEO_FORMAT.NAME)= UPPER(p_FormatName)
ORDER BY T_VIDEO.Name, T_COPY.CopyID;
BEGIN
SELECT COUNT(*)
INTO v_Count
FROM T_VIDEO
WHERE UPPER(T_VIDEO.Name) like '%' || UPPER(p_VideoName) || '%' ;
IF v_count = 0 THEN
DBMS_OUTPUT.PUT_LINE('**** '||v_Count|| ' results found for ' ||
p_VideoName||'. *****');
RETURN;
END IF;
SELECT count(T_COPY.CopyID) INTO v_TotalCopies
FROM T_COPY INNER JOIN T_VIDEO ON T_COPY.VideoID = T_VIDEO.VideoID
INNER JOIN T_VIDEO_FORMA ON T_VIDEO_FORMAT.FormatID =
T_VIDEO.FormatID
WHERE Status !='D' AND UPPER(T_VIDEO.Name) like '%' ||
UPPER(p_VideoName) ||'%'
OR UPPER(T_VIDEO_FORMAT.NAME)=UPPER(p_FormatName);
SELECT count(T_COPY.CopyID)INTO v_Avalb FROM T_COPY
INNER JOIN T_VIDEO ON T_COPY.VideoID = T_VIDEO.VideoID
INNER JOIN T_VIDEO_FORMAT ON T_VIDEO_FORMAT.FormatID =
T_VIDEO.FormatID
WHERE Status ='A' AND UPPER(T_VIDEO.Name) like '%' ||
UPPER(p_VideoName) ||'%'
OR UPPER(T_VIDEO_FORMAT.NAME)=UPPER(p_FormatName);
IF v_TotalCopies >=0 THEN
IF p_FormatName IS NULL THEN
DBMS_OUTPUT.PUT_LINE(v_TotalCopies||' results found for '||
p_VideoName||' . (Available copies:'|| v_Avalb|| ')' );
ELSE
DBMS_OUTPUT.PUT_LINE(v_TotalCopies||' results found for '||
p_VideoName||'('|| p_FormatName||') . (Available copies:'||
v_Avalb|| ')' );
end if;
OPEN asdf;
LOOP
FETCH asdf INTO v_VideoName, v_CopyID, v_Status,
v_FormatName ; exit when asdf%NOTFOUND ;
SELECT COUNT(CheckoutDate)
INTO v_Count FROM T_RENTAL WHERE CopyID = v_CopyID;
IF v_Count = 1 THEN
SELECT CheckoutDate,DueDate
INTO v_CheckoutDate,v_DueDate
FROM T_RENTAL
WHERE CopyID = v_CopyID;
end if;
DBMS_OUTPUT.PUT_LINE(RPAD('-', 53, '-'));
DBMS_OUTPUT.PUT_LINE(RPAD('Name:',30) || RPAD(v_VideoName,15));
DBMS_OUTPUT.PUT_LINE(RPAD('CopyID:',30) || RPAD(v_CopyID,15));
DBMS_OUTPUT.PUT_LINE(RPAD('Format:',30) ||
RPAD(v_FormatName,15));
IF v_Status = 'A' THEN v_Status := 'Available';END IF;
IF v_Status = 'R' THEN v_Status := 'Rented'; END IF;
DBMS_OUTPUT.PUT_LINE(RPAD('Status:',30) || RPAD(v_Status,15));
IF v_Status ='Available' THEN
DBMS_OUTPUT.PUT_LINE(RPAD('CheckoutDate:',30)
||'****************************');
DBMS_OUTPUT.PUT_LINE(RPAD('DueDate:',30)
||'****************************');
ELSE
DBMS_OUTPUT.PUT_LINE(RPAD('CheckoutDate:',30)
||RPAD(TO_CHAR(v_CheckoutDate, 'DD-MON-YYYY'),15));
DBMS_OUTPUT.PUT_LINE(RPAD('DueDate:',30) ||RPAD(TO_CHAR(
v_DueDate, 'DD-MON-YYYY'),15));
END IF; END LOOP; CLOSE asdf; END IF; END proc_video_search ;
EXEC proc_video_search('ANOTHER', 'DVD')`
enter image description here
The problem is with this line of your cursor asdf
OR UPPER(T_VIDEO_FORMAT.NAME)= UPPER(p_FormatName)
Because it says OR, the query can choose to ignore this criteria if it evaluates to false. That is why you are getting results with all the formats; it ignores the filtering.
You have to wrap the OR statement in another AND clause, like so
WHERE Status !='D'
AND UPPER(T_VIDEO.Name) like '%' || UPPER(p_VideoName) || '%'
AND ( /* OR clause here */ )
And then you can handle the case of p_formatName being null or not.

PL/SQL code coming with compilation error

I have the following block of code. Can someone help me in rectifying the same.
CREATE OR REPLACE package body NMS.ResourceBindDistribute_withfile is
v_date date :=sysdate ;
v_user varchar2(10) := 'NMS';
procedure create_SIMDMLNK_new(v_SIMRANGE varchar2 , v_MSISDN varchar2,v_TECH varchar2) is
v_SIM_count integer;
v_dlink_dn_cnt integer;
v_dlink_dn integer;
v_counter integer;
v_new_dn_cnt integer;
v_free_count integer := 0;
sm_count integer;
ms_count integer;
cursor sim_curr is
select sim from temp_SIM_MSISDN;
cursor msisdn_curr is
select msidn from temp_SIM_MSISDN;
/* Cursor to selecet SIM for linking*/
cursor simcusrsor_3G (l_SIMRANGE varchar2) is
select sm_id,SM_SERIALNUM from storage_medium where SM_SERIALNUM in
(select SM_SERIALNUM from storage_medium
where SM_SERIALNUM = l_SIMRANGE and SM_STATUS='r' and SMC_ID in (1,2)
minus
(select SM_SERIALNUM from NMS.SIMDMSLNK where SM_SERIALNUM = l_SIMRANGE
union
select SM_SERIALNUM from NMS.SIMULNK where SM_SERIALNUM = l_SIMRANGE));
cursor simcusrsor_4G (l_SIMRANGE varchar2) is
select sm_id,SM_SERIALNUM from storage_medium where SM_SERIALNUM in
(select SM_SERIALNUM from storage_medium
where SM_SERIALNUM = l_SIMRANGE and SM_STATUS='r' and SMC_ID in (3)
minus
(select SM_SERIALNUM from NMS. SIMDMSLNK where SM_SERIALNUM = l_SIMRANGE
union
select SM_SERIALNUM from NMS.SIMULNK where SM_SERIALNUM = l_SIMRANGE));
type t_simcursor is table of simcusrsor_3G%rowtype index by PLS_INTEGER;
v_simsoure t_simcursor;
/* Cursor to select Dlinked MSISDN for linking with New SIM*/
cursor dlinkdn_cur (l_MSISDN varchar2) is
select distinct DN_ID,DN_NUM from NMS.SIMDMSLNK where DN_NUM = l_MSISDN and status='D';
type t_dlinkdn_cur is table of dlinkdn_cur %rowtype index by PLS_INTEGER;
v_dlinkdn_cur_source t_dlinkdn_cur ;
/* Cursor to select new Dummy MSISDN for linking with New SIM*/
cursor dummydn_cur (l_MSISDN varchar2) is
select distinct DN_ID, DN_NUM from directory_number where DN_NUM = l_MSISDN
and dn_status = 'f' and evcode is null and rscode=2 and DN_TYPE=3
minus
select distinct DN_ID,DN_NUM from NMS.SIMDMSLNK where DN_NUM = l_MSISDN;
type t_dummydn_cur is table of dummydn_cur%rowtype index by PLS_INTEGER;
v_dummydn_source t_dummydn_cur;
type t_SIMDMSLNK is table of NMS.SIMDMSLNK%rowtype index by PLS_INTEGER;
v_SIMDM_target t_SIMDMSLNK;
v_simdml_count PLS_INTEGER :=1;
NO_SIM_WITH_RANGE exception;
NO_DUMMY_DN_WITH_RANGE exception;
BEGIN
select count(1) into v_new_dn_cnt from
(select distinct DN_NUM from directory_number where DN_NUM = v_MSISDN
and dn_status = 'f' and evcode is null and rscode=2 and DN_TYPE=3
minus
select distinct DN_NUM from NMS.SIMDMSLNK where DN_NUM = v_MSISDN );
select count(distinct DN_NUM) into v_dlink_dn from NMS.SIMDMSLNK where DN_NUM = v_MSISDN and status='D';
if ( v_dlink_dn =0 and v_new_dn_cnt = 0) then
raise NO_DUMMY_DN_WITH_RANGE;
end if;
v_free_count := v_new_dn_cnt + v_dlink_dn;
/* Cusrsor opened Dlinked MSISDN, to assign first DLINKED MSISDN */
BEGIN
open msisdn_curr;
for i in msisdn_curr
LOOP
select count(*) into ms_count from directory_number where dn_num = i.msisdn;
if
ms_count > 0
then
open dlinkdn_cur (v_MSISDN);
fetch dlinkdn_cur bulk collect into v_dlinkdn_cur_source;
IF v_dlinkdn_cur_source.count = 0 THEN
RAISE NO_DATA_FOUND;
ELSE
v_dlink_dn_cnt := v_dlinkdn_cur_source.count;
DBMS_OUTPUT.PUT_LINE ( 'FIRST D-LINKED MSISDN ARE LINKED TO SIM.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ( 'NO FREE D-LINKED MSISDN ARE AVAILABLE, FREE DUMMY MSISDN WILL BE USED FOR ASSOSOIATION.');
END IF;
END LOOP;
END;
open sim_curr
for i in sim_curr
LOOP
select count(*) into sm_count from storage_medium where sm_serialnum=i.sim;
if
sm_count > 0
then
IF v_TECH = 3 THEN
open simcusrsor_3G (v_SIMRANGE);
fetch simcusrsor_3G bulk collect into v_simsoure;
END IF;
IF v_TECH = 4 THEN
open simcusrsor_4G (v_SIMRANGE);
fetch simcusrsor_4G bulk collect into v_simsoure;
END IF;
v_SIM_count := v_simsoure.count;
IF v_SIM_count = 0 then
raise NO_SIM_WITH_RANGE;
END IF;
END IF;
END LOOP;
/* Cusrsor opened NEW DUMMY MSISDN, to assign NEW DUMMY MSISDN */
BEGIN
open msisdn_curr;
for i in msisdn_curr
LOOP
select count(*) into ms_count from directory_number where dn_num = i.msisdn;
if
ms_count > 0
then
open dummydn_cur (v_MSISDN);
fetch dummydn_cur bulk collect into v_dummydn_source;
IF v_dummydn_source.count = 0 THEN
RAISE NO_DATA_FOUND;
ELSE
DBMS_OUTPUT.PUT_LINE ( 'NEW DUMMY MSISDN ARE LINKED TO SIM.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ( 'NO NEW DUMMY MSISDN IS AVAILABL FOR ASSOSOIATION.');
END IF;
END LOOP;
END;
v_counter :=1;
for l_sim_counter in v_simsoure.first .. v_simsoure.last
loop
if l_sim_counter = ( v_free_count) then
if l_sim_counter <= v_dlink_dn_cnt then
v_SIMDM_target(v_simdml_count).DN_ID := v_dlinkdn_cur_source(l_sim_counter).DN_ID;
v_SIMDM_target(v_simdml_count).DN_NUM := v_dlinkdn_cur_source(l_sim_counter).DN_NUM;
DELETE from NMS.SIMDMSLNK where DN_ID=v_dlinkdn_cur_source(l_sim_counter).DN_ID and STATUS='D';
else
v_SIMDM_target(v_simdml_count).DN_ID := v_dummydn_source(v_counter).DN_ID;
v_SIMDM_target(v_simdml_count).DN_NUM := v_dummydn_source(v_counter).DN_NUM;
v_counter := v_counter +1 ;
end if;
v_SIMDM_target(v_simdml_count).SM_SERIALNUM := v_simsoure(l_sim_counter).SM_SERIALNUM;
v_SIMDM_target(v_simdml_count).SM_ID := v_simsoure(l_sim_counter).SM_ID;
v_SIMDM_target(v_simdml_count).USER_LASTMOD := v_user;
v_SIMDM_target(v_simdml_count).LAST_UPDATE := v_date;
v_SIMDM_target(v_simdml_count).STATUS := 'L';
exit;
end if;
if l_sim_counter <= v_dlink_dn_cnt then
v_SIMDM_target(v_simdml_count).DN_ID := v_dlinkdn_cur_source(l_sim_counter).DN_ID;
v_SIMDM_target(v_simdml_count).DN_NUM := v_dlinkdn_cur_source(l_sim_counter).DN_NUM;
DELETE from NMS.SIMDMSLNK where DN_ID=v_dlinkdn_cur_source(l_sim_counter).DN_ID and STATUS='D';
else
v_SIMDM_target(v_simdml_count).DN_ID := v_dummydn_source(v_counter).DN_ID;
v_SIMDM_target(v_simdml_count).DN_NUM := v_dummydn_source(v_counter).DN_NUM;
v_counter := v_counter +1 ;
end if;
v_SIMDM_target(v_simdml_count).SM_SERIALNUM := v_simsoure(l_sim_counter).SM_SERIALNUM;
v_SIMDM_target(v_simdml_count).SM_ID := v_simsoure(l_sim_counter).SM_ID;
v_SIMDM_target(v_simdml_count).USER_LASTMOD := v_user;
v_SIMDM_target(v_simdml_count).LAST_UPDATE := v_date;
v_SIMDM_target(v_simdml_count).STATUS := 'L';
v_simdml_count := v_simdml_count+1;
end loop;
FORALL i IN v_SIMDM_target.FIRST .. v_SIMDM_target.LAST SAVE EXCEPTIONS
INSERT INTO NMS.SIMDMSLNK
VALUES v_SIMDM_target (i);
COMMIT;
close dlinkdn_cur;
close dummydn_cur;
IF v_TECH =3 THEN
close simcusrsor_3G;
ELSE
close simcusrsor_4G;
END IF;
DBMS_OUTPUT.PUT_LINE ( 'SIM & DUMMY MSISDN LINKING PROCESS IS COMPLETED SUCCESSFULLY.');
EXCEPTION
WHEN NO_SIM_WITH_RANGE THEN
DBMS_OUTPUT.PUT_LINE ( 'THERE ARE NO SIMS AVAILABLE FOR TECHNOLOGY WITH GIVEN RANGE = '||v_SIMRANGE);
WHEN NO_DUMMY_DN_WITH_RANGE THEN
DBMS_OUTPUT.PUT_LINE ( 'THERE ARE NO DUMMY MSISDN AVAILABLE FOR GIVEN RANGE = '||v_MSISDN);
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE : ' || SQLCODE);
DBMS_OUTPUT.put_line ('ERROR MESSAGE : ' || SQLERRM);
ROLLBACK;
END create_SIMDMLNK;
procedure create_REALDN (v_MSISDN varchar2) is
v_DN_count integer;
v_count integer;
NO_DN_WITH_RANGE exception;
DN_WITH_PREPROVISION exception;
BEGIN
select count(DN_ID) into v_DN_count from NMS.SIMDMSLNK
where DN_NUM = v_MSISDN;
if v_DN_count > 0 then
raise DN_WITH_PREPROVISION;
end if;
select count(1) into v_count from
(select DN_ID from DIRECTORY_NUMBER
where DN_NUM = v_MSISDN
MINUS
select DN_ID from NMS.REALDN
where REAL_DN like v_MSISDN||'%');
if v_count = 0 then
raise NO_DN_WITH_RANGE;
end if;
insert into NMS.REALDN (DN_ID,REAL_DN,DN_TYPE,USER_LASTMOD,LAST_UPDATE,STATUS )
select DN_ID,DN_NUM ,DN_TYPE,v_user,v_date,'L' from Directory_number where DN_ID in
((select DN_ID from DIRECTORY_NUMBER
where DN_NUM = v_MSISDN and dn_type not in (1,2) and evcode is null
MINUS
select DN_ID from NMS.REALDN
where REAL_DN = v_MSISDN));
COMMIT;
DBMS_OUTPUT.PUT_LINE ( 'REAL DIRECTORY NUMBER CREATION PROCESS IS COMPLETED SUCCESSFULLY.');
EXCEPTION
WHEN DN_WITH_PREPROVISION THEN
DBMS_OUTPUT.PUT_LINE ( 'MSISDN RANGE IS WITH PREPROVISION POOL ' || v_MSISDN);
WHEN NO_DN_WITH_RANGE THEN
DBMS_OUTPUT.PUT_LINE ( 'NO DN AVAILABLE WITH RANGE ' || v_MSISDN);
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE : ' || SQLCODE);
DBMS_OUTPUT.put_line ('ERROR MESSAGE : ' || SQLERRM);
ROLLBACK;
END create_REALDN;
procedure create_FREESIM (v_SIMRANGE varchar2) is
v_SIM_count integer;
v_count integer;
NO_SIM_WITH_RANGE exception;
BEGIN
select count(1) into v_count from
(select SM_SERIALNUM from storage_medium
where SM_SERIALNUM = v_SIMRANGE and SM_STATUS='r' and SMC_ID in (3)
minus
(select SM_SERIALNUM from NMS. SIMDMSLNK where SM_SERIALNUM = v_SIMRANGE
union
select SM_SERIALNUM from NMS.SIMULNK where SM_SERIALNUM = v_SIMRANGE));
if v_count = 0 then
raise NO_SIM_WITH_RANGE;
end if;
insert into NMS.SIMULNK (SM_SERIALNUM,SM_ID, USER_LASTMOD, LAST_UPDATE, STATUS)
select SM_SERIALNUM,sm_id,v_user,v_date,'U' from storage_medium where SM_SERIALNUM in
(select SM_SERIALNUM from storage_medium
where SM_SERIALNUM = v_SIMRANGE and SM_STATUS='r' and SMC_ID in (3)
minus
(select SM_SERIALNUM from NMS. SIMDMSLNK where SM_SERIALNUM = v_SIMRANGE
union
select SM_SERIALNUM from NMS.SIMULNK where SM_SERIALNUM = v_SIMRANGE));
COMMIT;
DBMS_OUTPUT.PUT_LINE ( 'FREE 4G SIM CREATION PROCESS IS COMPLETED SUCCESSFULLY.');
EXCEPTION
WHEN NO_SIM_WITH_RANGE THEN
DBMS_OUTPUT.PUT_LINE ( 'SIM NOT AVAILABLE WITH RANGE ' ||v_SIMRANGE ||'TO INCLUDE IN FREE SIM POOL.');
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE : ' || SQLCODE);
DBMS_OUTPUT.put_line ('ERROR MESSAGE : ' || SQLERRM);
ROLLBACK;
END create_FREESIM;
procedure dummy_dlink is
v_count integer;
NO_ACTIVE exception;
begin
select count(distinct cd.CD_SM_NUM) into v_count from CONTR_DEVICES cd, contract_all coa , NMS.SIMDMSLNK SIMD
where coa.CH_STATUS='a' and COA.CO_ID=cd.co_id and SIMD.SM_serialnum=cd.cd_SM_NUM and SIMD.STATUS <> 'D';
If v_count =0 then
raise NO_ACTIVE;
else
update NMS.SIMDMSLNK set status='D' , Last_update=v_date where status <> 'D' and SM_SERIALNUM in
(select distinct CD_SM_NUM from CONTR_DEVICES cd, contract_all coa
where coa.CH_STATUS='a' and COA.CO_ID=cd.co_id);
COMMIT;
DBMS_OUTPUT.PUT_LINE ( v_count ||' DUMMY MSISDN D-LINKED');
end if;
EXCEPTION
when NO_ACTIVE then
NULL;
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE : ' || SQLCODE);
DBMS_OUTPUT.put_line ('ERROR MESSAGE : ' || SQLERRM);
end dummy_dlink;
procedure update_port_kind
is
v_port_id number;
v_smc_id number;
v_sm_id number;
v_vend_code varchar2 (10);
BEGIN
FOR cur
IN (SELECT port_id, sm_id
FROM port
WHERE TRUNC (PORT_STATUSMODDAT) = TRUNC (SYSDATE)
AND port_kind IS NULL and port_status = 'r')
LOOP
SELECT smc_id
INTO v_smc_id
FROM storage_medium
WHERE sm_id = cur.sm_id;
SELECT vendcode
INTO v_vend_code
FROM storage_medium
WHERE sm_id = cur.sm_id;
IF v_smc_id IN (1, 2) AND v_vend_code = 'DZ'
THEN
UPDATE port
SET port_kind = 1
WHERE port_id = cur.port_id;
ELSIF v_smc_id IN (1, 2) AND v_vend_code = 'MORPHO'
THEN
UPDATE port
SET port_kind = 2
WHERE port_id = cur.port_id;
ELSIF v_smc_id IN (1, 2) AND v_vend_code = 'GD'
THEN
UPDATE port
SET port_kind = 3
WHERE port_id = cur.port_id;
ELSIF v_smc_id = 3 AND v_vend_code = 'DZ'
THEN
UPDATE port
SET port_kind = 4
WHERE port_id = cur.port_id;
ELSIF v_smc_id = 3 AND v_vend_code = 'ORN'
THEN
UPDATE port
SET port_kind = 5
WHERE port_id = cur.port_id;
ELSIF v_smc_id = 3 AND v_vend_code = 'MORPHO'
THEN
UPDATE port
SET port_kind = 6
WHERE port_id = cur.port_id;
END IF;
END LOOP;
COMMIT;
END;
END ResourceBindDistribute;
/
On running the above I am getting the following error :
ERROR line 112, col 12, ending_line 112, ending_col 20, Found 'EXCEPTION', Expecting: ( SELECT -or- END -or- $IF : AT BEGIN CASE CLOSE COMMIT CONTINUE CURSOR DAY DECLARE DELETE ELSE ELSIF EXECUTE EXIT FETCH FOR FORALL GOTO identifier IF INSERT LOCK LOOP MERGE MOD MODEL MULTISET NULL OPEN RAISE REM RETURN ROLLBACK SAVEPOINT SET SQL THE UPDATE WHILE WITH YEAR -or- <<”
In the section
-- Cusrsor opened Dlinked MSISDN, to assign first DLINKED MSISDN
You start your loop inside the begin section but end the loop after the exception.
If you start a if or loop inside a anonymous block you need to ensure that it is fully contained within it.

create a procedure with cursor as parameter

I wrote this code and it works ok:
declare
cursor c_emp is
select last_name, first_name from employees;
type c_list is table of employees.last_name%type index by binary_integer;
type c_list2 is table of employees.first_name%type index by binary_integer;
last_list c_list;
first_list c_list2;
counter integer := 0;
begin
for i in c_emp loop
counter := counter + 1;
last_list(counter) := i.last_name;
first_list(counter) := i.first_name;
dbms_output.put_line('Employee(' || counter || '): ' || last_list(counter) || ' ' || first_list(counter));
end loop;
end;
/
This time I am trying to make procedure with parameters that I can insert the table name and column into the cursor. And I have tried with this :
create or replace procedure show_data(tab_name in varchar2, data_list in varchar2)
is
str varchar2(100);
str2 varchar2(100);
column_name varchar2(100);
begin
str := 'select ' || data_list || ' from ' || tab_name;
for vRec in str loop
dbms_output.put_line(str);
end loop;
end;
/
It gave a error which the str is not a cursor. I am not sure that if cursor can be done in this way, but from the error it seems it can't.
Which part of my code is wrong, or because I didn't declare my cursor? But if i declare my cursor, I can't get the parameter by using dynamic sql way.
The below should produce the same result as your original PL/SQL block. Note that the table_name can be dynamic and so can the data_list but you need to know the column names in the data_list to be able to fetch from the cursor and then print them.
create or replace procedure show_data(tab_name in varchar2
, data_list in varchar2)
is
str varchar2(100);
str2 varchar2(100);
column_name varchar2(100);
TYPE cursor_ref IS REF CURSOR;
vRec_cursor cursor_ref;
counter integer = 0;
last_name employee.last_name%TYPE;
first_name employee.first_name%TYPE;
begin
str := 'select ' || data_list || ' from ' || tab_name;
open vRec_cursor for str;
loop
FETCH vRec_cursor INTO last_name, first_name;
EXIT WHEN vRec_cursor%NOTFOUND;
dbms_output.put_line('Employee(' || counter || '): ' || last_name || ' ' || first_name;
counter = counter + 1;
end loop;
end;
/
NOTE: Haven't run the above code yet

Dynamic String contcatination in Cursor

I have a function which concatinates the value for a cursor. Its now only concatinates 4 columns and that column name should be hardcoded. Is there a way to have a generic solution for this, such that if i pass a cursor it will automatically concatinate data regardless of column name and number of columns in 11g.
FUNCTION generateData(p_dataCursor IN SYS_REFCURSOR)
RETURN VARCHAR2 AS
-- ---------------------------------------------------------------------
crlf VARCHAR2(2) := chr(13)||chr(10);
lv_message VARCHAR2(32000);
BEGIN
FOR rec IN p_dataCursor
LOOP
lv_message := lv_message || rec.a||','||rec.b||','||rec.c||','||rec.d || crlf;
END LOOP;
RETURN lv_message;
END;
Since 11g Oracle built-in package DBMS_SQL provides function TO_CURSOR_NUMBER - "This function takes an OPENed strongly or weakly-typed ref cursor and transforms it into a DBMS_SQL cursor number."
Example code:
DECLARE
l_cursor SYS_REFCURSOR;
FUNCTION generateData(p_dataCursor IN SYS_REFCURSOR)
RETURN VARCHAR2 AS
curs SYS_REFCURSOR := p_dataCursor;
l_cursorid NUMBER;
l_column_count INTEGER;
l_describe_table DBMS_SQL.DESC_TAB;
l_numvar NUMBER;
l_ignore INTEGER;
l_value VARCHAR2(2000);
l_coma VARCHAR2(10);
crlf VARCHAR2(2) := chr(13)||chr(10);
lv_message VARCHAR2(32000);
BEGIN
l_cursorid := dbms_sql.to_cursor_number( curs );
dbms_sql.describe_columns( l_cursorid, l_column_count, l_describe_table );
FOR i IN 1..l_column_count LOOP
dbms_sql.define_column(l_cursorid, i, l_value, 2000);
END LOOP;
LOOP
IF DBMS_SQL.FETCH_ROWS(l_cursorid)>0 THEN
l_coma := '';
FOR i IN 1..l_column_count LOOP
dbms_sql.column_value(l_cursorid, i, l_value);
lv_message := lv_message || l_coma || l_value;
l_coma := ',';
END LOOP;
lv_message := lv_message || crlf;
ELSE
EXIT;
END IF;
END LOOP;
dbms_sql.close_cursor( l_cursorid );
RETURN lv_message;
END;
BEGIN
open l_cursor FOR 'SELECT 1 as A, 2 AS B, 3 AS C, 4 AS D FROM DUAL UNION ALL SELECT 1 as A, 2 AS B, 3 AS C, 4 AS D FROM DUAL';
dbms_Output.put_Line(generateData(l_cursor));
END;
/

Get Installation Sequence of Oracle Objects

Ok, I have a complex recursion problem. I want to get a dependecy installation sequence of all of my objcts (all_objects table) in my Oracle 11g database.
First I have created a view holding all dependencies
create or replace
view REALLY_ALL_DEPENDENCIES as
select *
from ALL_DEPENDENCIES
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
from all_indexes
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
from all_constraints p
join all_constraints f
on F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME
and F.CONSTRAINT_TYPE = 'R'
and p.constraint_type='P'
;
/
EDIT
I have tried do concate all dependencies by using this function:
create
or replace
function dependency(
i_name varchar2
,i_type varchar2
,i_owner varchar2
,i_level number := 0
,i_token clob := ' ') return clob
is
l_token clob := i_token;
l_exist number := 0;
begin
select count(*) into l_exist
from all_objects
where object_name = i_name
and object_type = i_type
and owner = i_owner;
if l_exist > 0 then
l_token := l_token || ';' || i_level || ';' ||
i_name || ':' || i_type || ':' || i_owner;
else
-- if not exist function recursion is finished
return l_token;
end if;
for tupl in (
select distinct
referenced_name
,referenced_type
,referenced_owner
from REALLY_ALL_DEPENDENCIES
where name = i_name
and type = i_type
and owner = i_owner
)
loop
-- if cyclic dependency stop and shout!
if i_token like '%' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '%' then
select count(*) into l_exist
from REALLY_ALL_DEPENDENCIES
where name = tupl.referenced_name
and type = tupl.referenced_type
and owner = tupl.referenced_owner;
if l_exist > 0 then
return '!!!CYCLIC!!! (' || i_level || ';' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '):' || l_token;
end if;
end if;
-- go into recursion
l_token := dependency(
tupl.referenced_name
,tupl.referenced_type
,i_owner /* I just want my own sources */
,i_level +1
,l_token);
end loop;
-- no cyclic condition and loop is finished
return l_token;
end;
/
And I can query through
select
object_name
,object_type
,owner
,to_char(dependency(object_name, object_type, owner)) as dependecy
from all_objects
where owner = 'SYSTEM'
;
Ok, maybe it is something like "cheating" but you can not do cyclic dependencies at creation time. So at least as a human beeing I am only able to create one object after another :-) And this sequence should be "reverse engineer able".
Now I am more interested in a solution than before ;-) And it is still about the tricky part ... "How can I select all soures from a schema orderd by its installation sequence (dependent objects list prior the using object)"?
It is just some kind of sorting problem, insn't it?
Usually you "cheat" by creating the objects in a particular order. For example, you might make sequences first (they have zero dependencies). Then you might do tables. After that, package specs, then package bodies, and so on.
Keep in mind that it is possible to have cyclic dependencies between packages, so there are cases where it will be impossible to satisfy all dependencies at creation anyway.
What's the business case here? Is there a real "problem" or just an exercise?
EDIT
The export tool we use exports objects in the following order:
Database Links
Sequences
Types
Tables
Views
Primary Keys
Indexes
Foreign Keys
Constraints
Triggers
Materialized Views
Materialized View Logs
Package Specs
Package Bodies
Procedures
Functions
At the end, we run the dbms_utility.compile_schema procedure to make sure everything is valid and no dependencies are missed. If you use other object types than these, I'm not sure where they'd go in this sequence.
Ok, I had some time to look at the job again and I want to share the results. Maybe anotherone comes across this thread searching for a solution. First of all I did the SQLs as SYS but I think you can do it in every schema using public synonyms.
The Procedure "exec obj_install_seq.make_install('SCOTT');" makes a clob containing a sql+ compatible sql file, assuming your sources are called "object_name.object_type.sql". Just spool it out.
Cheers
Chris
create global temporary table DEPENDENCIES on commit delete rows as
select * from ALL_DEPENDENCIES where 1=2 ;
/
create global temporary table install_seq(
idx number
,seq number
,iter number
,owner varchar2(30)
,name varchar2(30)
,type varchar2(30)
) on commit delete rows;
/
create global temporary table loop_chk(
iter number
,lvl number
,owner varchar2(30)
,name varchar2(30)
,type varchar2(30)
) on commit delete rows;
/
create or replace package obj_install_seq is
procedure make_install(i_schema varchar2 := 'SYSTEM');
end;
/
create or replace package body obj_install_seq is
subtype install_seq_t is install_seq%rowtype;
type dependency_list_t is table of DEPENDENCIES%rowtype;
procedure set_list_data(i_schema varchar2 := user)
is
l_owner varchar2(30) := i_schema;
begin
-- collect all dependencies
insert into DEPENDENCIES
select *
from (select *
from ALL_DEPENDENCIES
where owner = l_owner
and referenced_owner = l_owner
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
from all_indexes
where owner = l_owner
and table_owner = l_owner
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
from all_constraints p
join all_constraints f
on F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME
and F.CONSTRAINT_TYPE = 'R'
and p.constraint_type='P'
and p.owner = f.owner
where p.owner = l_owner
) all_dep_tab;
-- collect all objects
insert into install_seq
select rownum, null,null, owner, object_name, object_type
from (select distinct owner, object_name, object_type, created
from all_objects
where owner = l_owner
order by created) objs;
end;
function is_referencing(
i_owner varchar2
,i_name varchar2
,i_type varchar2
,i_iter number
,i_level number := 0
) return boolean
is
l_cnt number;
begin
select count(*) into l_cnt
from loop_chk
where name = i_name
and owner = i_owner
and type = i_type
and iter = i_iter
and lvl < i_level;
insert into loop_chk values(i_iter,i_level,i_owner,i_name,i_type);
if l_cnt > 0 then
return true;
else
return false;
end if;
end;
procedure set_seq(
i_owner varchar2
,i_name varchar2
,i_type varchar2
,i_iter number
,i_level number := 0)
is
-- l_dep all_dependencies%rowtype;
l_idx number;
l_level number := i_level +1;
l_dep_list dependency_list_t;
l_cnt number;
begin
-- check for dependend source
begin
select * bulk collect into l_dep_list
from dependencies
where name = i_name
and owner = i_owner
and type = i_type;
if l_dep_list.count <= 0 then
-- recursion finished
return;
end if;
end;
for i in 1..l_dep_list.count loop
if is_referencing(
l_dep_list(i).referenced_owner
,l_dep_list(i).referenced_name
,l_dep_list(i).referenced_type
,i_iter
,i_level
) then
-- cyclic dependecy
update install_seq
set seq = 999
,iter = i_iter
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type;
else
--chek if sequence is earlier
select count(*) into l_cnt
from install_seq
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type
and seq > l_level *-1;
-- set sequence
if l_cnt > 0 then
update install_seq
set seq = l_level *-1
,iter = i_iter
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type;
end if;
-- go recusrion
set_seq(
l_dep_list(i).referenced_owner
,l_dep_list(i).referenced_name
,l_dep_list(i).referenced_type
,i_iter + (i-1)
,l_level
);
end if;
end loop;
end;
function get_next_idx return number
is
l_idx number;
begin
select min(idx) into l_idx
from install_seq
where seq is null;
return l_idx;
end;
procedure make_install(i_schema varchar2 := 'SYSTEM')
is
l_obj install_seq_t;
l_idx number;
l_iter number := 0;
l_install_clob clob := chr(10);
begin
set_list_data(i_schema);
l_idx := get_next_idx;
while l_idx is not null loop
l_iter := l_iter +1;
select * into l_obj from install_seq where idx = l_idx;
update install_seq set iter = l_iter where idx = l_idx;
update install_seq set seq = 0 where idx = l_idx;
set_seq(l_obj.owner,l_obj.name,l_obj.type,l_iter);
l_idx := get_next_idx;
end loop;
for tupl in ( select * from install_seq order by seq, iter, idx ) loop
l_install_clob := l_install_clob || '#' ||
replace(tupl.name,' ' ,'') || '.' ||
replace(tupl.type,' ' ,'') || '.sql' ||
chr(10);
end loop;
l_install_clob := l_install_clob ||
'exec dbms_utility.compile_schema(''' || upper(i_schema) || ''');';
-- do with the install file what you want
DBMS_OUTPUT.PUT_LINE(dbms_lob.substr(l_install_clob,4000));
end;
end;
/

Resources