getting 'FROM' error in oracle query - sql

I'm getting this error on the below query. The query is to modify a constraint
SELECT 'EXEC DROP_CONSTRAINTS('RTK_TYUVOICE_SYSTEM','IOA_WRTYOICE');' FROM DUAL
*
ERROR at line 1:
ORA-00923: FROM keyword not found where expected
Please advise on how to overcome this when I execute the above query from sql/nolog

Either double quotes in the string
SELECT 'EXEC DROP_CONSTRAINTS(''RTK_TYUVOICE_SYSTEM'',''IOA_WRTYOICE'');' as txt FROM DUAL;
TXT
------------------------------------------------------------
EXEC DROP_CONSTRAINTS('RTK_TYUVOICE_SYSTEM','IOA_WRTYOICE');
or use the (from 10g) quoted string
SELECT q'[EXEC DROP_CONSTRAINTS('RTK_TYUVOICE_SYSTEM','IOA_WRTYOICE');]' as txt FROM DUAL;
TXT
------------------------------------------------------------
EXEC DROP_CONSTRAINTS('RTK_TYUVOICE_SYSTEM','IOA_WRTYOICE');

You are trying to modify a constraint using a statement I hope, and are not looking to just print your statement.
In that case, you need to make use of Execute Immediate statement, which helps to execute DDL statements on the fly in a procedure.
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ANAL2 DROP CONSTRAINT SYS_C008611' ;
END;
/
Any valid DDL statement (like create, alter, drop etc) can be squeezed in the EXECUTE IMMEDIATE statement, using their correct syntactic formation.
Alternatively, you could just mention, if the given SQL is static, as
ALTER TABLE ANAL2 DROP CONSTRAINT SYS_C008611

Related

PLS-00103: Encountered the symbol "CREATE" when expecting one of the

