ORA-00933 runtime plsql throwing the error - plsql

I am trying to query the dba_tables, if table "SPLIT_EXT_INFO" not present i am getting correct output, if table "SPLIT_EXT_INFO" exist i am getting below error,
SET serveroutput ON
DECLARE
t_cnt NUMBER;
v_schema_name VARCHAR2(40) := 'DBA';
v_table_name VARCHAR2(40) := 'SPLIT_EXT_INFO';
refcur SYS_REFCURSOR;
split_mapper VARCHAR2(40);
info_tab VARCHAR2(40);
tracker VARCHAR2(40);
BEGIN
SELECT Count(1)
INTO t_cnt
FROM dba_tables
WHERE owner = v_schema_name
AND table_name = v_table_name;
dbms_output.Put_line(t_cnt);
IF t_cnt = 0 THEN
dbms_output.Put_line('NO_SPLIT_TAB');
ELSE
OPEN refcur FOR 'SELECT split_mapper, info_tab, tracker FROM '
||v_schema_name
||'.'
||v_table_name
|| 'where nodename = ''host1.world.com''';
LOOP
FETCH refcur INTO split_mapper,info_tab,tracker;
EXIT WHEN refcur%NOTFOUND;
dbms_output.Put_line(split_mapper
||':'
||info_tab
||':'
||tracker);
END LOOP;
IF refcur%rowcount = 0 THEN
dbms_output.Put_line('NO_SPLIT_ENTRY');
END IF;
END IF;
CLOSE refcur;
END;
/
Error:
1
DECLARE
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
ORA-06512: at line 21
can someone add help in this, thanks !
Regards
Kannan

The apostrophe symbol is on a wrong place before WHERE clause is being concatenated
your code: || 'where nodename = ''host1.world.com''';
right is : ||' where nodename = ''host1.world.com''';
In your version the sql will look like
select ... FROM tableWHERE nomename = ...
The missing space symbol between table name and WHERE causing this problem

Related

Returning table results from a dynamic PL/SQL query

Trying to dynamically generate and execute a PL/SQL statement. It doesn't return results, but executing okay. What I am trying is to get the table name from the schema in first statement (got it right!), and append that to a select statement, and then execute it to return the table results.
DECLARE
LATEST_TABLE VARCHAR2(256);
PostalCode ADM.POSTAL_CODE_201801%ROWTYPE;
BEGIN
SELECT TO_CHAR(max(table_name)) INTO LATEST_TABLE FROM all_tables WHERE owner = 'ADM' AND table_name LIKE 'POSTAL_CODE_%';
LATEST_TABLE := 'begin Select POSTALCODE,LONGITUDE,LATITUDE,MUNICIPALITY_FULL_NAME,LOCAL_NAME,SZONE_NAME,ZONE_NAME,RHA_CODE,RHA_NAME,URBAN,ZONE_RURAL from ADM.'||LATEST_TABLE||' ;end;';
execute immediate LATEST_TABLE into PostalCode;
Exception
When others then
Null;
END;
Why am I not getting any results? Adding
dbms_output.put_line(PostalCode.LONGITUDE || PostalCode.LATITUDE); after execute immediate is also not generating results!
I see a couple of issues here; your code is something like:
declare
vSQL varchar2(1000);
vTabName varchar2(30);
vResult number;
begin
select table_name into vTabName from user_tables;
vSQL := 'begin select a from ' || vTabName || '; end;';
execute immediate vSQL into vResult;
dbms_output.put_line('REsult: ' || vResult);
exception
when others then
null
end;
If you run this, you see nothing, because the dynamic part gives error, but the (dangerous) exception handling hides it; if you would edit the null; into something like
dbms_output.put_line('Error: ' || sqlerrm);
you would get:
Error: ORA-06550: line 1, column 7:
PLS-00428: an INTO clause is expected in this SELECT statement
In fact you dynamic code is like
begin select a from someTable; end;
and this gives error.
A way to do what you need could be:
...
vSQL := 'select a from ' || vTabName;
execute immediate vSQL into vResult;
...

ORA-00904 - "NORM": invalid identifier - string in dynamic sql

