Oracle errors ORA-00922 and ORA-06512 - oracle

I was trying to run the following script:
SET serveroutput ON
DECLARE
v_nbr_part NUMBER := 2;
v_nbr_subpart NUMBER := 2;
v_table_name VARCHAR2(100) := 'XPTO';
v_table_shortname VARCHAR2(100) := 'XPTO';
v_part_first NUMBER;
v_part_last NUMBER;
v_subpart_first NUMBER;
v_subpart_last NUMBER;
v_sql CLOB := '';
v_sql_part CLOB := '';
v_sql_subpart CLOB := '';
v_part_dynam CLOB := '';
v_part_keys CLOB := '';
BEGIN
IF v_nbr_part > 0 THEN
IF v_nbr_subpart > 0 THEN
v_subpart_first := 0;
v_subpart_last := v_nbr_subpart-1;
v_part_dynam:='';
FOR i IN v_subpart_first .. v_subpart_last
LOOP
v_part_dynam := v_part_dynam || ' SUBPARTITION SP' || i ||' VALUES ('||i||')';
IF i <> v_subpart_last THEN
v_part_dynam := v_part_dynam || ',';
END IF;
END LOOP;
v_sql_subpart:= where_to_save('LDR_SUBTYPE', v_part_dynam);
v_part_keys:= ' , "LDR_SUBTYPE" NUMBER NOT NULL ENABLE ';
END IF;
v_part_first := 1;
v_part_last := v_nbr_part;
v_sql_part:= to_clob(' PARTITION BY RANGE (PART_KEY) interval(numtodsinterval(1,''day'')) ')|| v_sql_subpart ||
to_clob(' ( partition EMPTY values less than (to_date(''01-01-2013'',''DD-MM-YYYY'') ) ) ');
v_part_keys:= ', "PART_KEY" TIMESTAMP (6) NOT NULL ENABLE ' || v_part_keys;
END IF;
v_sql:=to_clob(
'CREATE OR REPLACE TABLE "'||v_table_name||'" (
"SEQUENCENUMBER" NUMBER NOT NULL ENABLE,
"LDRID" VARCHAR2(100),
"LDRTYPE" VARCHAR2(50),
"LDR_SUBTYPE" VARCHAR2(50),
"CREATIONTIMESTAMP" TIMESTAMP (6),
"CORRELATIONID" VARCHAR2(4000),
"PARENTLDRID" VARCHAR2(100),
"NUMBEROFCHILDREN" NUMBER,
"PROTOCOLSESSIONID" VARCHAR2(100),
"ACTIVITYID" VARCHAR2(100),
"ACTIVITYINITIALTIMESTAMP" TIMESTAMP (6),
"ACTIVITYELAPSEDTIME" NUMBER,
"CANCELED" CHAR(1),
"REPLACED" CHAR(1),
"INVALIDATIONTIMESTAMP" TIMESTAMP (6),
"INVALIDATEDBYLDRID" VARCHAR2(100),
"INVALIDATESLDRID" VARCHAR2(100),
"OPERATIONID" VARCHAR2(256),
"ACCOUNTID" VARCHAR2(100),
"TOPLEVELID" VARCHAR2(100),
"RESULTCODE" VARCHAR2(100),
"VERSION" NUMBER,
"LDROBJECT" BLOB,
"OBJMETADATA" BLOB,
"OBJKEY" BLOB,
"OBJKEYHASH" VARCHAR2(200) ') ||
v_part_keys ||
to_clob('
)
LOB (OBJKEY) STORE AS SECUREFILE
LOB (LDROBJECT) STORE AS SECUREFILE
LOB (OBJMETADATA) STORE AS SECUREFILE
') ||
v_sql_part || to_clob(',TABLESPACE OCS LOGGING NOCOMPRESS NOCACHE NOPARALLEL');
dbms_output.put_line(dbms_lob.substr(v_sql,4000,1)); //this is line 84!!!!!!!!!
EXECUTE IMMEDIATE v_sql;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.Put_Line(DBMS_UTILITY.Format_Error_Backtrace);
DBMS_OUTPUT.Put_Line(SQLERRM);
END;
/
CREATE OR REPLACE FUNCTION where_to_save(LDR_SUBTYPE VARCHAR2, v_part_dynam OUT CLOB)
RETURN CLOB
IS
BEGIN
CASE
WHEN LDR_SUBTYPE = ('IEC') THEN v_part_dynam := v_part_dynam || 'SUBPARTITION SP0 VALUES (IEC)';
ELSE v_part_dynam := v_part_dynam || 'SUBPARTITION SP1 VALUES (OTHER)';
END CASE;
RETURN v_part_dynam;
END where_to_save;
The script look good to me, but every time I try to run it I get the following errors:
ORA-06512: line 84
ORA-00922: missing or invalid option
I've searched a lot and the only thing I've found about fixing this was "contact your DBA".
What is wrong with my script? How can I fix this?
P.S.: I've commented line 84 !

Tables can't be created or replaced, try dropping it first or build a pl that drops table if exists.
'CREATE TABLE "'||v_table_name||'" (

Create or replace table
Create or replace view --> yes
but not create or replace table. This Option does not exist.

Related

CLOB - ORA-06502: PL/SQL: numeric or value error: character string buffer too small

I am using Toad For Oracle and I have a procedure in a package where I'm getting the CLOB value for result. I'll be using dummy variables only but I'll be putting the whole process here.
My goal is to a rest web service where my output will be a JSON CLOB.
START OF THE BODY PACKAGE
TYPE in_emp_type IS RECORD ( emp_id NUMBER,
emp_fname VARCHAR2(50), emp_lname VARCHAR2(50),
city VARCHAR2(40), country(50) )
in_emp_rec in_emp_type ;
TYPE out_emp_type IS RECORD (emp_addr_1 VARCHAR2(100), emp_addr_2 VARCHAR2(100);
TYPE out_emp_tab_type IS TABLE OF out_emp_type;
query_tab out_emp_tab_type := out_emp_tab_type ();
PROCEDURE get_employee_details(api_key VARCHAR2, emp_id NUMBER,
emp_fname VARCHAR2, emp_lname VARCHAR2, out_result_json OUT CLOB ) IS
CURSOR get_all_emp IS
select city, country from emp_table
where emp_id = emp_id
and fname = emp_fname
and lname = emp_lname ;
CURSOR get_emp_addr (emp_id NUMBER, city VARCHAR2) IS
select addr_1, addr_2 from emp_addr
where emp_id = emp_id and city = city;
v_city VARCHAR2;
v_country VARCHAR2;
v_json_input CLOB;
v_result_json CLOB;
BEGIN
open get_all_emp;
fetch get_all_emp into v_city , v_country ;
close get_all_emp;
v_json_input := '{"EmployeeDetails":
{"EmployeeID": || emp_id || ' ",
"EmployeeFirstName": || emp_fname || '",
"EmployeeLastName": || emp_lname || '",
"EmployeeCity": || v_city || '",
"EmployeeCountry": || v_country || '"}'
convert_input_json(v_json_input,in_emp_rec);
open get_emp_addr (emp_id, city);
fetch get_emp_addr bulk collect into query_tab ;
v_result_json := convert_result_json(query_tab);
out_result_json := v_result_json;
END;
And this is my sample of the convert_input_json procedures & convert_result_json function
PROCEDURE convert_input_json(input_json IN CLOB, output_json OUT in_emp_type) IS
CURSOR get_details IS
select emp_id, emp_fname, emp_lname, city, country
from json_table(input_json, '$' COLUMNS (
emp_id NUMBER PATH '$.EmployeeDetails.EmployeeID',
emp_fname VARCHAR2(50) PATH '$.EmployeeDetails.EmployeeFirstName',
emp_lname VARCHAR2(50) PATH '$.EmployeeDetails.EmployeeLastName', ... includeother fields here)
BEGIN
output_json := in_emp_type( emp_id => NULL, emp_fname => NULL....)
open get_details;
fetch get_details into output_json.emp_id , output_json.emp_fname ....);
close get_details;
END;
FUNCTION convert_result_json (in_result out_emp_tab_type) RETURN CLOB IS
v_clob CLOB
BEGIN
FOR i in 1...query_tab.count LOOP
v_clob := '{ '||chr(13)||'"customerResults": {'
v_clob := v_clob||chr(13)||chr(9)||chr(9)||'"addr1": "'||query_tab(i).emp_addr_1 ||'",';
v_clob := v_clob||chr(13)||chr(9)||chr(9)||'"addr2": "'||query_tab(i).emp_addr_2 ||'",';
END LOOP;
RETURN (v_clob)
END;
So when I try to run this, I'm getting the ORA-06502: PL/SQL: numeric or value error: character string buffer too small
And I'm not really sure why am I getting this error. Can someone please help me.
There should be an error stack trace showing the line number that raised the exception. Looking at your code, there are two obvious places where this can happen:
The JSON_TABLE COLUMNS mapping - ensure that emp_fname/emp_lname never overflows the allotted 50 characters.
In the convert_result_json function, you are using || to append new addresses to an existing CLOB value. || will convert the operands to varchar2(32767). If the size of the CLOB + the new string being appended > 32KB, it will fail due to the varchar2 datatype limit. If this is your issue, use dbms_lob to append to your LOBs, not ||.

How to pass JSON type data as an input parameter in a Stored procedure

I have one requirement wherein I need to pass JSON as an input parameter and process the data accordingly.
JSON data:
{
"Table name": "test_table",
"Column name":["column_1","column_2"],
"Column_value":["test_data","1"]
}
I need to write a procedure with this JSON as an input parameter.
Then based on the table name and column name it should insert the particular column value into the respective columns of a table.
Pseudo Code:
Store JSON in one table with the table structure as
table_id |Table_name | Column_name | Column_value
Then pass table_name, column_name, and column_values JSON format as input parameters.
Then extract tables, columns, and column_value from the input parameter and load in into the respective table.
Will this work? As I am not aware of how to handle JSON in a stored procedure or if anyone has any clue of how to start with this it would help me.
Tool Used: SQL Developer (18c)
You can use:
CREATE PROCEDURE load_data(
i_json IN CLOB
)
IS
v_obj JSON_OBJECT_T := JSON_OBJECT_T(i_json);
v_tbl VARCHAR2(20) := v_obj.get_string('Table name');
v_cols JSON_ARRAY_T := v_obj.get_Array('Column name');
v_vals JSON_ARRAY_T := v_obj.get_Array('Column_value');
v_sql CLOB := 'INSERT INTO ';
v_sql_vals CLOB := ') VALUES (';
BEGIN
v_sql := v_sql || DBMS_ASSERT.SQL_OBJECT_NAME(
DBMS_ASSERT.ENQUOTE_NAME(v_tbl, FALSE)
);
v_sql := v_sql || ' (';
FOR pos IN 0 .. v_cols.get_size() - 1
LOOP
IF pos > 0 THEN
v_sql := v_sql || ',';
v_sql_vals := v_sql_vals || ',';
END IF;
v_sql := v_sql || DBMS_ASSERT.ENQUOTE_NAME(v_cols.get_string(pos), FALSE);
v_sql_vals := v_sql_vals || DBMS_ASSERT.ENQUOTE_LITERAL(v_vals.get_string(pos));
END LOOP;
v_sql := v_sql || v_sql_vals || ')';
EXECUTE IMMEDIATE v_sql;
END;
/
If you have the table:
CREATE TABLE "test_table" (
"column_1" VARCHAR2(20),
"column_2" NUMBER
);
Then you can use:
BEGIN
load_data('{
"Table name": "test_table",
"Column name":["column_1","column_2"],
"Column_value":["test_data","1"]
}');
END;
/
And the table will contain:
SELECT * FROM "test_table";
column_1
column_2
test_data
1
db<>fiddle here

Pass a table name and time stamp variable to a PL/SQL

I am writing a below PL/SQL code in SQL developer to delete data from a table with a timestamp column in the where condition. How can I modify this code to pass the table name and the timestamp value to values that I want based on what table and time records I want to delete the data from and create a stored procedure that can be reused.
DBMS_OUTPUT.ENABLE;
DECLARE
counter INTEGER := 0;
stop INTEGER;
BEGIN
dbms_output.put_line('START');
LOOP
counter := counter + 1;
DELETE my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM'
AND ROWNUM <= 100000;
SELECT COUNT(*)
INTO stop
FROM my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM';
EXIT WHEN stop <= 0;
COMMIT;
END LOOP;
dbms_output.put_line('Counter: ' || counter);
dbms_output.put_line('Left: ' || stop);
COMMIT;
END;
Adapting your anonymous to a stored procedure will, as indicated, require converting it to dynamic SQL. Always more difficult. And subject to SQL injection. For this you should validate string replacement parameters. I have a couple other changes:
Pass the desired as a timestamp, not a string, this allows/forces the
calling routine to determine the format and necessary conversion, if
any.
Added a parameter for column name as well. This frees naming columns
from the requirement of the procedure.
There is no need to count remaining items. Your loop processes until
that value reaches 0, but this can be determined by the number of
rows deleted on the last pass. Delete sets sql%rowcount to the number
of rows deleted. When the pass deletes 0 rows the process is
complete.
Removed the results display and the commit from the procedure, again
offloading this to the caller.
create or replace
procedure delete_values_by_timestamp
( p_table_name in varchar2
, p_column_name in varchar2
, p_timestamp in timestamp
, p_result_msg out varchar2
)
IS
table_name_parameter_invalid exception;
pragma exception_init(table_name_parameter_invalid, -44002);
column_name_parameter_invalid exception;
pragma exception_init(column_name_parameter_invalid, -44003);
k_nl constant varchar2(1) := chr(10);
k_max_delete_per_interation constant integer := 100000;
k_base_delete varchar2(256) :=
'delete from <table_name>' ||
' where <column_name> <= :1' ||
' and rownum <= :2';
v_delete_sql varchar2 (256) ;
v_rows_deleted integer := 0;
begin
v_delete_sql := replace(replace(k_base_delete,'<table_name>', dbms_assert.sql_object_name(p_table_name))
,'<column_name>',dbms_assert.simple_sql_name(p_column_name));
dbms_output.put_line('Running SQL:' || k_nl || v_delete_sql);
loop
execute immediate v_delete_sql using p_timestamp, k_max_delete_per_interation;
exit when sql%rowcount = 0;
v_rows_deleted :=v_rows_deleted + sql%rowcount;
end loop;
if v_rows_deleted = 0
then
p_result_msg := 'No Data Found';
else
p_result_msg := 'Number of Rows Deleted ' || to_char(v_rows_deleted);
end if;
exception
when table_name_parameter_invalid then
raise_application_error(-20199,'Invalid Table Name (' || p_table_name || ') specified.');
when column_name_parameter_invalid then
raise_application_error(-20198,'Invalid Column Name (' || p_column_name || ') specified.');
end delete_values_by_timestamp;
See example: In the example I reduce the number of rows deleted on each iteration from 100000 to 20. An additionally enhancement would be to pass the number of rows for each iteration as a parameter.
I couldn't test it but you could create a function whcih takes the table name and the timestamp as parameter.
As long you want to delete every record with the given timestamp you don't need to loop for each record.
This function should be just an example.
FUNCTION delete_values_by_timestamp (p_table_name IN VARCHAR2 DEFAULT NULL,
p_timestamp IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2
IS
v_count NUMBER := 0;
v_query VARCHAR2 (500) := '';
BEGIN
IF p_table_name IS NOT NULL
THEN
IF p_timestamp IS NOT NULL
THEN
v_query := 'SELECT COUNT(*)
FROM my_schema.' || p_table_name | '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query INTO v_count;
IF v_count > 0
THEN
v_query := 'DELETE FROM my_schema.' || p_table_name || '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query;
ELSE
RETURN 'NO RECORDS FOUND!';
END IF;
ELSE
RETURN 'TIMESTAMP EMPTY!';
END IF;
ELSE
RETURN 'TABLE NAME EMPTY!';
END IF;
END;

ORA-01007: variable not in select list while fetch c2 into cursor2

I have oracle pl/sql procedure with below:
TYPE Paycomp2 IS RECORD(
Row_Id VARCHAR2(15),
Created DATE,
Created_By VARCHAR2(15),
Last_Upd DATE,
Last_Upd_By VARCHAR2(15),
Modification_Num NUMBER(10),
Conflict_Id VARCHAR2(15),
Comp_Price NUMBER(10),
Access_Level VARCHAR2(30),
Comp_Name VARCHAR2(30),
Depends_On VARCHAR2(30),
Gold_Cat VARCHAR2(30),
Order_Type VARCHAR2(30),
Parent_Id VARCHAR2(15),
Price_Plan VARCHAR2(30),
TYPE VARCHAR2(30),
Check_Flag VARCHAR2(1),
PREPAID_INIT_PRICE number(10),
DB_LAST_UPD date,
DB_LAST_UPD_SRC varchar2(50),
Unit_Type varchar2(30),
M2M_CATEGORY varchar2(30));
TYPE Paycomp IS REF CURSOR;
C2 Paycomp;
Cursor2 Paycomp2;
when I do the below operation
FETCH C2 INTO Cursor2;
I am getting this error :
ORA-01007: variable not in select list error.
This piece of script has worked previously.
How to resolve this issue?
script
Vordertype := 'Migration Prepaid - Postpaid';
Curcomp_Sql := Curcomp_Sql || Vordertype || '''' || ' union all ' || '' || Curcomp2sql || '' ||
Vordertype || '''';
OPEN C2 FOR Curcomp_Sql;
Sadmin.Pkg_Spliter.Prcsplitchar(Ppaycompstr, ';', Arrcomplist);
Vtotalcompprc := 0;
Arrcount := Arrcomplist.Count;
BEGIN
Dbms_output.put_line('reached17');
LOOP
FETCH C2
INTO Cursor2;
Dbms_output.put_line('reached18');
EXIT WHEN C2%NOTFOUND;
-- Processing each entry from Array
Compfndflg := 0;
dbms_output.put_line('arrCount 0: reached');
FOR Counter IN 1 .. Arrcount
LOOP
Vstrcommand := Arrcomplist(Counter);
dbms_output.put_line('arrCount : reached');
Sadmin.Pkg_Spliter.Prcsplitchar(Vstrcommand, '?', Arrdisclist);
IF Arrdisclist.Count <> 0 THEN
dbms_output.put_line('arrCount : reached1');
-- Extracting the ? seperated values and putting them into variables
Vcompname := Arrdisclist(1);
--dbms_output.put_line(CURSOR2.comp_name||':- count -'||COUNTER||'--'||VCOMPNAME);
BEGIN
-- Added by Accenture
IF Vcompname IS NOT NULL THEN
--dbms_output.put_line(CURSOR2.comp_name||':- count -'||COUNTER||'--'||ARRDISCLIST(1)||'-'||ARRDISCLIST(2)||'-'||ARRDISCLIST(3));
SELECT COUNT(0)
INTO v_Count_Exist
FROM Siebel.Cx_Paycomp_Mtx a, Siebel.Cx_Paycomp_Mtx b
WHERE a.Row_Id = b.Parent_Id
AND a.Order_Type = Vordertype
AND b.Type = 'Payment Component'
AND b.Comp_Name = Vcompname;
IF (v_Count_Exist = 0) THEN
Err_Msg := 'Invalid Payment Component in String';
Result_Out := '74';
Errflg := 1;
--dbms_output.put_line('Counter 2' || counter);
--dbms_transaction.rollback;
RAISE Error_Out;
END IF;
END IF;
--dbms_output.put_line('Counter 3' || CURSOR2.comp_name);
IF Vcompname = Cursor2.Comp_Name
--and VCOMPNAME != '3'
THEN
Compfndflg := 1;
EXIT;
END IF;
END;
END IF;
END LOOP;
---DBMS_OUTPUT.PUT_LINE('VCOMPNAME, COMPFNDFLG'||VCOMPNAME||','||COMPFNDFLG);
--dbms_output.put_line('CURSOR2.comp_name :'||CURSOR2.comp_name||' - COMPFNDFLG :'||COMPFNDFLG);
IF Compfndflg != 1 THEN
IF Temp_Comp_String IS NULL THEN
Temp_Comp_String := Cursor2.Comp_Name || '?0?;';
---DBMS_OUTPUT.PUT_LINE('STRING 1'||TEMP_COMP_STRING);
ELSE
Temp_Comp_String := Temp_Comp_String || Cursor2.Comp_Name || '?0?;';
---DBMS_OUTPUT.PUT_LINE('STRING 2'||TEMP_COMP_STRING);
END IF;
--- END IF;
ELSE
IF Temp_Comp_String IS NULL THEN
Temp_Comp_String := Arrdisclist(1) || '?' || Arrdisclist(2) || '?' ||
Arrdisclist(3) || ';';
---DBMS_OUTPUT.PUT_LINE('STRING 3'||TEMP_COMP_STRING);
ELSE
Temp_Comp_String := Temp_Comp_String || Arrdisclist(1) || '?' || Arrdisclist(2) || '?' ||
Arrdisclist(3) || ';';
---DBMS_OUTPUT.PUT_LINE('STRING 4'||TEMP_COMP_STRING);
END IF;
-- end if;
--- END IF;
END IF;
END LOOP;
END;
Curcomp_Sql VARCHAR2(2000) := 'SELECT mtx2.*
FROM siebel.CX_PAYCOMP_MTX mtx1, siebel.CX_PAYCOMP_MTX mtx2
WHERE mtx2.parent_id = mtx1.row_id
AND mtx2.comp_name <> ''Security Deposit''
AND mtx2.TYPE = ''Payment Component''
AND mtx1.order_type = ''';
Curcomp2sql VARCHAR2(2000) := 'SELECT mtx2.*
FROM siebel.CX_PAYCOMP_MTX mtx1, siebel.CX_PAYCOMP_MTX mtx2
WHERE mtx2.parent_id = mtx1.row_id
AND mtx2.comp_name = ''Security Deposit''
AND mtx2.TYPE = ''Payment Component''
AND mtx2.depends_on = ''ACCESS LEVEL''
AND mtx1.order_type = ''';
A simplified version of what you're seeing, with a dummy table and simple anonymous block:
create table t42 (id number, some_value varchar2(10));
declare
type t_rec is record(id number, some_value varchar2(10));
l_rec t_rec;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
close l_cur;
end;
/
PL/SQL procedure successfully completed.
To get the error you're seeing I just need to remove one of the table columns:
alter table t42 drop column some_value;
and run exactly the same code again:
declare
type t_rec is record(id number, some_value varchar2(10));
l_rec t_rec;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
close l_cur;
end;
/
ORA-01007: variable not in select list
ORA-06512: at line 10
The field list in the record type declared in the PL/SQL block no longer matches the column type in the cursor query. The record variable you're fetching into expects two columns (in my version; 22 in yours), but the query only gets one value.
You can (some would say should) specify all the columns you're selecting explicitly, but assuming you're actually referring to them all later you would then have done the equivalent of:
open l_cur for 'select id, some_value from t42';
which would still have errored after the column removal, though a bit more helpfully perhaps:
ORA-00904: "SOME_VALUE": invalid identifier
ORA-06512: at line 9
Since you're currently intending to get all columns from a single table, you could also have used the %rowtype syntax instead of your own record type:
declare
l_rec t42%rowtype;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
close l_cur;
end;
/
which with this trivial example runs successfully. You'll still have a problem though as soon as you refer to the removed column, assuming it's still part of the record:
declare
l_rec t42%rowtype;
l_cur sys_refcursor;
begin
open l_cur for 'select * from t42';
fetch l_cur into l_rec;
dbms_output.put_line(l_rec.some_value);
close l_cur;
end;
/
ORA-06550: line 7, column 30:
PLS-00302: component 'SOME_VALUE' must be declared
ORA-06550: line 7, column 3:
PL/SQL: Statement ignored
(Using %rowtype would give you some breathing space if a column was added, as it would just be ignored, unless and until you added code to refer to that record field. But with your code you'd get ORA-00932 inconsistent data types, rather than ORA-01007, so that doesn't seem to be what's happening here.)
If you aren't referring to the removed column/field anywhere then you shouldn't be selecting it anyway. Change the record type to only include the fields you actually need, and only get the corresponding columns in the cursor query.
If you are referring to the removed column/field then you're stuck anyway - you'll have find out what was removed and why, and then either fix your code to not refer to it (if that makes sense), or get that change reverted.

pass function argument to cursor in oracle

I am getting an error while passing function argument to the cursor. Here is the Below example
Create OR Replace FUNCTION UPD_TAB(ID_VAL IN OUT VARCHAR2,SRC_COLUMN IN OUT VARCHAR2,DEST_COLUMN IN OUT VARCHAR2,OWNER_TAB IN OUT VARCHAR2,SRC_TAB IN OUT VARCHAR2,DEST_TAB IN OUT VARCHAR2)
RETURN VARCHAR2
IS
SRC_COL VARCHAR2(30) := SRC_COLUMN;
DEST_COL VARCHAR2(20) := DEST_COLUMN;
ID_VALUE VARCHAR2(20) := ID_VAL;
SRC_TABLE VARCHAR(20) := SRC_TAB;
DEST_TABLE VARCHAR(20) := DEST_TAB;
TAB1 VARCHAR2(40) := OWNER_TAB||'.'||SRC_TAB;
TAB2 VARCHAR2(40) := OWNER_TAB||'.'||DEST_TAB;
CURSOR RET_VAL
IS
SELECT C1.SRC_COL,C2.DEST_COL
FROM TAB1 C1,TAB2 C2
WHERE C1.SRC_COL=C2.DEST_COL
AND C1.ID=ID_VALUE;
Here in the above example when pass pass the actual database values Schemaname.Tablename
eg. grany.Booking . It output the results but when i pass the variable having value TAB1 and TAB2. It shows the following error
PL/SQL: ORA-00942: table or view does not exist
22/11 PL/SQL: Statement ignored
i searched a lot but didn't find the solution
I know what error is trying to say but i dont know how to fix the solution for this one.
Any help will be appreciated. Thanks in advance.
Static cursors cannot obtain table and column names from variables. One way to get around this is to build the query in a VARCHAR2 variable and then open a generic cursor (SYS_REFCURSOR type, defined in package SYS.STANDARD) for the query string:
CREATE OR REPLACE FUNCTION UPD_TAB(ID_VAL IN OUT VARCHAR2,
SRC_COLUMN IN OUT VARCHAR2,
DEST_COLUMN IN OUT VARCHAR2,
OWNER_TAB IN OUT VARCHAR2,
SRC_TAB IN OUT VARCHAR2,
DEST_TAB IN OUT VARCHAR2)
RETURN VARCHAR2
IS
SRC_COL VARCHAR2(30) := SRC_COLUMN;
DEST_COL VARCHAR2(20) := DEST_COLUMN;
ID_VALUE VARCHAR2(20) := ID_VAL;
SRC_TABLE VARCHAR2(20) := SRC_TAB;
DEST_TABLE VARCHAR2(20) := DEST_TAB;
TAB1 VARCHAR2(40) := OWNER_TAB||'.'||SRC_TAB;
TAB2 VARCHAR2(40) := OWNER_TAB||'.'||DEST_TAB;
vVAL1 VARCHAR2(2000);
vVAL2 VARCHAR2(2000);
strCursor VARCHAR2(32767) :=
'SELECT C1.' || SRC_COL ||
',C2.' || DEST_COL ||
'FROM ' || TAB1 || ' C1, ' ||
TAB2 || ' C2 ' ||
'WHERE C1.' || SRC_COL || '=C2.' || DEST_COL || ' AND ' ||
'C1.ID=' || ID_VALUE;
csr SYS_REFCURSOR;
BEGIN
OPEN csr FOR strCursor;
LOOP
FETCH csr
INTO vVAL1, vVAL2;
EXIT WHEN csr%NOTFOUND;
-- Do something useful with values fetched from cursor;
END LOOP;
CLOSE csr;
END UPD_TAB;
Share and enjoy.

Resources