How to fetch row of unknown ROWTYPE in PL/SQL? - plsql

I have table in oracle with definitions of lists. Each definition is sql string, that returns table with 'd' and 'r' columns. I want get some 'd' value by 'r' value.
Example:
My query string is: SELECT SOME_COLUMN d, SOME_COLUMN2 r from SOME_TABLE order by 1
My PL/SQL code is:
DECLARE
query_str VARCHAR2(2000) := 'SELECT SOME_COLUMN d, SOME_COLUMN2 r from SOME_TABLE order by 1';
return_str VARCHAR2(2000);
TYPE LovCurTyp IS REF CURSOR;
v_lov_cursor LovCurTyp;
--And there is my problem:
lov_record UNKNOWN_TYPE_OF_SOME_TABLE%ROWTYPE;
BEGIN
OPEN v_lov_cursor FOR query_str;
LOOP
FETCH v_lov_cursor INTO lov_record;
EXIT WHEN v_lov_cursor%NOTFOUND;
--Get return_str here
END LOOP;
CLOSE v_lov_cursor;
return return_str;
END;
So my question is: How to fetch row of unknown ROWTYPE or maybe there is another way to do something like I describe?

Related

How to fetch the records from cursor which contains columns from different table?

FIRST PROCEDURE
create or replace PROCEDURE TESTPROCEDURE
(
P_LAF_PK IN NUMBER,
P_RET_VAL OUT SYS_REFCURSOR
) AS
BEGIN
OPEN p_RET_VAL FOR
SELECT LAF.AF_FEE,LAF.AF_FEES_PAYABLE,
LAH.LH_DECISION_DT,LAH.LH_ISSUED
FROM LH_APP_HDR LAH JOIN LIQ_APP_FEE LAF
ON AF_PK = LH_PK
WHERE LAF_APPID = P_LAF_PK;
END TESTPROCEDURE;
Calling this procedure in another procedure
SECOND PROCEDURE
create or replace PROCEDURE TESTPROCEDURE1
AS
BEGIN
DECLARE
V_LIQ_CURSOR SYS_REFCURSOR;
V_LIQ_CURSOR_OUT1 LIQ_APP_FEE%ROWTYPE;
BEGIN
TESTPROCEDURE (2727,V_LIQ_CURSOR);
LOOP
FETCH V_LIQ_CURSOR INTO V_LIQ_CURSOR_OUT1; -- getting error in this line like "Return
types of Result Set variables or query do not match"
EXIT WHEN V_LIQ_CURSOR%NOTFOUND;
IF(V_LIQ_CURSOR_OUT1.AF_FEE != 0) THEN
SELECT (V_LIQ_CURSOR_OUT1.AF_FEES_PAYABLE + V_LIQ_CURSOR_OUT1.AF_FEE) INTO V_TOTALFEE FROM DUAL;
END IF;
END TESTPROCEDURE1;
Can anyone tell me how to get the result from cursor which contains multiple table columns.
NOTE:
I want only two columns from the first procedure

Find a column and a value from a schema scan all the table in oracle