Im trying to execute below section of code but get an ORA-00904 error.
Declare
i_status varchar2(4) := 'NORM';
vsql varchar2(4000);
...
...
Begin
...
...<Part of larger dynamic sql>
If i_status is not null Then
vSql := vSql || ' And account.astatus = ' ||i_status|| '';
End if;
execute immediate (vSql) into tmp,ssn;
<Do something with tmp, ssn>
End;
An exception is raised at line "execute immediate" with error
ORA-00904 - "NORM": invalid identifier
column account.astatus has type char(4 byte)
I assume the problem is that I am trying to pass string variable NORM in the where clause without adding quotes ' '. How do get around this issue?
Thanks.
You can easily dig into your code and check where the issue exist by printing your VSQL before executing it.
Declare
i_status varchar2(10) := 'NORM';
vsql varchar2(4000):= 'Select * from dual where 1=3';
Begin
If i_status is not null Then
vSql := vSql || ' And account.astatus = ' ||i_status|| '';
End if;
dbms_output.put_line(vSql);
--execute immediate (vSql) into tmp,ssn;
End;
When you run this block you can see the statement that is getting generated which shows :
Select * from dual where 1=3 And account.astatus = NORM
Now you can easily note that your account.astatus = NORM is not correct so you can replace it with:
i_status varchar2(10) := '''NORM''';
or using q quotes:
i_status varchar2(10) := q'['NORM']';
Nevertheless what Boneist mentioned is the best practice which avoids sql injection.
The simple answer is to use bind variables, meaning you avoid the whole thorny issue of sql injection that you open yourself up to when you hardcode your variables into the dynamic sql. You also save yourself the faff of having to work out how to include the single-quotes to go around the string that your dynamic sql is currently missing.
Using bind variables, your code becomes:
Declare
i_status varchar2(4) := 'NORM';
vsql varchar2(4000);
...
...
Begin
...
...<Part of larger dynamic sql>
If i_status is not null Then
vSql := vSql || ' And account.astatus = :i_status';
End if;
execute immediate (vSql) into tmp,ssn using i_status;
<Do something with tmp, ssn>
End;

ORA-00972: identifier is too long ORA-06512

i have a PROCEDURE like this, whenever i execute the procedure it will give result in cursor according select type:
create or replace PROCEDURE EMAT_PROC_DROPDOWN_SELECTALL(SELECT_TYPE IN VARCHAR2, RESULT_SET OUT SYS_REFCURSOR)
AS
SELECT_TYPE_IN VARCHAR2(100);
TABLE_NAME VARCHAR2(100);
FIELD_NAME VARCHAR2(100);
C_ZONE SYS_REFCURSOR;
C_USER_ID SYS_REFCURSOR;
BEGIN
SELECT_TYPE_IN:=SELECT_TYPE;
IF(SELECT_TYPE_IN ='ZONE') THEN
BEGIN
TABLE_NAME:='MM_ZONEMASTER';
FIELD_NAME:='ZONE_NAME';
OPEN C_ZONE FOR
'SELECT DISTINCT' ||FIELD_NAME|| 'FROM' ||TABLE_NAME||';';
LOOP
FETCH C_ZONE INTO RESULT_SET;
EXIT WHEN C_ZONE%NOTFOUND;
END LOOP;
CLOSE C_ZONE;
END;
ELSIF(SELECT_TYPE_IN ='USER') THEN
BEGIN
TABLE_NAME:='AD_USERMASTER';
FIELD_NAME:='USER_ID';
OPEN C_USER_ID FOR
'SELECT DISTINCT' ||FIELD_NAME|| 'FROM' ||TABLE_NAME||';';
LOOP
FETCH C_USER_ID INTO RESULT_SET;
EXIT WHEN C_USER_ID%NOTFOUND;
END LOOP;
CLOSE C_ZONE;
END;
END IF;
END;
but the returns the error ***ORA-00972: identifier is too long
ORA-06512: at "EMAT.EMAT_PROC_DROPDOWN_SELECTALL", line 14
ORA-06512: at line 7
This is the issue: 'SELECT DISTINCT' ||FIELD_NAME|| 'FROM' ||TABLE_NAME||';';
It will see it as SELECT DISTINCTZONE_NAMEFROMMM_ZONEMASTER
The same goes for the other one.
Add spaces and write it as SELECT DISTINCT ' ||FIELD_NAME|| ' FROM ' ||TABLE_NAME||';';
There are missing space in the cursor around the field name and the table name. It reads SELECT DISTINCTZONE_NAMEFROMMM_ZONEMASTER; instead of SELECT DISTINCT ZONE_NAME FROM MM_ZONEMASTER;
Replace that line by this should help :
'SELECT DISTINCT ' ||FIELD_NAME|| ' FROM ' ||TABLE_NAME||';';
Additionally be careful with the use of nested blocks in your IF. I would avoid abusing from it if it's not needed.

