Failed to dynamically drop table in PL / SQL - oracle

What i am trying to do
I am trying to create a procedure which accepts table_name as its parameter. And inside the procedure i am dynamically dropping the table using Dynamic SQL
What is the problem
After calling the procedure by writing execute droptab('TEST'); i get the following error:
ERROR at line 1:
ORA-00950: invalid DROP option
ORA-06512: at "SYSTEM.DROPTAB", line 4
ORA-06512: at line 1
Procedure
create or replace procedure dropTab (tableName in varchar2) is
begin
EXECUTE IMMEDIATE 'DROP TABLE' || tableName;
end;
/

Change
'DROP TABLE'
to
'DROP TABLE '
I.e. add an additional space

Related

ORA-00903:invalid table name

I have the following code in PLSQL:
Declare
tablename varchar2(20):='emp';
drop_stmt varchar2(2000);
begin
drop_stmt:='drop table :1 ;';
--dbms_output.put_line(drop_stmt);
execute immediate drop_stmt using tablename;
end;
Results in:
ORA-00903:invalid table name
ORA-06512: at line 8
However when I run:
drop table emp ;
it just successfully runs. What may be the cause of this error?
You must use this one:
drop_stmt:='drop table '||tablename; -- without ";" at the end of string
--dbms_output.put_line(drop_stmt);
execute immediate drop_stmt;

Execution of Multiple procedures one after another is not working

I am trying to execute a procedure which in turn should execute four other procedures one after the other. How do I acheive this?
Create or replace procedure mainproc
as
begin
tack(400);
phno_insert;
address_insert;
academics_insert;
commit;
end;
Error report:
PLS-00905: Object phno_insert is invalid. PL/SQL: Statement ignored.
PLS-00905: Object address_insert is invalid. PL/SQL: Statement
ignored. PLS-00905: Object academics_insert is invalid. PL/SQL:
Statement ignored.
The problem seems to be in the fact that you have a procedure doing a DDL over an object that is statically referenced in another procedure; for example, if I define:
create table runtimeTable as select 1 as one from dual;
create or replace procedure createTable is
begin
execute immediate 'drop table runtimeTable';
execute immediate 'create table runtimeTable as select 1 as one from dual';
end;
create or replace procedure useTable is
vVar number;
begin
select one
into vVar
from runtimeTable;
--
dbms_output.put_line(vVar);
end;
create or replace procedure createAndUseTable is
begin
createTable;
useTable;
end;
/
when I try to execute createAndUseTable I get:
ORA-04068: existing state of packages has been discarded ORA-04065:
not executed, altered or dropped stored procedure "ALEK.USETABLE"
ORA-06508: PL/SQL: could not find program unit being called:
"ALEK.USETABLE" ORA-06512: at "ALEK.CREATEANDUSETABLE", line 4
ORA-06512: at line 1
If you strictly need to do a DDL runtime, you need to use dynamic SQL to reference the modified object; for example if I define the procedure useTable this way
create or replace procedure useTable is
vVar number;
begin
execute immediate
'select one
from runtimeTable'
into vVar;
--
dbms_output.put_line(vVar);
end;
the call to createAndUseTable will work:
SQL> exec createAndUseTable
1

Running PLSQL ( Oracle ) Stored Procedure in Liquibase error : Package or function X is in an invalid state

I am trying to run the following stored procedure:
CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
AS
BEGIN
FOR i IN 1..5 LOOP
DBMS_OUTPUT.PUT('Try #' || i);
ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL;
END;
END;
/
and calling it in changelog.xml as:
<sql>CALL RETRY_TRANS_EXCEPTION();</sql>
i get error:
Liquibase update Failed: Migration failed for change set eldata-changelog.xml::2016-08-25-cn-01::Ch Will:Reason: liquibase.exception.DatabaseException: Error executing SQL CALL RETRY_TRANS_EXCEPTION(): ORA-06575: Package or function RETRY_TRANS_EXCEPTION is in an invalid state
What i am trying to achieve is to be able to run a stored procedure through Liquibase with a loop in it.
Thanks for your help Prashant. What worked in my case was your solution plus one change:
CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
AS
v_query varchar2(100);
BEGIN
FOR i IN 1..500 LOOP
DBMS_OUTPUT.PUT('Try #' || i);
v_query := 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NULL';
execute immediate v_query;
END loop;
END;
/
and then calling the Stored Procedure from the changelog, as:
<changeSet id="2016-08-25-cw-01" author="Ch Will">
<comment>
Testing retry logic on liquibase
</comment>
<sql>CALL RETRY_TRANS_EXCEPTION();</sql>
</changeSet>
You can't call it because the procedure does not compile correctly. Go back and fix the compilation errors, then try again.
Here are a couple of errors that stand out to me:
the for loop should end with end loop;, not end;
You can't have DDL statements directly in the code. You need dynamic SQL to execute a DDL statement from a procedure: execute immediate 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL';
Additional note: I don't understand why you are trying to execute the same DDL statement multiple times inside a loop. Obviously, you won't be able to add the same column with the same name over and over. You will get a runtime error.
SQL> CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
2 AS
3 BEGIN
4 FOR i IN 1..5 LOOP
5 DBMS_OUTPUT.PUT('Try #' || i);
6 ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL;
7 END;
8 END;
9 /
Warning: Procedure created with compilation errors
SQL> show err
Errors for PROCEDURE PRASHANT-MISHRA.RETRY_TRANS_EXCEPTION:
LINE/COL ERROR
-------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6/4 PLS-00103: Encountered the symbol "ALTER" 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
Did required fixes :
CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
AS
v_query varchar2(100);
BEGIN
FOR i IN 1..5 LOOP
DBMS_OUTPUT.PUT('Try #' || i);
v_query := 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL' ;
execute immediate v_query;
END loop;
END;
PLSQL stored procedure can't use DDL statements, like
alter table ...
so the
execute immediate ("...")
statement is required because in fact it creates an autonomous implicit transition that can't be rollbacked