I am trying to find a column (ABC) and it's value 1234 from a schema , basically i need to to check if ABC and a value from this column 1234 is present in any other table that is mapped to ABC , i tried to do a search the most efficient way but it is taking lot of time and not retrieving the desired result
i have tried
https://lalitkumarb.wordpress.com/2015/01/06/sql-to-search-for-a-value-in-all-columns-of-all-atbles-in-an-entire-schema/
but the query is not results at all it is running running...
You may write the output to a file if you get buffer overflow on set Serveroutput otherwise this should do.Output will have all tables that has 'ABC' column and respective count shows count of record with ABC column value as 1234.
SET SERVEROUTPUT ON 100000
DECLARE
lv_count number(10):=0;
l_str varchar2 (1000);
BEGIN
FOR V1 IN
(select distinct table_name
from dba_tab_columns
where column_name = 'ABC')
LOOP
BEGIN
lv_query := ' select count(*) from '||v1.table_name||' where ABC =1234';
EXECUTE IMMEDIATE lv_query INTO lv_count;
dbms_output.put_line(v1.table_name||' --> '||lv_count);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('OTHERS EXCEPTION '||v1.table_name||' ERRCODE '||SQLERRM||' '||SUBSTR(SQLCODE,1,200));
END;
END LOOP;
END;
To find all tables having column_name ABC, simple query as below should do.
select table_name
from dba_tab_columns
where column_name = UPPER('ABC');
PS: Metadata tables(dba_Tab_columns) stores column_name in upper case, to avoid any issues with case ,converting the case to upper for the literal.
Second query in PL/SQL block,
SET SERVEROUTPUT ON 100000
DECLARE
lv_count number(10):=0;
l_str varchar2 (1000);
lv_col_name varchar2(255) :='ABC';
BEGIN
FOR V1 IN
(select distinct table_name
from dba_tab_columns
where column_name = lv_col_name)
LOOP
dbms_output.put_line(lv_col_name||' '||v1.table_name);
END LOOP;
END;

Can not perform DML Operation inside a query? While trying to fetch data from collection

here is my PLSQL code:
declare
headerStr varchar2(1000):='C1~C2~C3~C5~C6~C7~C8~C9~C10~C11~C12~C16~C17~C18~C19~RN';
mainValStr varchar2(32000):='1327~C010802~9958756666~05:06AM~NO~DISPOSAL~NDL~4~P32~HELLO~U~28-OCT-2017~28-OCT-2017~Reject~C010741~1;1328~C010802~9958756666~06:07AM~MH~DROP~NDL~1~P32~~U~28-OCT-2017~28-OCT-2017~Reject~C010741~2;1329~C010802~9999600785~01:08AM~BV~DROP~NDL~2~P32~MDFG~U~28-OCT-2017~28-OCT-2017~Reject~C010741~3';
valStr varchar2(4000);
headerCur sys_refcursor;
mainValCur sys_refcursor;
valCur sys_refcursor;
header varchar2(1000);
val varchar2(1000);
iterator number:=1000;
strIdx number;
strLen number;
idx number;
TYPE T_APPROVAL_RECORD IS TABLE OF VARCHAR2(4000) INDEX BY VARCHAR2(1000);
headerTable T_APPROVAL_RECORD;
cnt number;
begin
open headerCur for select * from table(split_str(headerStr,'~'));
open mainValCur for select * from table(split_str(mainValStr,';'));
loop
fetch mainValCur into valStr;
exit when mainValCur%notfound;
insert into header_test values(cnt, valStr); -- for testing purpose
open valCur for select * from table(split_str(valStr,'~'));
loop
fetch valCur into val;
fetch headerCur into header;
exit when valCur%notfound;
exit when headerCur%notfound;
insert into header_test values(header, val);
headerTable(header):= val;
end loop;
idx := headerTable.FIRST; -- Get first element of array
WHILE idx IS NOT NULL LOOP
insert into header_test values (idx, headerTable(idx));
idx := headerTable.NEXT(idx); -- Get next element of array
END LOOP;
headerTable.delete;
end loop;
commit;
end;
c1 c2 ..... c19 are column name and RN is rownumber,
data for the columns of each will be in mainValString seperated by ;
Why i am getting ORA-14551 when i am trying to access collection "headerTable"?
Please help.
Problem is with this line.
idx := headerTable.FIRST;
The index of headertable is of TYPE VARCHAR2 whereas idx is defined as NUMBER.
declare idx as VARCHAR2(1000), it should work.
Having said that, ORA-14551 - Cannot perform DML ... is not related to this error. It is unclear to me why should you encounter this error.
Oh but it does:
EXCEPTION WHEN OTHERS THEN
v_msg:=sqlcode||sqlerrm;
insert into err_data_transfer values('SPLIT_STR',v_msg,sysdate,null);
It may only be during an exception, but it's still DML during a select statement. You may be able to create another procedure as an AUTONOMOUS_TRANSACTION to create the error log. Also, you should either re-raise or raise_application_error afterward. If not your procedure will continue as though the error did not occur; which leads to more problems as to why your main process does not work (including running to completion but doing the wrong thing).

