PL/SQL - Create tables based on cursor using execute immediate? - sql

I've written the following code that selects some student test data and using a cursor, inserts it into a table.
What id like to be able to do is create one table for each student and insert their relative data. This could be one row or multiple rows.
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE run_student_scores
IS
CURSOR c_pass_fail_cursor
IS
SELECT students.firstname,
test_history.score,
test_id.test_name,
test_id.passing_grade
FROM students
INNER JOIN test_history
ON students.student_id = test_history.student_id
INNER JOIN test_id
ON test_id.test_id = test_history.test_id
WHERE test_history.start_time BETWEEN to_timestamp(sysdate) + INTERVAL '8' HOUR
AND to_timestamp(sysdate) + INTERVAL '21' HOUR;
v_name students.firstname%TYPE;
v_score test_history.score%TYPE;
v_test varchar2(40);
v_passing test_id.passing_grade%TYPE;
v_result varchar2(4);
BEGIN
EXECUTE IMMEDIATE ('create table student_tests_' || (to_char(sysdate, 'yyyymmdd')) || '(student_name VARCHAR2(20), test_name varchar2(40), test_score NUMBER(3), pass_rate NUMBER(3), pass_fail VARCHAR2(4))');
OPEN c_pass_fail_cursor;
LOOP
FETCH c_pass_fail_cursor INTO v_name, v_score, v_test, v_passing;
EXIT WHEN c_pass_fail_cursor%NOTFOUND;
If v_score < v_passing
THEN v_result := 'Fail';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
ELSE
v_result := 'Pass';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
END IF;
EXECUTE IMMEDIATE 'INSERT INTO student_tests_' || (to_char(sysdate, 'yyyymmdd')) || ' ' || ' values(:1, :2, :3, :4, :5)' using v_name, v_test, v_score, v_passing, v_result;
END LOOP;
CLOSE c_pass_fail_cursor;
END;
/
I've played around with it for the last couple of days and cant get it to work. The closest i can get is to create the tables and insert the first row only, generating an error when the loop tries to create a table that already exists.
Any help would be awesome
Thanks folks
Ben

Outcome: 1 table for each student (unique by name).
The create table ... is now inside the loop surrounded by an exception block. If the table already exists, the exception (ORA-00955) is handled.
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE run_student_scores
IS
CURSOR c_pass_fail_cursor
IS
SELECT students.firstname,
test_history.score,
test_id.test_name,
test_id.passing_grade
FROM students
INNER JOIN test_history
ON students.student_id = test_history.student_id
INNER JOIN test_id
ON test_id.test_id = test_history.test_id
WHERE test_history.start_time BETWEEN to_timestamp(sysdate) + INTERVAL '8' HOUR
AND to_timestamp(sysdate) + INTERVAL '21' HOUR;
v_name students.firstname%TYPE;
v_score test_history.score%TYPE;
v_test varchar2(40);
v_passing test_id.passing_grade%TYPE;
v_result varchar2(4);
--New variables
table_already_exists EXCEPTION;
PRAGMA EXCEPTION_INIT(table_already_exists, -955);
BEGIN
OPEN c_pass_fail_cursor;
LOOP
FETCH c_pass_fail_cursor INTO v_name, v_score, v_test, v_passing;
EXIT WHEN c_pass_fail_cursor%NOTFOUND;
begin
EXECUTE IMMEDIATE ('create table student_tests_' || v_name || ' (student_name VARCHAR2(20), test_name varchar2(40), test_score NUMBER(3), pass_rate NUMBER(3), pass_fail VARCHAR2(4))');
exception when table_already_exists then
null;
end;
If v_score < v_passing
THEN v_result := 'Fail';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
ELSE
v_result := 'Pass';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
END IF;
EXECUTE IMMEDIATE 'INSERT INTO student_tests_' || v_name || ' ' || ' values(:1, :2, :3, :4, :5)' using v_name, v_test, v_score, v_passing, v_result;
END LOOP;
CLOSE c_pass_fail_cursor;
END;
/

Grafros answer looks good, but i strongly recommend to take a look at DBMS_ASSERT with DBMS_ASSERT.ENQUOTE_NAME or DBMS_ASSERT.ENQUOTE_LITERAL whenever you have take abitrary strings and use them in execute immidiate.

Related

Print a json structure from a dynamic query

