How to convert to procedure - sql

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"

Related

How to drop and create table again and again

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 want to create a table and insert a row in same table during run time using dynamic sql

I have created a procedure that accepts table name, 2 column names and 2 values that needed to be inserted on create table.
create or replace procedure SP_TABLE(P_TAB IN VARCHAR2,P_COL_1 IN VARCHAR2,P_COL_2 VARCHAR2,P_ID IN NUMBER,P_NAME IN VARCHAR2)
AS
v_sql varchar2(2000);
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE '||P_TAB||' ('||P_COL_1||' NUMBER, '||P_COL_2 ||' VARCHAR2(20))';
v_sql := 'insert into ' ||P_TAB||'values (:1,:2)';
EXECUTE IMMEDIATE v_sql USING P_ID,P_NAME;
END;
/
The procedure was successfully created without any errors. However when i ran the below script i got error like 'ORA-00928: missing SELECT keyword
ORA-06512: at "SQL_PXADYXDREZPVPJSALLEGOZJOB.SP_TABLE", line 7'.
DECLARE
V_TAB VARCHAR2(20) := 'TABLE1';
V_COL1 VARCHAR2(20) := 'ID';
V_COL2 VARCHAR2(20) := 'NAME';
V_ID NUMBER := 1;
V_NAME VARCHAR2(20):= 'RAJA';
BEGIN
SP_TABLE(V_TAB,V_COL1,V_COL2,V_ID,V_NAME);
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);
END;
/
some one help me with this.
You can add space before values
create or replace procedure SP_TABLE(P_TAB IN VARCHAR2,P_COL_1 IN VARCHAR2,P_COL_2 VARCHAR2,P_ID IN NUMBER,P_NAME IN VARCHAR2)
AS
v_sql varchar2(2000);
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE '||P_TAB||' ('||P_COL_1||' NUMBER, '||P_COL_2 ||' VARCHAR2(20))';
v_sql := 'insert into ' ||P_TAB||' values (:1,:2)';
EXECUTE IMMEDIATE v_sql USING P_ID,P_NAME;
END;
/

parameter i PL/SQL procedure

I am trying to execute a PL/SQL procedure without success.
It shows me "inexistent table". What can I do?
CREATE OR REPLACE PROCEDURE INTEGRATION(tableName varchar2) IS
BEGIN
MERGE INTO tableName alert
USING ...
you can try with execute immediate statement and concatenate the tablename passed from procedure
see example from oracle site
CREATE OR REPLACE PROCEDURE delete_rows (
table_name IN VARCHAR2,
condition IN VARCHAR2 DEFAULT NULL) AS
where_clause VARCHAR2(100) := ' WHERE ' || condition;
v_table VARCHAR2(30);
BEGIN
-- first make sure that the table actually exists; if not, raise an exception
SELECT OBJECT_NAME INTO v_table FROM USER_OBJECTS
WHERE OBJECT_NAME = UPPER(table_name) AND OBJECT_TYPE = 'TABLE';
IF condition IS NULL THEN where_clause := NULL; END IF;
EXECUTE IMMEDIATE 'DELETE FROM ' || v_table || where_clause;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Invalid table: ' || table_name);
END;
/
BEGIN
delete_rows('employees_temp', 'employee_id = 111');
END;
/
for other info see oracle site
execute immediate

EXECUTE IMMEDIATE PL/SQL Block return type

