This is the code I'm using. I'm a newbie to PL/SQL making some modifications to existing pl/sql code.
There is a cursor C_GET_REFERENCED_USER_GROUPS which is storing data from sec_user_group table based on user input which is stored inside variable r_username.
So I'm giving some input which will be taken as the value for variable used inside cursor C_GET_REFERENCED_USER_GROUPS and it has output with few rows. During the execution of the cursor inside a for loop, the for loop is getting completely skipped despite the fact that output is there and I haven't given any lines to exit out of the code.
This is how for loop has been created which loops through the cursor and adds to a table.
FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
LOOP
BEGIN
add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
dbms_output.put_line(add_user_to_group_cmd||';');
execute immediate (add_user_to_group_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);
END;
END LOOP;
COMMIT;
I don't get any errors while I'm executing this code, it's just the the execution finishes after the looping through the execution of for loop which loops through cursor C_GET_ROLE_DETAIL and just skips the above mentioned cursor execution which is executed last.
I had also printed the cursor during the beginning of the execution of PL/SQL block just to verify that the output exists by using simple for loop:
FOR rec IN C_GET_REFERENCED_USER_GROUPS
LOOP
DBMS_OUTPUT.put_line (rec.group_id);
END LOOP;
The above does print couple of rows yet the same rows are not being inserted during the last part of pl/sql insertion.
Please see below for the Full code:
SET lines 200
SET trimspool ON
SET echo OFF
SET verify OFF
--SET serveroutput ON size 1000000
SET serveroutput ON size unlimited
DECLARE
l_cmd VARCHAR2(4000);
l_rmsschema VARCHAR2(5000) := trim('&&rmsschema');
l_username VARCHAR2(5000);
l_password VARCHAR2(5000);
l_name VARCHAR2(5000);
l_email VARCHAR2(5000);
l_user_id VARCHAR2(5000) :=trim('&&userid');
l_pwd VARCHAR2(5000) :=trim('&&password');
l_new_username VARCHAR2(5000) :=trim('&&new_user_name');
l_user_email VARCHAR2(5000) :=trim('&&emailid');
r_username VARCHAR2(5000) :=trim('&&referenced_schema_name');
insert_new_user_cmd VARCHAR2(5000);
add_user_to_group_cmd VARCHAR2(5000);
l_granted_roles VARCHAR2(5000);
l_granted_groups VARCHAR2(5000);
RMS_SCHEMA_ERROR EXCEPTION;
CURSOR C_GET_NEW_USER_DETAIL
IS
select distinct nuc.user_id,nuc.pwd,nuc.user_name,nuc.user_email from PROD.NEW_USER_CREATION nuc
where not exists ( select 1 from dba_users du where du.username=nuc.user_id );
CURSOR C_GET_ROLE_DETAIL
IS
select distinct nuc.user_id,nuc.granted_role from PROD.NEW_USER_CREATION nuc order by 1;
CURSOR C_GET_REFERENCED_USER_ROLES
IS
select GRANTED_ROLE from dba_role_privs where grantee=r_username;
CURSOR C_GET_REFERENCED_USER_GROUPS
IS
select group_id from prod.sec_user_group where user_id=r_username;
BEGIN
----Testing the cursor values by printing it-----
FOR rec IN C_GET_REFERENCED_USER_GROUPS
LOOP
DBMS_OUTPUT.put_line (rec.group_id);
END LOOP;
------Insert into NEW_USER_CREATION_TABLE----------
OPEN C_GET_REFERENCED_USER_ROLES;
dbms_output.put_line('TRUNCATE TABLE PROD.NEW_USER_CREATION');
EXECUTE immediate 'TRUNCATE TABLE PROD.NEW_USER_CREATION';
LOOP
FETCH C_GET_REFERENCED_USER_ROLES into l_granted_roles;
EXIT when C_GET_REFERENCED_USER_ROLES%NOTFOUND;
insert_new_user_cmd := 'insert into PROD.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('''|| l_user_id ||''','''||l_pwd||''','''||l_new_username||''','''||l_user_email||''','''||l_granted_roles||''')';
dbms_output.put_line(insert_new_user_cmd||';');
execute immediate (insert_new_user_cmd);
commit;
END LOOP;
CLOSE C_GET_REFERENCED_USER_ROLES;
-- User Creation-------------------------------------------------------------------------
FOR A_REC IN C_GET_NEW_USER_DETAIL
LOOP
BEGIN
l_username := A_REC.USER_ID;
l_password := A_REC.PWD;
l_name := A_REC.USER_NAME;
l_email := A_REC.USER_EMAIL;
BEGIN
dbms_output.put(CHR(10));
dbms_output.put_line('Creating RMS');
BEGIN
l_cmd := 'CREATE USER "'||l_username||'" identified by "'||l_password||'" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01';
dbms_output.put_line(l_cmd||';');
EXECUTE immediate (l_cmd);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : CREATE USER : '||SQLERRM);
END;
BEGIN
--l_cmd := 'INSERT INTO '||l_rmsschema||'.USER_ATTRIB(USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
l_cmd := 'MERGE INTO '||l_rmsschema||'.USER_ATTRIB TGT';
l_cmd := l_cmd || ' USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM '||l_rmsschema||'.NEW_USER_CREATION WHERE user_id=''' || A_REC.USER_ID || ''') SRC';
l_cmd := l_cmd || ' ON (TGT.USER_ID = SRC.USER_ID )';
l_cmd := l_cmd || ' WHEN NOT MATCHED THEN';
l_cmd := l_cmd || ' INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL)';
l_cmd := l_cmd || ' VALUES ('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
dbms_output.put_line(l_cmd||';');
EXECUTE immediate(l_cmd);
COMMIT;
--CR_SYNONYMS
BEGIN
declare
missing_object varchar2(128);
prefix1 varchar2(128);
prefix2 varchar2(128);
cursor c_get_missing_object is
select object_name
from dba_objects
where owner = upper(l_rmsschema)
and object_type in ('TABLE', 'VIEW', 'CLUSTER', 'FUNCTION', 'PACKAGE', 'PROCEDURE', 'SEQUENCE', 'TYPE')
and object_name not like 'DBC_%'
and object_name not like 'BIN$%'
MINUS
select object_name
from dba_objects
where owner = upper(l_username)
order by 1;
begin
if l_username <> '&_USER' then
prefix1:='"' || l_username || '".';
else
prefix1:='';
end if;
if l_rmsschema <> '&_USER' then
prefix2:='"' || l_rmsschema || '".' ;
else
prefix2:='';
end if;
open c_get_missing_object;
LOOP
fetch c_get_missing_object into missing_object;
--When at end of objects, exit
if c_get_missing_object%NOTFOUND then
exit;
end if;
BEGIN
execute immediate 'CREATE SYNONYM '||prefix1||'"'||missing_object||'" FOR '||prefix2||'"'||missing_object||'"';
dbms_output.put_line('Created synonym '||prefix1||missing_object||' pointing to '||prefix2||missing_object);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Create synonym FAILED '||missing_object||' '||SQLCODE||' - '||SQLERRM);
END;
END LOOP;
close c_get_missing_object;
end;
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR RMS: INSERT USER_ATTRIB: '||SQLERRM);
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
END;
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT ;
END;
END LOOP;
-- RMS Role Assignment-------------------------------------------------------------------------
FOR A_REC IN C_GET_ROLE_DETAIL
LOOP
-- RMS Role Assignment-------------------------------------------------------------------------
begin
l_cmd := 'grant '|| A_REC.GRANTED_ROLE ||' to "'||A_REC.USER_ID||'"';
dbms_output.put_line(l_cmd||';');
execute immediate (l_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : GRANT PRIVILEGES : '||SQLERRM);
end;
end loop;
commit;
EXCEPTION
WHEN utl_file.invalid_path THEN
raise_application_error(-20000, 'Invalid path. Create directory or set UTL_FILE_DIR.');
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
-----Adding user to groups-----------------------------------------------------------------------
FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
LOOP
BEGIN
add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
dbms_output.put_line(add_user_to_group_cmd||';');
execute immediate (add_user_to_group_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);
END;
END LOOP;
COMMIT;
END;
/
I had spooled the output into a log file:Here is part of the log file:
Enter value for rmsschema: prod
Enter value for userid: SCOTT
Enter value for password: scott
Enter value for new_user_name: scott
Enter value for emailid: scott#test
Enter value for referenced_schema_name: 23093
1404
8322//These are the two values that are returned by the cursor and after that should be inserted into the table SEC_USER_GROUP but it's somehow getting skipped.////
TRUNCATE TABLE prod.NEW_USER_CREATION
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('SCOTT','scott','scott','scott#test','TEST_USER_ROLE');
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('SCOTT','scott','scott','scott#test','CUSTOMER_ROLE');
Creating RMS
CREATE USER "SCOTT" identified by "scott" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01;
MERGE INTO prod.USER_ATTRIB TGT USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM prod.NEW_USER_CREATION WHERE user_id='SCOTT') SRC ON (TGT.USER_ID = SRC.USER_ID ) WHEN NOT
MATCHED THEN INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES ('SCOTT','scott','1','scott#test');
//Synonyms for the user created
Created synonym "SCOTT".AA_XX_ITEM pointing to "prod".AA_XX_ITEM
Created synonym "SCOTT".ACC_VALIDATE_API pointing to "prod".ACC_VALIDATE_API
Created synonym "SCOTT".ADDR pointing to "prod".ADDR
Created synonym "SCOTT".ADDRESS_SQL pointing to "prod".ADDRESS_SQL
.................................................................
grant TEST_USER_ROLE to "SCOTT";
grant CUSTOMER_ROLE to "SCOTT";
PL/SQL procedure successfully completed.
As seen above the last part of the code doesn't get executed even though the cursor returns rows.
Related
when i use this code first time ,it create the table but i want to use this code again and again but second time when i use it ,it will drop the table but does not create table again . kindly help me to correct the code according to my requirement.
set serverout on
DECLARE
table_or_view_does_not_exist exception;
pragma exception_init(table_or_view_does_not_exist,-00942);
ddl_qry VARCHAR2 (200);
ddl_table varchar2(200);
r_emp SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
v_array SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('ACCT_ID',
'PARENT_ACCT_ID',
'CUST_ID',
'ACCT_NAME',
'BILLING_CYCLE_TYPE',
'PAID_FLAG',
'BILL_DELIVER_METHOD');
BEGIN
ddl_qry:='Drop Table Accnt_Profile_Spcl';
EXECUTE IMMEDIATE ddl_qry;
exception
when table_or_view_does_not_exist then
dbms_output.put_line('There is no error');
GOTO end_point;
<<end_point>>
ddl_table := 'create table Accnt_Profile_Spcl(
column_name varchar2(50),
spcl_char_count number)';
EXECUTE IMMEDIATE ddl_table;
dbms_output.put_line('Table has been created');
---------DBMS_OUTPUT.ENABLE;
FOR i IN 1..v_array.COUNT LOOP
r_emp.EXTEND;
EXECUTE IMMEDIATE
'SELECT /*+parallel(16)*/ COUNT(*) FROM account_profile WHERE NOT REGEXP_LIKE('||v_array(i)||',''[A-Za-z0-9.]'')'
INTO r_emp(i);
if r_emp(i)<>0 then
-----------dbms_output.put_line(v_array(i) || ': ' || r_emp(i));
execute immediate 'insert into Accnt_Profile_Spcl values (:param1,:param2)' using v_array(i), r_emp(i);
end if;
END LOOP;
END;
That's bad practice. You should really avoid dropping and creating tables that way, that's not how Oracle is supposed to work. Create table once, at SQL level, and reuse it as many times as you want. Just remove its contents, if you want / have to.
Anyway: here's how you could do that:
SQL> declare
2 l_cnt number;
3 begin
4 select count(*) into l_cnt
5 from user_tables
6 where table_name = 'ACCNT_PROFILE_SPCL';
7
8 if l_cnt = 1 then
9 execute immediate 'drop table ACCNT_PROFILE_SPCL';
10
11 dbms_output.put_line('Table dropped');
12 end if;
13
14 execute immediate 'create table ACCNT_PROFILE_SPCL ' ||
15 ' (column_name varchar2(50),' ||
16 ' spcl_char_count number)';
17
18 dbms_output.put_line('Table created');
19 end;
20 /
Table dropped
Table created
PL/SQL procedure successfully completed.
SQL> /
Table dropped
Table created
PL/SQL procedure successfully completed.
SQL>
Use a nested block to handle the exception and not the main block:
DECLARE
ddl_qry VARCHAR2 (200);
ddl_table varchar2(200);
r_emp SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
v_array SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('ACCT_ID',
'PARENT_ACCT_ID',
'CUST_ID',
'ACCT_NAME',
'BILLING_CYCLE_TYPE',
'PAID_FLAG',
'BILL_DELIVER_METHOD');
BEGIN
DECLARE
table_or_view_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_or_view_does_not_exist,-00942);
BEGIN
ddl_qry:='Drop Table Accnt_Profile_Spcl';
EXECUTE IMMEDIATE ddl_qry;
EXCEPTION
WHEN table_or_view_does_not_exist THEN
dbms_output.put_line('There is no error');
END;
ddl_table := 'create table Accnt_Profile_Spcl(
column_name varchar2(50),
spcl_char_count number)';
EXECUTE IMMEDIATE ddl_table;
dbms_output.put_line('Table has been created');
FOR i IN 1..v_array.COUNT LOOP
r_emp.EXTEND;
EXECUTE IMMEDIATE
'SELECT /*+parallel(16)*/ COUNT(*) FROM account_profile WHERE NOT REGEXP_LIKE('||v_array(i)||',''[A-Za-z0-9.]'')'
INTO r_emp(i);
if r_emp(i)<>0 then
execute immediate 'insert into Accnt_Profile_Spcl values (:param1,:param2)' using v_array(i), r_emp(i);
end if;
END LOOP;
END;
/
fiddle
I created table with grants list. How I can execute grants from this table ?
Something like
select * from grants_table;
then EXECUTE IMMEDIATE result from select
You could write a loop
begin
for grant in (select * from grants_table)
loop
execute immediate grants.column_with_ddl;
end loop;
end;
Most likely, you'll want to do some amount of logging/ exception handling/ etc.
If your table is of considerable size you could take advantage of the bulk operations and binds, something among the lines:
DECLARE
TYPE cursor_ref IS REF CURSOR;
c1 cursor_ref;
TYPE grants_t IS TABLE OF grants%ROWTYPE;
grants_tab grants_t;
rows_fetched NUMBER;
errors NUMBER;
dml_errors EXCEPTION;
PRAGMA exception_init(dml_errors, -24345);
BEGIN
OPEN c1 FOR 'SELECT * FROM grants';
FETCH c1 BULK COLLECT INTO grants_tab;
rows_fetched := c1%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Number of grants: ' || TO_CHAR(rows_fetched));
BEGIN
FORALL i IN 1 .. grants_tab.count
EXECUTE IMMEDIATE '< some ddl> :1' USING grants_tab(i);
EXCEPTION WHEN dml_errors THEN
errors := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE('Number of errors is ' || errors);
FOR j IN 1..errors LOOP
DBMS_OUTPUT.PUT_LINE('Error ' || j || ' occurred on iteration ' || SQL%BULK_EXCEPTIONS(j).ERROR_INDEX);
DBMS_OUTPUT.PUT_LINE('Oracle error is ' || SQLERRM(-SQL%BULK_EXCEPTIONS(j).ERROR_CODE));
END LOOP;
END;
END;
/
How to wite EXECUTE IMMEDIATE in the cursor select Query.
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE)
IS
l_cur_query VARCHAR2 (5000) := 'SELECT * from table X where c1='|| in_from_date;
CURSOR cur_attendee_data
IS
EXECUTE IMMEDIATE l_cur_query;
TYPE rec_attendee_data IS TABLE OF cur_attendee_data%ROWTYPE
INDEX BY PLS_INTEGER;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data;
LOOP
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
EXIT WHEN l_cur_attendee_data.COUNT = 0;
DBMS_OUTPUT.put_line ('here in first insert');
lrec := return_attendee_report ();
out_attendee_tab :=
return_attendee_arr_result (return_attendee_report ());
out_attendee_tab.DELETE;
FOR i IN 1 .. l_cur_attendee_data.COUNT
LOOP
BEGIN
NULL;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error occurred : ' || SQLERRM);
END;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('HERE INSIIDE OTHERS' || SQLERRM);
END;
here I try to use initialize cursor outside begin block but it rises exception, how to write a dynamic query for the cursor,
cur_attendee_data is
EXECUTE IMMEDIATE l_cur_query;
Error(113,8): PLS-00103: Encountered the symbol "CUR_ATTENDEE_DATA" when expecting one of the following: := . ( # % ;
If you fetch all rows with BULK COLLECT INTO ... then you need only one loop, the second loop is useless.
The basic solution would be this one:
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE) IS
l_cur_query VARCHAR2 (5000) := 'SELECT * from {table X} where c1=:d';
cur_attendee_data SYS_REFCURSOR;
TYPE rec_attendee_data IS TABLE OF {table X}%ROWTYPE;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data FOR l_cur_query USING in_from_date;
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
FOR i IN 1 .. l_cur_attendee_data.COUNT LOOP
-- do whatever you like to do with l_cur_attendee_data(i)
END LOOP;
CLOSE cur_attendee_data;
END;
However, I don't see any reason to make dynamic SQL. You can simply run
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE) IS
cur_attendee_data SYS_REFCURSOR;
TYPE rec_attendee_data IS TABLE OF {table X}%ROWTYPE;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data FOR SELECT * from {table X} where c1 = in_from_date;
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
FOR i IN 1 .. l_cur_attendee_data.COUNT LOOP
-- do whatever you like to do with l_cur_attendee_data(i)
END LOOP;
CLOSE cur_attendee_data;
END;
You can use below code instead -
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE)
IS
l_cur_query VARCHAR2 (100) := 'SELECT * from table X where c1=:in_from_date';
TYPE t_cur IS REF CURSOR;
cur_attendee_data t_cur
TYPE rec_attendee_data IS TABLE OF cur_attendee_data%ROWTYPE
INDEX BY PLS_INTEGER;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data FOR l_cur_query USING in_from_date;
LOOP
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
EXIT WHEN l_cur_attendee_data.COUNT = 0;
DBMS_OUTPUT.put_line ('here in first insert');
lrec := return_attendee_report ();
out_attendee_tab :=
return_attendee_arr_result (return_attendee_report ());
out_attendee_tab.DELETE;
FOR i IN 1 .. l_cur_attendee_data.COUNT
LOOP
BEGIN
NULL;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error occurred : ' || SQLERRM);
END;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('HERE INSIIDE OTHERS' || SQLERRM);
END;
You need to use open cursor for '' as following:
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE)
IS
l_cur_query VARCHAR2 (5000) := 'SELECT * from table X where c1='|| in_from_date;
cur_attendee_data SYS_REFCURSOR; -- JUST DECLARED THE CURSOR
--TYPE rec_attendee_data IS TABLE OF cur_attendee_data%ROWTYPE
-- INDEX BY PLS_INTEGER; -- this declaration must be at schema level
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data for l_cur_query; -- OPEN THE CURSOR WITH DYNAMIC QUERY
..
.. -- YOUR CODE AS IT IS
..
Cheers!!
I need help in creating this anonymous block into a procedure.
I am new to PLSQL. Any help will be much appreciated. Thank you in advance.
I would like this query to run just by calling a procedure.
TRUNCATE TABLE dblink_status_tbl;
set serveroutput on;
-- or equivalent for your client
declare
-- l_dummy dual.dummy%type;
l_dummy VARCHAR2(20);
l_status VARCHAR2(100);
begin
for r in
(select db_link from all_db_links where db_link in
( 'WP1',
'6P1',
'OP3',
'LP1',
'ODS')
and owner = 'CAMPER')
loop
begin
execute immediate 'select 1 from dual#' || r.db_link into l_dummy;
l_status:= 'ACTIVE';
dbms_output.put_line(r.db_link|| ',' || l_status);
rollback work;
execute immediate 'alter session close database link ' || r.db_link;
exception
when others then
l_status:= sqlerrm;
l_status := replace(replace(l_status,CHR(13), ' '),CHR(10),' ');
l_status := '"' || l_status || '"';
dbms_output.put_line(r.db_link|| ',' || l_status);
end;
insert into dblink_status_tbl
values(r.db_link,l_status);
commit;
end loop;
end;
Basically, you need only the first line in my example:
create or replace procedure p_your_proc as
-- from now on, it is your original code
l_dummy VARCHAR2(20);
l_status VARCHAR2(100);
begin
...
end;
/
Once it is created, run it as
begin
p_your_proc;
end;
/
P.S.
At the beginning, you're truncating a table - if it is necessary within the procedure, you'd use dynamic SQL (as it is a DDL):
begin
execute immediate ('TRUNCATE TABLE dblink_status_tbl');
...
end;
Or, simply delete its contents as
begin
delete from dblink_status_tbl;
...
end;
Make it like something:
create or replace procedure proc_name as
l_dummy VARCHAR2(20);
l_status VARCHAR2(100);
begin
...
Using l_dummy,l_status
end;
And run this like :
"Exec proc_name" or "execute proc_name"
I'm trying to create a procedure that will allow me to write an existing row to another table dynamically but the row declaration and insert-statement in the following snippet don't work. The error message indicates that the view hasn't been identified although outputting the target_table.table_name works just fine.
More will be added to the block later on - such as a column with the operation (e.g. INSERT or UPDATE). This is just a simple example and the last procedure (pass_reference) is used to trigger the procedure.
Any help would be much appreciated.
CREATE OR REPLACE PROCEDURE denormalize (new_cursor sys_refcursor, target_table_name varchar)
IS
target_table user_tables%rowtype;
sql_target_table varchar(200) := 'select * from user_tables where table_name = :target_table_name';
row target_table%rowtype;
BEGIN
execute immediate sql_target_table into target_table using target_table_name;
LOOP
fetch new_cursor into row;
exit when new_cursor%notfound;
insert into target_table values row;
commit;
END LOOP;
END denormalize;
/
CREATE OR REPLACE PROCEDURE pass_reference
AS
new_cursor sys_refcursor;
BEGIN
open new_cursor for select * from sales where sales_id=1;
denormalize(new_cursor, 'NEW_SALES');
END;
/
please check this code, it's not working only as for example, as you see for working columns in your cursor should be named as columns in destination table.
I take this code from package that create html table in mail base on view, hope you found this example useful
good luck
declare
in_view_name varchar2(30);
in_table_name varchar2(30) := 'your_new_table';
out_rc number;
out_rc_txt varchar2(1000);
l_cursor number;
l_sql varchar2(50) := 'select * from ' || in_view_name;
l_col_cnt binary_integer;
l_col_tab dbms_sql.desc_tab;
l_column_value varchar2(4000);
l_is_empty boolean := true;
l_insert_header varchar2(1000);
l_insert varchar2(32000);
begin
out_rc := 0;
out_rc_txt := 'OK';
l_cursor := dbms_sql.open_cursor;
dbms_sql.parse(l_cursor, l_sql, dbms_sql.native);
l_col_cnt := dbms_sql.execute(l_cursor);
dbms_sql.describe_columns(l_cursor, l_col_cnt, l_col_tab);
l_insert_header := 'insert into '||in_table_name||'(';
if l_col_cnt > 0 then
-- header
for i in l_col_tab.first .. l_col_tab.last loop
dbms_lob.append(l_insert_header, l_col_tab(i).col_name);
if i != l_col_tab.last then
dbms_lob.append(l_insert_header, ',');
end if;
dbms_sql.define_column(l_cursor, i, l_column_value, 4000);
end loop;
l_insert_header := l_insert_header || ') values(';
-- data
while dbms_sql.fetch_rows(l_cursor) > 0 loop
l_is_empty := false;
l_insert := l_insert_header;
for i in l_col_tab.first .. l_col_tab.last loop
dbms_sql.column_value(l_cursor, i, l_column_value);
l_insert := l_insert || '''' || l_column_value || ''','
if not in_attachment then
dbms_lob.append(out_table, l_td);
end if;
if (not in_attachment) or (l_column_value is not null) then
dbms_lob.append(out_table, nvl(l_column_value, l_nbsp));
end if;
if (not in_attachment) or (i != l_col_tab.last) then
dbms_lob.append(out_table, l_tdc);
end if;
end loop;
l_insert := substr(l_insert, 1, length(l_insert) - 1) || ')';
execute immediate l_insert;
end loop;
end if;
dbms_sql.close_cursor(l_cursor);
end;