I want to create function that return a CLOB with a json content.
But first i want to print the result (see query code) to see how it looks like.
The result must be a json, that will contain the information for 1 record just, this record select query, must be created dynamically.
So I try the next query, to resolve this problem. but i get an error.
Query
declare
v_stmt VARCHAR2(1000);
l_sep varchar2(1) := chr(10);
l_tab varchar2(1) := chr(9);
up_column VARCHAR2(50);
low_column VARCHAR2(50);
cur_asc SYS_REFCURSOR;
Vcdogcur SYS_REFCURSOR;
id_ccd number;
first boolean := true;
begin
id_ccd := 174;
v_stmt := 'select ';
open cur_asc for
SELECT column_name as up_column
,lower(column_name) as low_column
FROM USER_TAB_COLUMNS
WHERE table_name = upper('my_table');
loop
FETCH cur_asc
INTO up_column, low_column;
EXIT WHEN cur_asc%NOTFOUND;
if not first then
v_stmt := v_stmt || ',';
end if;
first := false;
v_stmt := v_stmt || l_sep || l_tab ||up_column || ' as ' || low_column;
END LOOP;
--v_stmt := v_stmt || l_sep || 'from my_table' || l_sep ||'where id = ' || id_ccd || ';';
v_stmt := v_stmt || l_sep || 'from my_table' || l_sep ||'where id = ' || id_ccd;
DBMS_OUTPUT.PUT_LINE('salida: ' || v_stmt);
CLOSE cur_asc;
--v_stmt := v_stmt || l_sep || 'from my_table' || l_sep ||'where id = ' || id_ccd;
--DBMS_OUTPUT.PUT_LINE('salida: ' || v_stmt);
open Vcdogcur for v_stmt;
APEX_JSON.initialize_clob_output;
APEX_JSON.open_object;
APEX_JSON.write('my_table', Vcdogcur);
APEX_JSON.close_object;
DBMS_OUTPUT.put_line(APEX_JSON.get_clob_output);
CLOSE Vcdogcur;
end;
/
DBMS output
salida: select
CREATED as created,
CREATED_BY as created_by,
UPDATED as updated,
UPDATED_BY as updated_by,
ID as id,
TEXT as text,
PART as part,
CODE as code,
DATE as date,
PERCENTAGE as percentage
from my_table
where id = 174
{
"my_table":[
{
"CREATED":"2020-06-04T08:10:09.000000000Z"
,"CREATED_BY":"APEX_APP"
,"UPDATED":"2020-06-04T10:10:09.295632000Z"
,"UPDATED_BY":"APEX_APP"
,"ID":174
,"TEXT":"ALL"
,"PART":2770
,"CODE":2212
,"DATE":"2017-01-01T00:00:00.000000000Z"
,"PERCENTAGE":-4.98
}
]
}
Error
Informe de error -
ORA-01001: cursor no válido
ORA-06512: en línea 44
01001. 00000 - "invalid cursor"
*Cause:
*Action:
Can somebody help me to resolve this?
Best Regards

ORA-01722: invalid number in execute immediate

