Unable to pass schema name in execute immediate - sql

I am trying to pass as a parameter the schema name into an execute immediate command.
DECLARE
sql_stmt VARCHAR2(200);
BEGIN
sql_stmt := 'DROP INDEX :owner.".MY_INDEX"';
EXECUTE IMMEDIATE sql_stmt using &owner_name ;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
The above raises following oracle error:
ORA-06550: line 5, column 38:
PLS-00201: identifier 'USER_X' must be declared
I have tried also tried to concatenate the sql_stmt without success though. I receive the exact same error as above:
DECLARE
sql_stmt VARCHAR2(200);
BEGIN
sql_stmt := 'DROP INDEX ' || &owner. || '".MY_INDEX";';
EXECUTE IMMEDIATE sql_stmt ;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
Any suggestions to pass the username as a variable in the execute statement?

I found that the following works. I was missing a dot '.':
DECLARE
sql_stmt VARCHAR2(200);
BEGIN
sql_stmt := 'DROP INDEX &owner_name.."MY_INDEX"';
EXECUTE IMMEDIATE sql_stmt;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;

A better approach would be assigning values through variables not directly to the execute immediate. If you use variables then this block can be reused for other purposes too. Always try to make blocks in such a way it can be reused. Hope below snippet helps.
SET define ON;
DECLARE
sql_stmt VARCHAR2(200);
lv_chema_nm VARCHAR2(100):='&Enter_schema_name';
lv_obj_type VARCHAR2(100):='&Enter_obj_type';
lv_obj_name VARCHAR2(100):='&Enter_obj_name';
BEGIN
sql_stmt := 'DROP '||lv_obj_type ||' '|| lv_chema_nm||'.'||lv_obj_name;
EXECUTE IMMEDIATE sql_stmt ;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;

Related

How to fix "ORA-00950: invalid DROP option"?

ORA-00950: invalid DROP option
Above is the error that I am getting. I have written this procedure to remove all indexes from the emp_1 table. So can anyone please help me to find out the error and to fix this error?
CREATE OR REPLACE NONEDITIONABLE PROCEDURE sp_drop_indexes (
p_table_name IN VARCHAR2,
p_errormsg OUT VARCHAR2 )
IS
v_sql VARCHAR2(1000);
CURSOR get_indexes IS
SELECT index_name
FROM user_indexes
WHERE table_name = 'EMP_1';
BEGIN
FOR rec IN get_indexes LOOP
v_sql := 'DROP INDEX' || rec.index_name;
EXECUTE IMMEDIATE v_sql;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
p_errormsg := sqlerrm;
END sp_drop_indexes;
You are missing a space after the DROP INDEX (but still inside the quotes) in your code:
v_sql := 'DROP INDEX ' || rec.index_name;
Make sure you include a space after the DROP INDEX keyword:
v_sql := 'DROP INDEX ' || rec.index_name;
You need a space after drop index and, if you can have case-sensitive index names, you need double quotes:
CREATE OR REPLACE NONEDITIONABLE PROCEDURE sp_drop_indexes (
p_table_name IN VARCHAR2,
p_errormsg OUT VARCHAR2 )
IS
v_sql VARCHAR2(1000);
CURSOR get_indexes IS
SELECT index_name
FROM user_indexes
WHERE table_name = 'EMP_1';
BEGIN
FOR rec IN get_indexes LOOP
v_sql := 'DROP INDEX "' || rec.index_name || '"';
EXECUTE IMMEDIATE v_sql;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
p_errormsg := sqlerrm;
END sp_drop_indexes;
/

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"

How to create a procedure in an oracle sql script and use it inside the script?

I want to create a script for my oracle DB, which drops tables. If the table does not exist, the script won't exit as fail, just print a text: "does not exists".
The script is the following:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE mytable';
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
END;
I want to drop a lot of table in one script, and I don't want to write these lines more than once.
Is there any way, to write it to a procedure or function which gets a parameter (the name of the table), and call this procedure in that script?
Maybe something like this:
drop_table_procedure('mytableA');
drop_table_procedure('mytableB');
Or maybe a procedure, which gets an undefined size list (like in java: String ... table names):
drop_tables_procedure('mytableA','mytableB');
Please give me some examples.
Thanks!
Yes, you can declare a "temporary" procedure in an anonymous PL/SQL block:
DECLARE
PROCEDURE drop_if_exists(p_tablename VARCHAR)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE '||p_tablename;
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
END;
BEGIN
drop_if_exists('TABLE_1');
drop_if_exists('TABLE_2');
END;
/
in execute immediate you need add name of database object.
here's the script
create table t1 (col1 int);
create table t2 (col1 int);
create procedure drop_my_table(av_name varchar2)
as
begin
EXECUTE IMMEDIATE 'DROP TABLE '||av_name;
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
end drop_my_table;
declare
type array_t is varray(2) of varchar2(30);
atbls array_t := array_t('t1', 't2');
begin
for i in 1..atbls.count loop
drop_my_table(atbls(i));
end loop;
end;
You can use below one also
create or replace PROCEDURE drop_if_exists(p_tablename in VARCHAR)
IS
v_var1 number;
begin
select 1 into v_var1 from user_tables where table_name=upper(p_tablename);
if v_var1=1
then
EXECUTE IMMEDIATE 'DROP TABLE '||p_tablename;
DBMS_Output.Put_Line(' table dropped');
else
DBMS_Output.Put_Line(' table not exist');
end if;
exception
when others then
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
end;
Call procedure
begin
drop_if_exists('emp');
end;
/

Simple PL/SQL to check if table exists is not working

