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.
Related
I have a procedure, which returns num_array data type which is a specially created number data type. Procedures Spec:
PROCEDURE GET_STATUS_LIST (P_MODUL_ID IN NUMBER,
P_DOCUMENT_ID IN NUMBER,
P_USER_ID IN NUMBER,
P_STATUS_LIST OUT NUM_ARRAY);
So, I want to see what is the end result of my procedure.
I have tried either dbms_output, or select, or return sys_refcursor
DECLARE
alma num_array;
armud SYS_REFCURSOR;
BEGIN
schema.pk_common_confirmation.get_status_list (816,
17025214,
263,
alma);
OPEN armud FOR SELECT * FROM TABLE (alma);
--return armud;
FOR t IN armud
LOOP
DBMS_OUTPUT.put_line (t);
END LOOP;
END;
Error message PLS-00221: 'armud' is not a procedure or is undefined
DECLARE
alma num_array;
armud SYS_REFCURSOR;
BEGIN
FOR t IN schema.pk_common_confirmation.get_status_list (816,
17025214,
263,
alma)
LOOP
DBMS_OUTPUT.put_line (t);
END LOOP;
END;
Error message PLS-00456: item 'get_status_list ' is not a cursor
DECLARE
alma num_array;
BEGIN
SELECT schema.pk_common_confirmation.get_status_list (816,
17025214,
263,
alma)
FROM DUAL;
END;
Error message ORA-00904: invalid identifier
DECLARE
alma num_array;
armud SYS_REFCURSOR;
BEGIN
turanbank.pk_common_confirmation.get_status_list (816,
17025214,
263,
alma);
FOR t IN (SELECT * FROM TABLE (alma))
LOOP
DBMS_OUTPUT.put_line (t);
END LOOP;
END;
Error message PLS-00306: wrong number or types of arguments in call to
'PUT_LINE'
Are there other ways I can output or see or select procedure results?
I don't know how to resolve these errors.
Any help would be appreciated
I have found one way of returning procedure results for this data type. I thought, if it's num_array as there's an array in its name, I can get the result by index.
DECLARE
alma num_array;
armud SYS_REFCURSOR;
BEGIN
schema.pk_common_confirmation.get_status_list (816,
17025214,
263,
alma);
FOR t IN 1..alma.count
LOOP
DBMS_OUTPUT.put_line (alma(t));
END LOOP;
END;
DBMS_OUTPUT :
1441
1442
1701
1741
1801
2582
But still, I would like to know any other ways of doing it, so if there is any suggestions, please do tell
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;
I have below procedure where i am trying to track the exceptions into I_Log table.To test whether its working or not I have made a ORA-00933: SQL command not properly ended error in my query where I am trying to insert into I_OPTION table. When i run this procedure the dbms output line is printing the error below but its not getting inserted into I_Log table:
OTHERS exception in EXT_I_OPTION - ID:1000196-933----ORA-00933: SQL command not properly ended
Below is my procedure:
CREATE OR REPLACE PROCEDURE
"EXT_I_OPTION"(in_id IN NUMBER DEFAULT 0)
AS
err_code VARCHAR(100);
err_msg VARCHAR(100);
in_event_id NUMBER;
in_db_link VARCHAR2(50);
in_env_id NUMBER;
l_sql VARCHAR2(5000);
l_sql1 VARCHAR2(5000);
BEGIN
FOR I_row IN I_cur
LOOP
l_sql2 := INSERT INTO I_OPTION(ID)
select DISTINCT(SO.ID)
)
from Icard I;
END LOOP;
EXCEPTION WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
INSERT INTO I_log (I_ID)
VALUES (i_id);
RAISE;
COMMIT;
END ext_I_option;
It seems that you have a RAISE before COMMIT; this way, the error will be raised before doing COMMIT, so you don't find data in your log table.
According to suggestions, you should define a procedure to handle your log table:
CREATE OR REPLACE procedure i_LOG (...) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
Insert into I_LOG(...);
COMMIT;
END;
/
This procedure runs in a separate transaction, so it only does commit of log data, with no conflict with data you modify in your main procedure.
Then you should modify your error handling in this way, avoiding COMMIT statement, that can be really dangerous, saving partial, unconsistent data:
DBMS_OUTPUT.PUT_LINE('OTHERS exception in EXT_I_OPTION - ID:'||to_char(ID) || err_code || '----' || err_msg );
ins_I_LOG(...);
RAISE;
I have the below PL SQL Block:
WHENEVER SQLERROR EXIT 1
SET SERVEROUTPUT ON
DECLARE
v_sql VARCHAR2(500);
f1 VARCHAR2(20) := 'abc';
p_procname VARCHAR2 (30) := 'OPENLOG';
PROCEDURE OPENLOG (file_name IN VARCHAR2)
IS
BEGIN
NULL;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Begin');
v_sql := 'BEGIN ' || p_procname || '(:a); END;';
EXECUTE IMMEDIATE v_sql USING IN f1;
END;
/
When I execute the above block, I get the error:
DECLARE
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'OPENLOG' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
ORA-06512: at line 19
However, if the procedure OPENLOG is part of a package, then it works fine.
Please advise how to execute a local procedure using dynamic SQL.
As Amarillo said you can't execute a locally-defined procedure dynamically, as it doesn't exist in the SQL scope the dynamic section will be using.
The situation you describe is that all the procedures are defined in the anonymous block's DECLARE section and you are running a query that tells you which of them to execute - and presumably which also gives you the arguments to pass. You can just use an if/else construct or a case statement to execute the appropriate procedures, something like:
DECLARE
...
BEGIN
FOR data IN (SELECT procname, arg1, arg2, ... from <your_query>) LOOP
CASE data.procname
WHEN 'OPENLOG' THEN
openlog(data.arg1);
WHEN 'WRITELOG' THEN
writelog(data.arg1, data.arg2);
WHEN ...
...
ELSE
-- handle/report an invalid procedure name
-- or skip the `ELSE` and let CASE_NOT_FOUND be thrown
END CASE;
END LOOP;
END;
/
You just need one WHEN condition and appropriate procedure call for each procedure. You can also either have an ELSE to catch any unexpected procedure names or let the CASE_NOT_FOUND exception (ORA-06592) be thrown, depending on what you need to happen if that ever occurs.
Use it like this:
DECLARE
v_sql VARCHAR2(500);
f1 VARCHAR2(20) := 'abc';
p_procname VARCHAR2 (30) := 'OPENLOG';
PROCEDURE OPENLOG (file_name IN VARCHAR2)
IS
BEGIN
NULL;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Begin');
openlog(f1);
END;
You don't need to use execute immediate with begin end in this case, because you have the procedure in the declare section.
The other way is create the procedure as a database object like this:
CREATE PROCEDURE OPENLOG (file_name IN VARCHAR2)
IS
BEGIN
NULL;
END;
And the you can use execute immediate:
DECLARE
v_sql VARCHAR2(500);
f1 VARCHAR2(20) := 'abc';
p_procname VARCHAR2 (30) := 'OPENLOG';
BEGIN
DBMS_OUTPUT.PUT_LINE('Begin');
v_sql := 'BEGIN ' || p_procname || '(:a); END;';
EXECUTE IMMEDIATE v_sql USING IN f1;
END;
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;