Compilation error with plsql procedure

Below is a plsql procedure which was written by someone else and I have asked to fix its compilation errors and run it right.
PROCEDURE DropMyTable IS
x number;
TYPE cur_typ IS REF CURSOR;
--type NAME_TBL is table of VARCHAR2(30);
--tab_Table NAME_TBL;
tab_Table VARCHAR2S(30);
stmt VARCHAR2(4096);
stmt2 VARCHAR2(4096);
outerCur cur_typ;
rows NATURAL := 1000;
TABLE_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942);
BEGIN
stmt2 := 'select distinct G_Tab from G_SERVE where G_TYPE=''CAP''';
--Begin
OPEN outerCur FOR stmt2;
LOOP
FETCH outerCur BULK COLLECT INTO
tab_Table LIMIT rows;
EXIT WHEN tab_Table.COUNT = 0;
FOR i IN 1..tab_Table.COUNT LOOP
--------------------------------------------------------------------
-- Drop the tables in G_SERVE.G_TAB
DBMS_OUTPUT.PUT_LINE('*** Drop table: ' || tab_Table(i) || ' ***');
-- BEGIN
--First drop the optable
stmt := 'DROP TABLE ' || tab_Table(i) || '_OPTAB CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the base table
stmt := 'DROP TABLE ' || tab_Table(i) || ' CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the Package
stmt := 'DROP PACKAGE ' || tab_Table(i) || '_PKG';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
EXCEPTION
-- When the table, optab and package doesn't exist,
-- ignore error "ORA-00942: table, optab or package does not exist".
WHEN TABLE_DOES_NOT_EXIST THEN
DBMS_OUTPUT.PUT_LINE('table, optab or package does not exist');
DBMS_OUTPUT.PUT_LINE(CHR(9));
--Re-raises any other errors.
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error!');
RAISE;
END;
END LOOP;
END LOOP;
--END;
END DropMyTable;
First up I have commented out 4th and 5th line of code from begging and changed it to what it looks like now ( 6th line from the top).
Other thing I have commented out 2 BEGIN keywords first commented out "BEGIN" can be seen after
stmt2 := 'select distinct gao_table from GAO_SERVICESIFACE where GAO_TYPE=''CAPABILITY''';
and the second "BEGIN" keyword has been commented out after the following line of code.
DBMS_OUTPUT.PUT_LINE('*** Drop table: ' || tab_Table(i) || ' ***');
Since I suspect that whoever has written this code put unnecessary "BEGIN" keyword (i apologize if I'm wrong as I'm not a plsql expert. But doing all the commenting out thing i got rid of so many errors).
But when I compile the above code I still get following 2 errors.
1)
ORA-06550: line 27, column 7:
PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
;
( begin case declare end exit for goto if loop mod null
pragma raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge
2)
ORA-06550: line 38, column 9:
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:
;
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
You have commented out the BEGIN inside the inner loop but not its associated EXCEPTION and END. You need that begin. Also you cannot change an array to a scalar variable while the code still expects an array (references to tab_Table(i) etc.)
Decent indentation of code always makes it easier to follow:
PROCEDURE DropMyTable IS
x number;
TYPE cur_typ IS REF CURSOR;
type NAME_TBL is table of VARCHAR2(30);
tab_Table NAME_TBL;
--tab_Table VARCHAR2S(30);
stmt VARCHAR2(4096);
stmt2 VARCHAR2(4096);
outerCur cur_typ;
rows NATURAL := 1000;
TABLE_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942);
BEGIN
stmt2 := 'select distinct G_Tab from G_SERVE where G_TYPE=''CAP''';
--Begin
OPEN outerCur FOR stmt2;
LOOP
FETCH outerCur BULK COLLECT INTO
tab_Table LIMIT rows;
EXIT WHEN tab_Table.COUNT = 0;
FOR i IN 1..tab_Table.COUNT LOOP
--------------------------------------------------------------------
-- Drop the tables in G_SERVE.G_TAB
DBMS_OUTPUT.PUT_LINE('*** Drop table: ' || tab_Table(i) || ' ***');
BEGIN
--First drop the optable
stmt := 'DROP TABLE ' || tab_Table(i) || '_OPTAB CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the base table
stmt := 'DROP TABLE ' || tab_Table(i) || ' CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the Package
stmt := 'DROP PACKAGE ' || tab_Table(i) || '_PKG';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
EXCEPTION
-- When the table, optab and package doesn't exist,
-- ignore error "ORA-00942: table, optab or package does not exist".
WHEN TABLE_DOES_NOT_EXIST THEN
DBMS_OUTPUT.PUT_LINE('table, optab or package does not exist');
DBMS_OUTPUT.PUT_LINE(CHR(9));
--Re-raises any other errors.
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error!');
RAISE;
END;
END LOOP;
END LOOP;
--END;
END DropMyTable;
I have reinstated that BEGIN and restored the array. I don't know if there is anything else wrong.