I'm in the process of converting some stored procedures from Sybase TSQL to Oracle PL/SQL and I've already come across a problem which I'm struggling to resolve!
The below code will not run:
DECLARE
t INT := 0;
t_error EXCEPTION;
v_line VARCHAR2(100);
BEGIN
SELECT COUNT(*) INTO t FROM user_tables WHERE table_name = UPPER('tbl_BSUK_PriceIssue');
IF t = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE tbl_BSUK_PriceIssue';
t := 0;
SELECT COUNT(*) INTO t FROM user_tables WHERE table_name = UPPER('tbl_BSUK_PriceIssue');
IF t = 1 THEN
RAISE t_error;
END IF;
END IF;
EXCEPTION
WHEN t_error THEN
v_line := '<<< FAILED DROPPING table tbl_BSUK_PriceIssue >>>';
dbms_output.put_line (v_line);
WHEN OTHERS THEN
v_line := '<<< Unknown Error >>>';
dbms_output.put_line (v_line);
END;
END;
I get the following error message, what am I doing wrong?!
Error starting at line : 17 in command - DECLARE
t INT := 0; t_error EXCEPTION; v_line VARCHAR2(100);
BEGIN
SELECT COUNT(*) INTO t FROM user_tables WHERE table_name =
UPPER('tbl_BSUK_PriceIssue');
IF t = 1 THEN EXECUTE IMMEDIATE 'DROP TABLE tbl_BSUK_PriceIssue';
t := 0; SELECT COUNT(*) INTO t FROM user_tables WHERE table_name =
UPPER('tbl_BSUK_PriceIssue'); IF t = 1 THEN
RAISE t_error; END IF; END IF;
EXCEPTION WHEN t_error THEN v_line := '<<< FAILED DROPPING table
tbl_BSUK_PriceIssue >>>'; dbms_output.put_line (v_line); WHEN
OTHERS THEN
v_line := '<<< Unknown Error >>>';
dbms_output.put_line (v_line); END;
END; Error report - ORA-06550: line 30, column 1: PLS-00103: Encountered the symbol "END"
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I'm actually trying to replace the following TSQL with a PL/SQL version:
-- Create temp table for relevant trev_id's
IF OBJECT_ID('dbo.tbl_BSUK_PriceIssue') IS NOT NULL
BEGIN
DROP TABLE dbo.tbl_BSUK_PriceIssue
IF OBJECT_ID('dbo.tbl_BSUK_PriceIssue') IS NOT NULL
PRINT '<<< FAILED DROPPING TABLE dbo.tbl_BSUK_PriceIssue >>>'
ELSE
PRINT '<<< DROPPED TABLE dbo.tbl_BSUK_PriceIssue >>>'
END
go
try to remove END; in this section
WHEN OTHERS THEN
v_line := '<<< Unknown Error >>>';
dbms_output.put_line (v_line);
END;
UPD. Actually, you can do it a bit shorter, no need to check if table exists after drop
declare
eTableNotExists exception;
pragma exception_init(eTableNotExists, -00942);
begin
EXECUTE IMMEDIATE 'DROP TABLE tbl_BSUK_PriceIssue';
dbms_output.put_line('<<< DROPPED TABLE dbo.tbl_BSUK_PriceIssue >>>');
exception
when eTableNotExists then null
when others then
dbms_output.put_line ('<<< Unknown Error >>>' || sqlerrm);
end;
/
I don't know about the error, but you can do what you want in a fraction of the code. You don't need the count variable if you use EXISTS() and you don't need EXECUTE IMMEDIATE because you don't have variable data in the command:
IF 1 = (SELECT 1 FROM user_tables WHERE table_name = 'TBL_BSUK_PRICEISSUE') THEN
DROP TABLE tbl_BSUK_PriceIssue;
IF 1 = (SELECT 1 FROM user_tables WHERE table_name = 'TBL_BSUK_PRICEISSUE') THEN
RAISE EXCEPTION;
END IF;
END IF;

cursor giving error

hi we are trying to execute following script we
are getting errors as
ERROR at line 1:
ORA-20000: Unknown Exception Raised: -933 ORA-00933: SQL command not properly
ended
ORA-06512: at line 23
DECLARE
l_cursor INTEGER;
l_output VARCHAR2(20);
l_rows INTEGER;
l_sql VARCHAR2(1000);
BEGIN
l_cursor := DBMS_SQL.OPEN_CURSOR;
l_sql := 'SELECT wk_units1 FROM cnt_sls_dm.fct_sales.summary UNION SELECT wk_units2 FROM cnt_sls_dm.fct_sales.summary';
DBMS_SQL.PARSE(l_cursor, l_sql, DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN_CHAR(l_cursor, 1, l_output, 20);
l_rows := DBMS_SQL.EXECUTE(l_cursor);
loop
if DBMS_SQL.FETCH_ROWS(l_cursor) = 0 then
exit;
end if;
DBMS_SQL.COLUMN_VALUE_CHAR(l_cursor, 1, l_output);
DBMS_OUTPUT.PUT_LINE('Output Text '||l_output);
end loop;
DBMS_SQL.CLOSE_CURSOR(l_cursor);
EXCEPTION
when others then
DBMS_SQL.CLOSE_CURSOR(l_cursor);
raise_application_error(-20000, 'Unknown Exception Raised: '||sqlcode||' '||sqlerrm);
END;
What is this?
cnt_sls_dm.fct_sales.summary
It's not a valid table declaration.
When encountering an error in a dynamic SQL statement, it often helps to output the actual SQL statement and try it in SQLplus.