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...
Related
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 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 ;
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;
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;
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;