As part of a test I want to run a PL/SQL block using EXECUTE IMMEDIATE but when I try to fetch the result with INTO it always returns the same error regardless the content of the PL/SQL block I want to run.
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN COMMIT; END;' INTO l_output;
END;
/
And the error is
ORA-01007: variable not in select list
I know this error has to with l_output not being the same type as the returning type by EXECUTE IMMEDIATE, but I don't know the type. I already tried to change l_output to CLOB, BLOB, NUMBER and nothing changes. Any idea?
OK, this is another example, same result.
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN DBMS_OUTPUT.PUT_LINE(''TEST''); END;' INTO l_output;
END;
/
Oracle is complaining because your PL/SQL does not return anything for it to store in l_output. What are you expecting the value of l_output to be?
One would use EXECUTE IMMEDIATE...INTO with something like this to return a value from a PL/SQL block.
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'SELECT ''ABC'' FROM DUAL' INTO l_output;
dbms_output.put_line('l_output = ' || l_output);
END;
/
UPDATE
If you want, you can do this:
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN :1 := 5; END;' USING IN OUT l_output;
dbms_output.put_line('l_output = ' || l_output);
END;

Dynamic SQL LOOP

Dynamic SQL is not my friend, basically the idea is that I can use the procedure with the "p_in_table" paramter to get the number of rows contained in the table.
CREATE OR REPLACE PROCEDURE how_many_rows(p_in_table VARCHAR2)
IS
TYPE cur_cur IS REF CURSOR;
v_cur_cur cur_cur;
v_rowcount NUMBER(28);
v_cur_txt VARCHAR2(299);
BEGIN
v_cur_txt := 'SELECT * FROM ' || p_in_table;
OPEN v_cur_cur FOR v_cur_txt;
LOOP
v_rowcount := v_cur_cur%ROWCOUNT;
EXIT WHEN v_cur_cur%NOTFOUND;
END LOOP;
CLOSE v_cur_cur;
dbms_output.put_line(v_rowcount);
END;
Would preciate it if someone would tell me what am I doing wrong?
The problem is that you not iterating through cursor - no fetch statement or something like that, so, basically, you have an infinite loop. To avoid this you need to do something like this:
CREATE OR REPLACE PROCEDURE how_many_rows
(p_in_table VARCHAR2) IS
TYPE cur_cur IS REF CURSOR;
v_cur_cur cur_cur;
v_rowcount NUMBER(28);
v_cur_txt VARCHAR2(299);
v_row SOME_TABLE%ROWTYPE; --add row variable
BEGIN
v_cur_txt := 'SELECT * FROM '|| p_in_table;
OPEN v_cur_cur FOR v_cur_txt;
LOOP
v_rowcount := v_cur_cur%ROWCOUNT;
FETCH v_cur_cur INTO v_row; --fetch a row in it
EXIT WHEN v_cur_cur%NOTFOUND;
END LOOP;
CLOSE v_cur_cur;
DBMS_OUTPUT.PUT_LINE(v_rowcount);
END;
But, as you can see, to do this you need to know, what table you're quering, so this is not general solution. Maybe there is a workaround for this, but i suggest, you use more simple and efficient approach, for example with EXECUTE IMMEDIATE:
CREATE OR REPLACE PROCEDURE HOW_MANY_ROWS(p_in_table VARCHAR2)
IS
v_tmp NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM ' || p_in_table INTO v_tmp;
DBMS_OUTPUT.PUT_LINE(v_tmp);
END;
Ok, I gave a thought on how to achieve this using your way, and here is what i've ended up with - just fetch ROWNUM from your table, every table has it and you know it's type - NUMBER. So this procedure will work in general case:
CREATE OR REPLACE PROCEDURE how_many_rows
(p_in_table VARCHAR2) IS
TYPE cur_cur IS REF CURSOR;
v_cur_cur cur_cur;
v_rowcount NUMBER(28);
v_cur_txt VARCHAR2(299);
v_row NUMBER; --add rownum variable
BEGIN
v_cur_txt := 'SELECT ROWNUM FROM '|| p_in_table; --select only rownum from target table
OPEN v_cur_cur FOR v_cur_txt;
LOOP
v_rowcount := v_cur_cur%ROWCOUNT;
FETCH v_cur_cur INTO v_row; --fetch rownum in it
EXIT WHEN v_cur_cur%NOTFOUND;
END LOOP;
CLOSE v_cur_cur;
DBMS_OUTPUT.PUT_LINE(v_rowcount);
END;