procedure using record type

I would like to create a procedure which returns a list of the first five records. I must use record type and table type. What am I doing wrong?
CREATE OR REPLACE PROCEDURE procedure_example(v_table OUT v_rec) IS
CURSOR cur1 IS
SELECT * FROM (
SELECT
type_note,
note
FROM dd_note ORDER BY type_note)
WHERE rownum < 5;
TYPE v_rec IS RECORD ( v_type_note NUMBER(2)
, v_note VARCHAR(30));
TYPE v_table IS TABLE OF v_rec INDEX BY BINARY_INTEGER;
BEGIN
OPEN cur1;
LOOP
FETCH cur1 INTO v_type_note, v_note;
dbms_output.put_line(v_type_note || '. --- ' || v_note);
EXIT WHEN cur1%NOTFOUND;
--enter code here
END LOOP;
CLOSE cur1;
END procedure_example;
The place where you declared your types is wrong. You must declare the type "v_rec" and type "v_table" in the package where this procedure belongs, NOT inside this procedure. Here's an improved version of your code. First, declare these types in your package:
TYPE v_rec IS RECORD(
v_type_note number(2),
v_note varchar(30));
TYPE v_table is table of v_rec index by pls_integer;
Then here's your function:
create or replace PROCEDURE procedure_example (out_table OUT v_table) IS
BEGIN
select type_note, note BULK COLLECT into out_table from (select type_note, note from dd_note order by type_note) where rownum < 5
FOR i in 1..out_table.COUNT LOOP
dbms_output.put_line(out_table(i).v_type_note || '. --- ' || out_table(i).v_note);
end loop;
END procedure_example;

Assigning object type in plsql

I need your help to know how to assign the object type through a string in PLSQL
Below is the problem description:
I first created the object types as below:
create or replace type picu_obj is object(Customer_ID varchar2(32767),Customer_Name varchar2(32767),Server_Name varchar2(32767),Time_stamp varchar2(32767));
create or replace type picu_obj_tab is table of picu_obj;
and I have a PLSQL block as below:
declare
l_str1 varchar2(1000);
l_str2 varchar2(10000);
l_newstr1_1 varchar2(10000);
picu_var picu_obj_tab;
cursor c1cudetails
is
select item,current_value
from
(select rownum,
last_value(category ignore nulls) over (order by rownum) category ,
last_value(item ignore nulls) over (order by rownum) item,
current_value
from pi_perfdata_new
order by rownum
)
where upper(category) like '%CUSTOMER%DETAILS%' ;
type cudet is table of c1cudetails%rowtype index by pls_integer;
l_cudet cudet;
begin
/* create dynamic string for items */
open c1cudetails;
fetch c1cudetails bulk collect into l_cudet limit 50;
for i in l_cudet.first..l_cudet.last loop
l_str1:=l_str1||','||''''||l_cudet(i).current_value||'''';
l_str2:=trim(leading ',' from l_str1);
l_newstr1_1:='picu_obj_tab(picu_obj('||l_str2||'))';
end loop;
-- dbms_output.put_line(''||l_newstr1_1||'');
-- picu_var := l_newstr1_1;
close c1cudetails;
end;
For the string "l_newstr1_1" following value is retruned from above PLSQL block
picu_obj_tab(picu_obj('CSCO5','DXRTYE','PI22-pro-333','2015-07-22-22:48:56'))
Now I want to assign the above result to variable "picu_var" which I have declared.
Basically I need to convert to the following during runtime.
picu_var := picu_obj_tab(picu_obj('CSCO5','DXRTYE','PI22-pro-333','2015-07-22-22:48:56'))
How to achieve the same?
Please suggest how to initialize the object type variable to the string values.
Use dynamic PL/SQL like this:
execute immediate 'begin :x := ' || l_newstr1_1|| '; end;'
using out picu_var;

Resources