PL/SQL: ORA-00942: table or view does not exist

Am getting this error 'PL/SQL: ORA-00942: table or view does not exist' in Oracle 11G when I try to runt his portion of my script. It seems the select statement isn't parsing the name of the variable from the cursor. Need help to ensure this can read the table name variable from the cursor.
DECLARE
ITEM_ERROR NUMBER;
CNT_SITE VARCHAR2(46);
CURSOR C_SITEID IS
SELECT OBJECTNAME,ATTRIBUTENAME FROM MAXATTRIBUTE WHERE ATTRIBUTENAME LIKE 'SITE%' GROUP BY OBJECTNAME,ATTRIBUTENAME, COLUMNNAME;
SITEIDRec C_SITEID%RowType;
BEGIN
BEGIN
OPEN C_SITEID;
LOOP
FETCH C_SITEID into SITEIDRec;
EXIT WHEN C_SITEID %NOTFOUND;
BEGIN
SELECT COUNT(SITEID) into CNT_SITE FROM SITEIDRec.OBJECTNAME
WHERE SITEID IN ('COLLEGE NANO SCI ENG-TGCM','FREESCALE-BALAZS','TGCM-GLOBAL FOUNDRIES','INTL RECTIFIER-TGM','TGCM-DMOS5','TGCM-IMFT','TGCM-TRIQUINT','GP-TRIQUINT');
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END LOOP;
--COMMIT;
CLOSE C_SITEID;
--COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
MSG_TEXT := SUBSTR(SQLERRM,1,200);
--COMMIT;
raise;
END;
I think you have FROM TableName missing in your query and hence it's rightly complaining.
SELECT COUNT(SITEID) into SITEIDRec.OBJECTNAME
WHERE SITEID IN
('COLLEGE NANO SCI ENG-TGCM','FREESCALE-BALAZS',
'TGCM-GLOBAL FOUNDRIES','INTL RECTIFIER-TGM','TGCM-DMOS5',
'TGCM-IMFT','TGCM-TRIQUINT','GP-TRIQUINT');
Please correct your query by adding the From TableName.
EDIT: Try using EXECUTE IMMEDIATE as below
EXECUTE IMMEDIATE 'SELECT COUNT(SITEID) into CNT_SITE FROM '
|| SITEIDRec.OBJECTNAME ||
' WHERE SITEID IN (''COLLEGE NANO SCI ENG-TGCM'',''FREESCALE-BALAZS'',
''TGCM-GLOBAL FOUNDRIES'',''INTL RECTIFIER-TGM'',''TGCM-DMOS5'',
''TGCM-IMFT'',''TGCM-TRIQUINT'',''GP-TRIQUINT'')';

Resources