I am running the following script in SQL Developer but getting the below error -
ORA-01722: invalid number
ORA-06512: at line 85
The data passed to this query is coming from a different table.
DATA BEING PASSED -
BAN - 945170744, ACTV_BILL_SEQ_NO- 12 , SUBSCRIBER_NO - 1234567891, DISCOUNT_CD - NULL, PRIOD_CVRG_ND_DATE - 04-JAN-20,
Note - Ban is defined as NUMBER(9) in both the tables.
SCRIPT -
SET SERVEROUTPUT ON
DECLARE
V_HIERARCHY_ID NUMBER(10);
V_NODE_CYCLE NUMBER(2);
V_BILL_CYCLE NUMBER(2);
V_DISCOUNT_CD CHAR(9);
V_EXP_DATE DATE;
V_COUNT NUMBER(3);
v_val_Done_by varchar2(25) ;
v_ban NUMBER(9);
v_comments varchar2(20);
v_success varchar2(10) :='SUCCESS';
v_yesnoind varchar2(1) :='Y';
v_comments_1 varchar2(30) :='DISCOUNT EXPIRED';
v_comments_2 varchar2(30) :='DISCOUNT NOT FOUND';
v_issue_Desc varchar2(50) :='NEW RECORD MISSING';
BEGIN
DBMS_OUTPUT.put_line ('BAN: '|| :1 || ' ACTV_BILL_SEQ_NO : ' || :2 || ' SUBSCRIBER: '|| :3 ||
'COLUMN_NAME : ' || :4|| ' COLUMN_DATA: '|| :5|| 'DIFF_DATA : ' || :6 || ' SOC: ' ||:7|| '
FEATURE_CODE: ' ||:8|| ' FTR_REVENUE_CODE: ' ||:9|| ' PRIOD_CVRG_ST_DATE: ' ||:10|| '
PRIOD_CVRG_ND_DATE: ' ||:11|| ' ACTV_REASON_CODE: ' ||:12|| 'BALANCE_IMPACT_CODE: '|| :13 || '
SOURCE_APPL_CODE : ' || :14 || ' DISCOUNT_CD: '|| :15 || ' BILL_MEDIA : ' || :16|| 'BILL_FORMAT : '
|| :17 || ' PRODUCT_TYPE: ' ||:18|| ' FTR_TYPE ' ||:19 || ' VAL_ID ' ||:20 );
v_ban :=:1;
V_DISCOUNT_CD :=:15;
V_EXP_DATE :=:11;
dbms_output.put_line(V_DISCOUNT_CD);
dbms_output.put_line(V_EXP_DATE);
select 'comments_'|| :20 into v_comments from dual;
select 'val_done_by_'|| :20 into v_val_Done_by from dual;
DBMS_OUTPUT.Put_line(v_val_Done_by);
DBMS_OUTPUT.Put_line(v_comments);
SELECT HIERARCHY_ID INTO V_HIERARCHY_ID FROM BILLING_ACCOUNT WHERE BAN =:1;
IF V_HIERARCHY_ID IS NULL
THEN
SELECT COUNT(*) INTO V_COUNT FROM BAN_DISCOUNT WHERE BAN =:1 AND TRIM(DISCOUNT_CODE) =
V_DISCOUNT_CD AND EXPIRATION_DATE < V_EXP_DATE;
IF V_COUNT >= 1
THEN
EXECUTE IMMEDIATE 'UPDATE BL_DIFF_CATEGORY SET VALIDATION_STS=:2,' || v_val_Done_by || ' = :3, '
|| v_comments || ' = :4 WHERE BAN = :1 AND DIFF_TYPE = :5'
using v_issue_Desc,v_comments_1,v_yesnoind,v_success,v_ban;
COMMIT;
ELSE
EXECUTE IMMEDIATE 'UPDATE BL_DIFF_CATEGORY SET VALIDATION_STS=:2,' || v_val_Done_by || ' = :3, '
|| v_comments || ' = :4 WHERE BAN = :1 AND DIFF_TYPE = :5'
using v_issue_Desc,v_comments_2,v_yesnoind,v_success,v_ban;
COMMIT;
END IF;
ELSE
-- NODE LEVEL DISCOUNT CHECK
SELECT COUNT(*) INTO V_COUNT FROM CH_OBJECT_ATTRIBUTES
WHERE
OBJ_ID IN ( SELECT ARC_FATHER_ID FROM CH_ARCS WHERE ARC_CHILD_ID = V_HIERARCHY_ID)
AND ATTR_NAME = 'Discount Plans'
AND ATTR_VALUE = V_DISCOUNT_CD
AND VALID_TO < V_EXP_DATE;
-- BAN LEVEL DISCOUNT CHECK
SELECT COUNT(*) INTO V_COUNT FROM CH_OBJECT_ATTRIBUTES
WHERE
OBJ_ID = V_HIERARCHY_ID
AND ATTR_NAME = 'Discount Plans'
AND ATTR_VALUE = V_DISCOUNT_CD
AND VALID_TO < V_EXP_DATE;
-- SUBSCRIBER LEVEL DISCOUNT CHECK
SELECT COUNT(*) INTO V_COUNT FROM CH_OBJECT_ATTRIBUTES
WHERE
OBJ_ID IN ( SELECT ARC_CHILD_ID FROM CH_ARCS WHERE ARC_FATHER_ID = V_HIERARCHY_ID)
AND ATTR_NAME = 'Discount Plans'
AND ATTR_VALUE = V_DISCOUNT_CD
AND VALID_TO < V_EXP_DATE;
IF V_COUNT >= 1
THEN
EXECUTE IMMEDIATE 'UPDATE BL_DIFF_CATEGORY SET VALIDATION_STS=:2,' || v_val_Done_by || ' = :3, '
|| v_comments || ' = :4 WHERE BAN = :1 AND DIFF_TYPE = :5'
using v_issue_Desc,v_comments_1,v_yesnoind,v_success,v_ban;
COMMIT;
ELSE
(I am facing the above error in this ELSE part in below line as it is going in this line 85)
EXECUTE IMMEDIATE ''UPDATE BL_DIFF_CATEGORY SET VALIDATION_STS=:2,'' || v_VAL_DONE_BY || '' =
:3, '' || v_comments || '' = :4 WHERE BAN = :1 AND DIFF_TYPE = :5''
using v_issue_Desc,v_comments_2,v_yesnoind,v_success,v_ban;
COMMIT;
END IF;
END IF;
END;
(I am facing the above error in this ELSE part in below line as it is going in this line 85)
EXECUTE IMMEDIATE ''UPDATE BL_DIFF_CATEGORY SET VALIDATION_STS=:2,'' || v_VAL_DONE_BY || '' = :3, '' || v_comments || '' = :4 WHERE BAN = :1 AND DIFF_TYPE = :5''
using v_issue_Desc,v_comments_2,v_yesnoind,v_success,v_ban;
There seems to be some discrepancy between orders of the placeholders in the string and the parameters in the USING clause. For instance BAN = :1 is the fourth placeholder but v_ban is the fifth variable passed to the EXECUTE IMMEDIATE statement, whilst the value actually assigned to BAN is v_success.
Perhaps you simply need to review the placeholders and re-order the parameters? If so, remember to do the same for the statement in the IF branch.
Incidentally, the names of the placeholders in the string don't matter, but if you're going to use numbers you might as well put them in numeric order.
DISCOUNT_CD - NULL <== Null is not a valid number -- you need a coalesce here
eg
SELECT COUNT(*) INTO V_COUNT FROM CH_OBJECT_ATTRIBUTES
WHERE
OBJ_ID IN ( SELECT ARC_CHILD_ID FROM CH_ARCS WHERE ARC_FATHER_ID = V_HIERARCHY_ID)
AND ATTR_NAME = 'Discount Plans'
AND ATTR_VALUE = COALESCE(V_DISCOUNT_CD,0)
AND VALID_TO < V_EXP_DATE;