I am trying to create a stored procedure in oracle 12c database and I am getting error when I am running code to store the procedure.
PLS-00103: Encountered the symbol "CREATE" when expecting one of the
There are multiple stack overflow question already asked on this topic. but they suggest some different syntax. which is deviation from actual oracle documentation. and even those didn't worked for me
I checked for documentation on multiple website including oracle documentation. oracle documetation suggest syntax as following
Oracle STORED PROCEDURE DOCUMENTATION
so I as per the syntax I wrote the following procedure.
CREATE PROCEDURE PDD_PROC_BASE
AS
--DROP TABLE BASE;
CREATE TABLE BASE as
SELECT idno
,DATE
,diff
,SUBSTR(idNO,7,2) AS PRD
,COMPLETED
,CATG
,OP_Number
FROM table1
WHERE = date >= '30-JUN-2018'
AND STATUS = 'G'
END;
and I got the following error.
Procedure PDD_PROC_BASE compiled
Errors: check compiler log
Errors for PROCEDURE AN_5043152.PDD_PROC_BASE:
LINE/COL ERROR
-------- ------------------------------------------------------------------------------
7/5 PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
( begin case declare 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
json_exists json_value json_query json_object json_array
I checked other resources as well but still didn't understood what went wrong.
I even tried code example from Oracle documentation and got similar error.
I am using SQLdeveloper tool as client
You cant use directly sql ddl statements in plsql block, you can do the same thing using dynamic sql with the "EXECUTE IMMEDIATE" statement like this:
begin
execute immediate 'create table test_table1 (test_column1 varchar2(40))';--your create table statement here
end;
In Oracle in stored procedures you can use DDL statements only as dynamic SQL, that means as EXECUTE IMMEDIATE 'CREATE TABLE ' ...
Check here, for example: http://www.dba-oracle.com/t_using_ddl_create_index_table_plsql.htm

How can I control execution of a SQL statement based on the DB2s structure?

We want to run a simple SQL statement (dropping and creating an index), but only if the old index has not already been deleted. After looking up the syntax for IF in DB2, I came up with this:
IF EXISTS (SELECT indname FROM SYSCAT.INDEXES WHERE INDNAME = 'TEST_CREATE_INDEX_OLD')
THEN
DROP INDEX TEST_CREATE_INDEX_OLD;
create index TEST_CREATE_INDEX_NEW on example_table
(
id,
another_field
);
END IF;
When run with either SQuirrel (already setup to run with db2) or via command line, this script results in an error:
An unexpected token "IF EXISTS (SELECT indname FROM SYSCAT.INDEX" was
found following "BEGIN-OF-STATEMENT". Expected tokens may include:
"".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.23.42 SQL Code:
-104, SQL State: 42601
So - what am I doing wrong? Am I missing something, or is there another way to achieve my goal (check for $thing in database, execute appropriate query) that so far has not occured to me?
If IF statement is valid only in a compound-SQL block (i.e. inside a stored-procedure/routine/function/anonymous-block).
It's not valid standalone as your question shows, and that is why Db2 throws the -104 error.
You can look up the explanation of the sqlcode -104 by looking up SQL0104N in the free online Db2 Knowledge Center at this link.
To be able to use compound-SQL in your Squirrel-SQL tool, you need to configure squirrel to use an alternative statement terminator. Google that. In the examples below, I show a statement terminator of # (to delimit the block).
Here are two different ways to do what you want with Db2-Linux/Unix/Windows, each uses an anonymous block. Other approaches are possible.
In this example the drop-index will only run if the index-name exists in the current schema:
begin
declare v_index_exists integer default 0;
select 1 into v_index_exists
from syscat.indexes
where indname = 'TEST_CREATE_INDEX_OLD';
if v_index_exists = 1
then
execute immediate('drop index TEST_CREATE_INDEX_OLD');
execute immediate('create index TEST_CREATE_INDEX_NEW on example_table ( id, another_field)');
end if;
end#
In this example the drop-index will always run, but the block won't abort if the index does'nt exist (i.e. it will continue and not throw any error).
begin
declare v_no_such_index integer default 0;
declare not_exists condition for sqlstate '42704';
declare continue handler for not_exists set v_no_such_index=1;
execute immediate('drop index TEST_CREATE_INDEX_OLD');
execute immediate('create index TEST_CREATE_INDEX_NEW on example_table ( id, another_field)');
end#
You must use another statement delimiter, if you want to use db2 compound statement.
In Squirrel: Session -> Session Properties -> SQL -> Statement Separator = #.
Indexes in Db2 are fully qualified by 2 SYSCAT.INDEXES columns: INDSCHEMA and INDNAME. So, it's advisable to use both these fields in a SELECT statement on SYSCAT.INDEXEX as in example.
You can't use static DDL statements in a compound statement. Use EXECUTE IMMEDIATE statements instead.
Below is an example emulating UPDATE INDEX for the index in a schema equal to CURRENT SCHEMA special registry set in the session.
BEGIN
IF EXISTS (SELECT indname FROM SYSCAT.INDEXES WHERE INDSCHEMA = CURRENT SCHEMA AND INDNAME = 'TEST_CREATE_INDEX_OLD')
THEN
EXECUTE IMMEDIATE 'DROP INDEX TEST_CREATE_INDEX_OLD';
EXECUTE IMMEDIATE'
create index TEST_CREATE_INDEX_NEW on example_table
(
id,
another_field
)
';
END IF;
END
#

PLSQL Procedure to Truncate and Re-populate table

I have some tables and views in my schema and I am trying to create a stored procedure that will take in 2 parameters (table_name, view_name) to Truncate a table and re-populate it from a view.
Here is the code I have for the procedure:
CREATE OR REPLACE
PROCEDURE PROC_NAME (TABLE_NAME IN VARCHAR2, VIEW_NAME IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE TABLE_NAME';
EXECUTE IMMEDIATE 'INSERT INTO TABLE_NAME
SELECT * FROM VIEW_NAME';
END;
/
Now when I run the following code:
BEGIN
PROC_NAME('SOME_TABLE', 'SOME_VIEW');
END;
/
I get the following error:
ORA-00942: table or view does not exist
ORA-06512: at "SCHEMA.PROC_NAME", line 4
ORA-06512: at line 2
00942. 00000 - "table or view does not exist"
What do you guys think is the issue?
Thanks in advance!
Try:
CREATE OR REPLACE
PROCEDURE PROC_NAME (TABLE_NAME IN VARCHAR2, VIEW_NAME IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE '||TABLE_NAME;
EXECUTE IMMEDIATE 'INSERT INTO '||TABLE_NAME||'
SELECT * FROM '||VIEW_NAME;
END;
/
Your basic problem is that you had passed the parameters correctly but had not used them in the procedure. The fix was to used the the concatenation operaterator || in the strings used by EXECUTE IMMEDIATE to combine the the parameters into the string being executed.
An additional option is to use DELETE FROM rather than TRUNCATE TABLE. When Oracle first implemented Materialised Views, which is a grown up version of what you are trying to achieve, they made the same mistake. TRUNCATE TABLE is very quick but in the Oracle implementation it is a DDL (Data Definition Language) statement which means it will complete with an implicit commit. Therefore, for a period of time until the INSERT completes (and is committed), your table will be empty. If Oracle thought it important enough to change their underlying technique, then you should consider doing the same.
If you do not change to the DELETE technique then you should adding a COMMIT at the end of your procedure. The use of TRUNCATE TABLE will guarantee the removal of the data is committed, so if your INSERT succeeds then you should also commit that statement.
My reference to Materialised Views is relevant as it is a potential a built-in replacement for what you are trying to write for yourself. The problem with it is that it has so many bells and whistles that it is difficult to find an article on how to use it in your simple use case. I would welcome a comment referencing such an article.

How to execute stored procedures containing dynamic SQL in oracle?

I've created the following procedure
Create or replace procedure abcd
(
tab_name in USER_TABLES.table_name%type
)
is
begin
execute immediate
'select * from'||tab_name;
end abcd;
The procedure gets compiled.
I am trying to get the output using the following
select abcd('Table') from dual ;
I am new to dynamic SQL and this does not seem to work for me. I keep getting the error
[Error] Execution (44: 8): ORA-00904: "ABCD": invalid identifier
Can someone please help ?
Regards,
Kshitij
You're missing a space before your table name:
create or replace procedure abcd (tab_name in USER_TABLES.table_name%type )
is
begin
execute immediate 'select * from '||tab_name;
end abcd;
This won't work because you're trying to call it as a function, not a procedure:
select abcd('Table') from dual ;
Your second attempt should now work:
exec abcd('Table');
... but will now get a different error. In PL/SQL you have to select into something. In this case you probably want to open a cursor with the dynamic string and do something with the results. Not really sure what your end goal is though.
You should also read up about SQL injection while you learn about dynamic SQL.
you cannot perform a select on a procedure, a function will work only if single record return.
use
begin
abcd();
end;
or use
execute keyword
ALSO use a space after from in query
It will not work.
When you invoke EXECUTE IMMEDIATE the sql statement is send to SQL engine. No results are passed back to the PL/SQL.
Writing "SELECT * FROM a_table" is not that hard and much safer.

Create/alter from SQL stored procedure

I want to call create table/ alter table command from a procedure. Is it possible?
My requirement is to change the datatype of a column in all tables. So, I am just getting the column name from user_tab_cols. Now I want to create a temp table which requires create statement .. but i am unable to use that within a proc.
Can anyone please help me out?
I presume from the reference to USER_TAB_COLUMNS that this is Oracle. ALTER and CREATE statements are DDL, which we cannot execute directly in PL/SQL. However, there are a couple of ways around this restriction: EXECUTE IMMEDIATE and DBMS_UTILITY.EXEC_DDL(). I will use EXECUTE IMMEDIATE in the following example.
begin
for lrec in ( select table_name from user_tab_columns
where column_name = 'UNIVERSAL_COLUMN_NAME')
loop
execute immediate 'alter table '||lrec.table_name||
' modify UNIVERSAL_COLUMN_NAME varchar2(255)';
end loop;
end;
Note that the usual restrictions apply: the new datatype has to be compatible with the existing datatype (unless the column is empty), and things are trickier with some specilaized datatypes like CLOBs.
edit
I haven't addressed the CREATE TABLE statement. The principle is the same, it is just longer to type out. Besides, I am not entirely clear how it applies to your prior requirement to change the datatype of those columns.
you can generate the query as string and execute it with 'exec' keyword.