Creation of table and insertion within the same procedure in pl/sql

I'm trying to create a table and then insert some values in it within the same procedure in pl/sql. I tried to run the following query without success:
create or replace Procedure insertval8(id_no in number,e_name in char)
is
begin
execute immediate 'create table edu2(id number(20), name char(12))';
insert into edu2 values(&id_no,&e_name);
end;
displays
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/1 PL/SQL: SQL Statement ignored
5/13 PL/SQL: ORA-00942: table or view does not exists
The error persists until I remove the insert code.
The procedure cannot be compiled because the table is not present at compile time.
Wrap the insert in execute immediate also, or use a global temporary table (generaly the preferred solution for temporary data).
create or replace procedure insertval8 (id in number,
name in char )
is
begin
execute immediate 'create table edu2(id number(20), name char(12))';
execute immediate 'insert into edu2(id, name) values (:1, :2)'
using id, name;
end;

Oracle : Stored procedure how to to_char expression in string variable

I am trying to create table dynamically in Oracle stored procedure.
I have created create table sql in the string variable.
Below is the sql snapshot and error.
Procedure is getting compiled without any issue. But when trying to execute the procedure, I am getting runtime error. I am getting the issue because of to_char expression.
CREATE OR REPLACE PROCEDURE TESTPROC12(P_TMP_Table IN VARCHAR2) AUTHID CURRENT_USER IS
V_SQL_STMT1 varchar2(1000);
V_TMP_Table varchar2(100);
BEGIN
V_TMP_Table := concat('TMP', to_char(sysdate,'MMDDYYYYHH24MISSSSS'));
V_SQL_STMT1 := 'CREATE TABLE '|| V_TMP_Table||' AS
SELECT * from TMP_STMTSENT2 where rowid in (select min(rowid) from '|| P_TMP_Table||'
group by CUSTOMER_RELATIONSHIP_ID, to_char(''STATEMENT_PROCESSED_DATE'',''MM/DD/YYYY''))';
EXECUTE IMMEDIATE V_SQL_STMT1;
END;
Procedure - I need to use to_char.
EXEC TESTPROC12('TMP_STMTSENT2')
Error starting at line 20 in command:
EXEC TESTPROC12('TMP_STMTSENT2')
Error report:
ORA-01722: invalid number
ORA-06512: at "EDLVY.TESTPROC12", line 15
ORA-06512: at line 1
01722. 00000 - "invalid number"
*Cause:
*Action:
The generated and executed statement could look like the following:
CREATE TABLE 10222013023309188 AS SELECT * from TMP_STMTSENT2 where rowid in (select min(rowid) from qeoiwqeoiwq group by CUSTOMER_RELATIONSHIP_ID, to_char('STATEMENT_PROCESSED_DATE','MM/DD/YYYY'))
The problem could be with 'STATEMENT_PROCESSED_DATE', which is not a date. Try sysdate instead and see if it works.
Take a look at the docs. You are passing the string 'STATEMENT_PROCESSED_DATE' to to_char(). Maybe you want to pass the column or value STATEMENT_PROCESSED_DATE instead?
A good way to do what you are pusuing is using Oracle Temporary Tables
http://docs.oracle.com/cd/B28359_01/server.111/b28310/tables003.htm#i1006400
http://www.dba-oracle.com/t_temporary_tables_sql.htm
http://www.oracle-base.com/articles/misc/temporary-tables.php

Resources