PL/SQL error : identifier 'NAME' must be declared - sql

I have to call a procedure from a package p_name but it gives error as identifier 'NAME' must be declared
DECLARE
V V_NAME;
V1 VARCHAR2(30);
v_sql VARCHAR2(4000);
BEGIN
SELECT PROCEDURE_NAME BULK COLLECT INTO V from ALL_PROCEDURES
where OBJECT_NAME='p_name';
FOR I IN 1..V.COUNT LOOP
name:='p_name';
v_sql:='begin'||name||'.'||V(I)||';'||'END;';
EXECUTE IMMEDIATE v_sql;
END LOOP;
END;

If this is the only problem, it should be ok like so:
DECLARE
V V_NAME;
V1 VARCHAR2(30);
NAME VARCHAR2(7);
v_sql VARCHAR2(4000);
BEGIN
SELECT PROCEDURE_NAME BULK COLLECT INTO V from ALL_PROCEDURES where
lower(OBJECT_NAME)='p_name';
FOR I IN 1..V.COUNT LOOP
name:=' p_name';
v_sql:='begin'||name||'.'||V(I)||';'||'END;';
EXECUTE IMMEDIATE v_sql;
END LOOP;
END;

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

How to write Execute immediate in cursor select Query

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!!

How to convert to procedure

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"

plsql - dynamically change table name in cursor

i'm getting below error while running the procedure. is the select correct.. trying to pass table name as parameter. Pls help.
PLS-00364: loop index variable 'CURSOR1' use is invalid
PROCEDURE generate_uniqueId(p_table_name IN VARCHAR2) is
--
--
CURSOR unique_id_cur
IS
SELECT /*PARALLEL(20)*/ unique_id
FROM p_table_name;
--
v_file UTL_FILE.file_type;
V_file_name Varchar2 (150);
V_file_parm Varchar2:= ora11g/test/;
v_output varchar2(200);
BEGIN
v_file_name := p_table_name || '.lst';
v_file := UTL_FILE.fopen ('ora11g/test/', 'unique_ID_file', 'A');
FOR cursor1 IN unique_id_cur
LOOP
BEGIN
v_output := cursor1.unique_id;
UTL_FILE.put_line (v_file, v_output);
END;
END LOOP;
UTL_FILE.fflush (v_file);
UTL_FILE.fclose (v_file);
END generate_uniqueId ;
Your PL/SQL code having many syntax issue.
You can pass the table name in cursor declaration in form of "from p_table_name".
CURSOR unique_id_cur
IS
SELECT /*PARALLEL(20)*/ unique_id
FROM p_table_name;
If you are using "VARCHAR2" data type then you have to provide the length of data should contain a variable. Also the string "ora11g/test/" should kept in single quota -'- as 'ora11g/test/'
V_file_parm Varchar2:= ora11g/test/;
The directory that you are passing, am not sure whether it is going to accept or not. But, should create a logical directly in Oracle using "CREATE DIRECTORY" and then pass the newly directory created in "UTL_FILE.FOPEN".
Here is the sample idea to create a procedure that will compile and work for you, create or real procedure like below.
create or replace PROCEDURE generate_uniqueId(p_table_name IN VARCHAR2 default 'abc')
as
CURSOR unique_id_cur
IS
SELECT object_id as unique_id
FROM all_tables
where rownum <=5;
v_file UTL_FILE.file_type;
V_file_name Varchar2(150);
V_file_parm Varchar2(200) := 'ora11g/test/';
v_output varchar2(200);
BEGIN
v_file_name := p_table_name || '.lst';
v_file := UTL_FILE.fopen ('ora11g/test/', 'unique_ID_file', 'A');
FOR cursor1 IN unique_id_cur
LOOP
BEGIN
v_output := cursor1.unique_id;
UTL_FILE.put_line (v_file, v_output);
END;
END LOOP;
UTL_FILE.fflush (v_file);
UTL_FILE.fclose (v_file);
END generate_uniqueId ;
EDIT-1
create or replace PROCEDURE generate_uniqueId(p_table_name IN VARCHAR2 default 'abc')
as
type t1 is table of varchar2(255) index by pls_integer;
v_unique_ids t1;
v_sql varchar2(4000);
v_file UTL_FILE.file_type;
V_file_name Varchar2(150);
V_file_parm Varchar2(200) := 'ora11g/test/';
v_output varchar2(200);
BEGIN
v_file_name := p_table_name || '.lst';
v_file := UTL_FILE.fopen ('ora11g/test/', 'unique_ID_file', 'A');
v_sql := 'select /* PARALLEL(20) */ unique_id from '|| p_table_name;
execute immediate v_sql bulk collect into v_unique_ids;
FOR cursor1 IN v_unique_ids.first..v_unique_ids.last
LOOP
BEGIN
v_output := v_unique_ids(cursor1);
UTL_FILE.put_line (v_file, v_output);
END;
END LOOP;
UTL_FILE.fflush (v_file);
UTL_FILE.fclose (v_file);
END generate_uniqueId ;

Execute immediate dbms_output.put_line

I have code like this:
set serveroutput on
declare
v_str varchar2(200);
begin
v_str := q'!dbms_output.put_line('Hello world');!';
Execute immediate v_str;
end;
Oracle SQL Developer says that there's invalid SQL Statement, what's the problem?
declare
v_str varchar2(200);
begin
v_str := q'!begin dbms_output.put_line('Hello world'); end;!';
Execute immediate v_str;
end;
/
works...