continuing loops a thing in oracle

I am carrying out another exercise to learn various things about Oracle SQL's syntax today's lesson I've chosen are loops. Please see below code where I am trying to have two fields (temp variables) having values being decreased until it's less than zero depending on which of the variables hit's zero depends on what text I would like to output into the script output. Hopefully it makes sense. If I have made any faux pas's please do shout at me.
DECLARE
"Character" VARCHAR2(255);
"Enemy" VARCHAR2(255);
"Character_Health" NUMBER;
"Enemy_Health" NUMBER;
"Character_Attack" NUMBER;
"Enemy_Attack" NUMBER;
BEGIN -- Generates Base Stats
SELECT 'Hero' INTO "Character" FROM dual;
SELECT 'Villain' INTO "Enemy" FROM dual;
SELECT 100 INTO "Character_Health" FROM dual;
SELECT 25 INTO "Enemy_Health" FROM dual;
SELECT 10 INTO "Character_Attack" FROM dual;
SELECT 5 INTO "Enemy_Attack" FROM dual;
dbms_output.put_line ("Character" || ' (' || "Character_Health" || ') VS ' ||' '|| "Enemy" || ' (' || "Enemy_Health" || ')') ;
dbms_output.put_line ('');
dbms_output.put_line ('FIGHT!');
BEGIN -- Round 1
LOOP
dbms_output.put_line ('');
SELECT "Enemy_Health" - "Character_Attack" INTO "Enemy_Health" FROM dual; -- Hero hits Villain
dbms_output.put_line ("Character" || ' Hits ' || "Enemy" || ' for ' || "Character_Attack" ||' Damage' );
dbms_output.put_line ("Enemy" || ' Has ' || "Enemy_Health" || ' Health Remaining ');
CASE WHEN "Enemy_Health" < 0 THEN dbms_output.put_line ("Enemy" || 'Has Fainted' || "Character" || 'Wins!');
ELSE CONTINUE;
EXIT WHEN "Enemy_Health" < 0;
SELECT "Character_Health" - "Enemy_Attack" INTO "Character_Health" FROM dual; -- Villain hits Hero
dbms_output.put_line ('');
dbms_output.put_line ("Enemy" || ' Hits ' || "Character" || ' for ' || "Enemy_Attack" ||' Damage' );
dbms_output.put_line ("Character" || ' Has ' || "Character_Health" || ' Health Remaining ');
CASE WHEN "Character_Health" < 0 THEN dbms_output.put_line ("Character" || 'Has Fainted' || "Enemy" || 'Wins!');
ELSE CONTINUE;
EXIT WHEN "Character_Health" < 0;
END LOOP;
END;
END;
I found some errors
1. Syntax for case is:
CASE [ expression ]
WHEN condition_1 THEN result_1
WHEN condition_2 THEN result_2
...
WHEN condition_n THEN result_n
[ELSE result]
END CASE
Learn more:
- simple case statement
- searched case statement
CONTINUE stops processing loop and starts it from the begining, so your logic is corrupt - only Hero is attacking.
You need space after "Fainted"
It's better to use IF in this case:
IF "Character_Health" < 0
THEN
dbms_output.put_line ("Character" || 'Has Fainted. ' || "Enemy" || 'Wins!');
EXIT;
END IF;
It's not mistake, but you don't need select into from dual if you want to change value of variable.
Last but not least- i don't like how you use variables. "Character_Health" is similar to 'Character_Health' or '''Character_Health'''. Better use names like characterHealth or character_health.
My version would be something like that:
DECLARE
v_Character VARCHAR2(255) := 'Hero' ;
v_Enemy VARCHAR2(255) := 'Villain';
v_Character_Health NUMBER := 100;
v_Enemy_Health NUMBER := 25;
v_Character_Attack NUMBER := 10;
v_Enemy_Attack NUMBER := 5;
v_nl VARCHAR2(1) := chr(10);
BEGIN
dbms_output.put_line (v_Character || ' (' || v_Character_Health || ') VS ' ||' '|| v_Enemy || ' (' || v_Enemy_Health || ')' || v_nl) ;
dbms_output.put_line ('FIGHT!' || v_nl);
LOOP
v_Enemy_Health := v_Enemy_Health - v_Character_Attack;
dbms_output.put_line (v_Character || ' Hits ' || v_Enemy || ' for ' || v_Character_Attack ||' Damage' );
dbms_output.put_line (v_Enemy || ' Has ' || v_Enemy_Health || ' Health Remaining' || v_nl);
IF v_Enemy_Health < 0 THEN dbms_output.put_line (v_Enemy || 'Has Fainted. ' || v_Character || 'Wins!'); EXIT;
END IF;
v_Character_Health := v_Character_Health - v_Enemy_Attack;
dbms_output.put_line (v_Enemy || ' Hits ' || v_Character || ' for ' || v_Enemy_Attack || ' Damage' );
dbms_output.put_line (v_Character || ' Has ' || v_Character_Health || ' Health Remaining' || v_nl);
IF v_Character_Health < 0 THEN dbms_output.put_line (v_Character || 'Has Fainted. ' || v_Enemy || 'Wins!'); EXIT;
END IF;
END LOOP;
END;
/

PLSQL : Dynamic table record holder

If I want to fetch records from a table (table name is dynamic from input), how to define the record holder or how to fetch the data from this defined table? p_table_name%rowtype will not complie because p_table_name is a parameter, not a table name.
PROCEDURE do_scan(p_table_name IN VARCHAR2
,p_min_num IN NUMBER
,p_time_range IN NUMBER
,p_problem_desc OUT
,p_result_code OUT)
IS
TYPE ObjCurTyp IS REF CURSOR;
v_obj_cursor ObjCurTyp;
v_obj_record ???????(p_table_name%rowtype)
BEGIN
v_stmt_str := 'Select * from :t where date_started > TRUNC(SYSDATE-3)';
OPEN v_obj_cursor FOR v_stmt_str USING p_table_name;
LOOP
FETCH v_obj_cursor INTO v_obj_record;
EXIT WHEN v_obj_cursor %NOTFOUND;
END LOOP;
END do_scan;
You can put that code as a dynamic PL/SQL block within an EXECUTE IMMEDIATE statement.
PROCEDURE do_scan
(
p_table_name IN VARCHAR2
p_min_num IN NUMBER
p_time_range IN NUMBER
p_problem_desc OUT
p_result_code OUT
)
IS
BEGIN
EXECUTE IMMEDIATE
'DECLARE ' ||
' TYPE ObjCurTyp IS REF CURSOR; ' ||
' v_obj_cursor ObjCurTyp; ' ||
' v_obj_record ' || p_table_name || '%rowtype; '||
'BEGIN ' ||
' v_stmt_str := ''Select * from :t where ' ||
' date_started > TRUNC(SYSDATE-3)''; ' ||
' OPEN v_obj_cursor ' ||
' FOR v_stmt_str USING ' ||
p_table_name || '; ' ||
' LOOP ' ||
' FETCH v_obj_cursor INTO v_obj_record; ' ||
' EXIT WHEN v_obj_cursor %NOTFOUND; ' ||
' END LOOP; ' ||
'END;';
END do_scan;
Regards,
Dariyoosh

pl sql and dynamic sql

I am trying to create some dynamic sql using the following code block
firstSqlStatement := true;
updateText := 'UPDATE T_EMPLOYEES SET ';
if FIRSTNAME IS NOT NULL and FIRSTNAME > 0 THEN
updateText:=updateText || ' firstName=' || FIRSTNAME || ' ';
firstSqlStatement := false;
end if;
if MIDDLENAME IS NOT NULL and length(MIDDLENAME) > 0 THEN
if firstSqlStatement = false THEN
updateText:=updateText || ',';
end if;
updateText:=updateText || ' middleName=' || MIDDLENAME || ' ';
firstSqlStatement := false;
end if;
updateText:=updateText
|| ' where upper(id)=upper(' || ID ||');';
DBMS_OUTPUT.put_line(updateText);
EXECUTE IMMEDIATE updateText;
The statement never executes properly as there are missing single quotes around values.
Any ideas what i can do to make this small example work or is there any better way of doing this?
firstSqlStatement := true;
updateText := 'UPDATE T_EMPLOYEES SET ';
if FIRSTNAME IS NOT NULL and FIRSTNAME > 0 THEN
updateText:=updateText || ' firstName=''' || FIRSTNAME || ''' ';
firstSqlStatement := false;
end if;
if MIDDLENAME IS NOT NULL and length(MIDDLENAME) > 0 THEN
if firstSqlStatement = false THEN
updateText:=updateText || ',';
end if;
updateText:=updateText || ' middleName=''' || MIDDLENAME || ''' ';
firstSqlStatement := false;
end if;
updateText:=updateText || ' where upper(id)=upper(' || ID || ');';
DBMS_OUTPUT.put_line(updateText);
EXECUTE IMMEDIATE updateText;
use '''
Maybe you can do it this way.
declare
ll_employee_id number := 10;
lv_firstname varchar2(30) := 'Thomas';
lv_middlename varchar2(30) := null;
begin
update t_employees
set firstname = decode(lv_firstname, null, firstname, lv_firstname),
middlename = decode(lv_middlename, null, middlename, lv_middlename)
where employee_id = ll_employee_id;
end;
DECLARE
my_error exception;
sql_stmt VARCHAR2 (500);
v_char_field VARCHAR2 (500);
v_number_field NUMBER;
v_stmt_number NUMBER;
BEGIN
sql_stmt := 'UPDATE TABLE';
IF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION FIELD
THEN
sql_stmt := sql_stmt || 'field_1 = :1';
v_stmt_number := 1;
ELSIF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION FIELD
THEN
sql_stmt := sql_stmt || 'field_2 = :1';
v_stmt_number := 2;
ELSE
DBMS_OUTPUT.put_line ('Field unmanaged');
RAISE my_error;
END IF;
IF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION TYPE FIELD
THEN
EXECUTE IMMEDIATE sql_stmt USING v_char_field;
ELSIF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION TYPE FIELD
THEN
EXECUTE IMMEDIATE sql_stmt USING v_number_field;
ELSE
DBMS_OUTPUT.put_line ('Type Field unmanaged');
RAISE my_error;
END IF;
DBMS_OUTPUT.PUT_LINE ('STATEMENT NUMBER : ' || v_stmt_number);
DBMS_OUTPUT.PUT_LINE ('TOTAL RECORD UPDATE : ' || SQL%ROWCOUNT);
EXCEPTION
WHEN my_error
THEN
NULL;
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE ('ERROR :' || SQLERRM);
END;
You can use multiple selections to compose your statement for selection fields to be updated and for the type.