Error while executing a stored procedure to drop a table - oracle

Getting error while executing a stored procedure that drops a table.
I have compiled the procedure successfully (used dynamic SQL for the code).
Tool used is SQL Developer.
CREATE OR REPLACE PROCEDURE sp_DROP(P_VAR IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE'||P_VAR; -- passing table via parameter
END;
but I'm getting error while executing this procedure:
EXECUTE sp_DROP('CON1'); -- i have made sure CON1 is a legit table.
Error :
ORA-00950: invalid DROP option
ORA-06512: at "HR.SP_DROP", line 4
ORA-06512: at line 3
00950. 00000 - "invalid DROP option"
*Cause:
*Action:
Thanks for the help.

Add a space to the end of drop table.
CREATE OR REPLACE PROCEDURE sp_DROP(P_VAR IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE '||P_VAR; -- passing table via parameter
END;

Related

Insufficient privilege when create dynamic table in stored procedure while in PL/SQL block table has been created [duplicate]

This question already exists:
I am getting an error due to variable when I execute stored procedure which dynamic PLSQL inside was there in the stored procedure [duplicate]
Closed 3 years ago.
When i execute stored procedure which contain EXECUTE IMMEDIATE along with create table statement inside the stored procedure then getting error while execute this Stored Proc.
Here is the Stored proc-
create or replace sp_exec
as
.......
v_mth date;
.......
begin
select to_char(add_months(current_DATE, -1), 'MON_YY') INTO v_mth FROM dual;
execute immediate 'create table tbl_mon_' ||v_mth|| ' as select ............... from ..... ';
end;
When I try to execute this Stored proc then getting error "Insufficient Privilege" at 2nd last line using this code to execute Stored Proc.
begin
sp_exec;
end;
then getting error which mentioned below:-
ORA-01031: Insufficient privilege
ORA-06512: at sp_exec line 11 --here line 11 mention for Execute immediate
ORA-06512: at line 2 -- here mention for sp_exec in the PLSQL block
I am working in the user schema itself so I've all types of privileges even CREATE TABLE statement also. When i run outside the stored procedure (PL/SQL block) then dynamic table have been created.
Apparently, you acquired the create table privilege via role. It won't work in named PL/SQL procedures, which means that you'll have to grant it directly to user.

ORA-04068: existing state of packages has been discarded

I've wrapper procedure which looks like this:
Procedure A
BEGIN;
Procedure B
Procedure C
END;
/
Procedure B drops and re-creates a table used in Procedure C. Due to this, I get the below error:
ERROR at line 1:
ORA-04068: existing state of packages has been discarded ORA-04065: not executed, altered or dropped stored procedure "SCHEMA.PROCEDURE C"
ORA-06508: PL/SQL: could not find program unit being called: "SCHEMA.PROCEDURE C"
ORA-06512: at "SCHEMA.PROCEDURE A", line 4
ORA-06512: at line 1
How do I go about getting this procedure to work?
So your proc get invalid during the execution, that is why you need recompile Procedure C. To achive this, you can call a dynamic SQL statement:
EXECUTE IMMEDIATE 'ALTER PROCEDURE my_procedure COMPILE';
Procedure_A IS
BEGIN;
Procedure_B;
EXECUTE IMMEDIATE 'ALTER PROCEDURE Procedure_C COMPILE';
Procedure_C;
END;
/
I recommend using dynamic SQL to call the DML in procedure C. By removing the dependency nothing gets invalidated. This would likely be more reliable than dynamically re-compiling code or dynamically running the code and catching all exceptions.
You can see this in the below sample code. Comment out the static SQL call on line 10 in procedure C to replicate the error.
drop table drop_me;
create table drop_me(id number);
create or replace procedure C is
v_count number;
begin
--Static SQL would fail with this error:
-- ORA-04068: existing state of packages has been discarded
-- ORA-04065: not executed, altered or dropped stored procedure "JHELLER.C"
-- ORA-06508: PL/SQL: could not find program unit being called: "JHELLER.C"
-- ORA-06512: at "JHELLER.A", line 4
-- ORA-06512: at line 2
--select count(*) into v_count from drop_me;
--Dynamic SQL runs correctly:
execute immediate 'select count(*) from drop_me' into v_count;
end;
/
create or replace procedure B is
begin
execute immediate 'drop table drop_me purge';
execute immediate 'create table drop_me(id number)';
end;
/
create or replace procedure A is
begin
B;
C;
end;
/
begin
A;
end;
/
But I agree with Alex Poole that there is almost certainly a better way to do this without dropping and re-creating objects. I can think of a few reasons why a DROP and CREATE might run faster than a TRUNCATE and INSERT, but only because of some weird side-effect, like dropping bad table statistics. Investigate the difference more and you might find the real reason.
You can do something like it.
begin
procedureB;
begin
execute immediate 'begin procedureC; end;';
exception when others then
execute immediate 'begin procedureC; end;';
end;
end;

Issue with Oracle stored Procedure when invoked with Hibernate - ORA-01001: invalid cursor

I am facing a strange problem.
I have created an oracle stored procedure and tested it in SQL Developer and it works fine.
Now when I tried to call it using Hibernate 3,it shows the below mentioned error message. Can someone help me what I am missing? The line number it is giving points to the line where myCursor2 is being closed.
Caused by: java.sql.SQLException: ORA-01001: invalid cursor
ORA-06512: at "MystoredProcedure", line 56
My stored procedure looks as below.
create or replace PROCEDURE MystoredProcedure (
four input arguemnts and
one output variable all are numbers
) AS
cursor myCursor2 is
select statement;
CURSOR myCursor1 is
select statement;
Variables to hold data
BEGIN
OPEN myCursor1;
LOOP
FETCH myCursor1 into variables;
EXIT WHEN myCursor1%NOTFOUND;
insert data into a set of tables.
OPEN myCursor2;
LOOP
FETCH myCursor2 into variables;
EXIT WHEN myCursor2%NOTFOUND;
insert data into some other tables
END LOOP;
end Loop;
insert into another table
CLOSE myCursor2;
CLOSE myCursor1;
END MystoredProcedure;

Creating a DB link if not created inside a stored procedure

I'm trying to code a stored procedure in Oracle. I don't have a ton of experience with it and I'm running to an issue. The end goal of the procedure is to take data from one DB and put it into another in a different form. I have most of the procedure working it seems but I'm having issues with something that seems like it should be simple. At the beginning of the code, I would like to check to make sure a DB link is created. If not, then I want to create the db link.
This is what I put inside my procedure:
IF (select count(1) from ALL_DB_LINKS where db_link = 'DB_LINK.NAME.COM') = 0 THEN
CREATE DATABASE LINK LINK_NAME
CONNECT TO username IDENTIFIED BY password
USING 'SID';
END IF;
I know the link works because I've done it outside this and did a lookup with it. The error I get when I try to compile is this:
Encountered the symbol "CREATE" when expecting one of the following:
I've done all the googling I think I can do and I cannot figure out what I am doing wrong. To head off the other question I have, I've also tried to do it by putting in:
DECLARE test_count number;
select count(1) into test_count from ALL_DB_LINKS where db_link = 'DB_LINK.NAME.COM';
BEGIN
IF test_count = 0 THEN
CREATE DATABASE LINK LINK_NAME
CONNECT TO username IDENTIFIED BY password
USING 'SID';
END IF;
END;
But I get the same error. I'm also not sure if having a begin inside a begin will work. Any help would be a great... well, help.
Oracle compiles packages and in order to do that all objects referenced in code need to already exist. This includes objects referenced over a database link. Things will get marked invalid if the referenced objects don't exist. Usually a DBA will create and maintain such an environment using PL/SQL scripts and not stored procedures.
If you really want to anyway:
EXECUTE IMMEDIATE q'[ CREATE DATABASE LINK LINK_NAME
CONNECT TO username IDENTIFIED BY password
USING 'SID']';
If you really need to do this, you can create the link using dynamic SQL as Ed Gibbs suggested and Brian showed, as long as the link already exists at the point the procedure is created:
create database link test_link
connect to scott identified by oracle
using 'ORCL';
Database link created.
create or replace procedure p42 as
l_count number;
l_dummy dual.dummy%type;
begin
select count(*) into l_count
from all_db_links
where db_link = 'TEST_LINK';
if l_count = 0 then
execute immediate q'[
create database link test_link
connect to scott identified by oracle
using 'ORCL'
]';
end if;
select dummy into l_dummy from dual#test_link;
dbms_output.put_line('Value from remote database: ' || l_dummy);
end;
/
Procedure created.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
But the procedure won't compile if the link doesn't already exist:
drop database link test_link;
create or replace procedure p42 as
...
end;
/
Warning: Procedure created with compilation errors.
show errors
Errors for PROCEDURE P42:
LINE/COL ERROR
-------- -----------------------------------------------------------------
16/5 PL/SQL: SQL Statement ignored
16/5 PL/SQL: ORA-00942: table or view does not exist
Curiously it doesn't object if you create the procedure while the link exists, and then drop the link; the procedure stays valid, the dynamic SQL works to recreate the link, and the procedure runs successfully:
drop database link test_link;
Database link dropped.
select object_type, object_name, status from all_objects
where object_type = 'PROCEDURE' and object_name = 'P42';
OBJECT_TYPE OBJECT_NAME STATUS
--------------- --------------- ---------------------
PROCEDURE P42 VALID
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
I would have expected dropping the link to invalidate the procedure, but apparently not, despite it appearing in all_dependencies. You can't recompile the procedure though:
drop database link test_link;
Database link dropped.
alter procedure p42 compile;
Warning: Procedure altered with compilation errors.
show errors
Errors for PROCEDURE P42:
LINE/COL ERROR
-------- -----------------------------------------------------------------
16/5 PL/SQL: SQL Statement ignored
16/5 PL/SQL: ORA-00942: table or view does not exist
In order to let you compile (or recompile) while the link does not exist, you'd need to reference the link using dynamic SQL as well:
drop database link test_link;
drop database link test_link
*
ERROR at line 1:
ORA-02024: database link not found
create or replace procedure p42 as
....
execute immediate 'select dummy from dual#test_link' into l_dummy;
dbms_output.put_line('Value from remote database: ' || l_dummy);
end;
/
Procedure created.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
drop database link test_link;
Database link dropped.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.
drop database link test_link;
Database link dropped.
alter procedure p42 compile;
Procedure altered.
exec p42;
Value from remote database: X
PL/SQL procedure successfully completed.

creating insert trigger error

i'm trying to create a trigger that sets the id from a predefined sequence.
CREATE SEQUENCE seq_list_status
START WITH 1
INCREMENT BY 1
;
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
select seq_list_status.nextval into :new.id from dual;
/
i'm getting the error below while creating the trigger
Error starting at line 1 in command:
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
select seq_list_status.nextval into :new.id from dual
Error at Command Line:4 Column:4
Error report:
SQL Error: ORA-04079: invalid trigger specification
04079. 00000 - "invalid trigger specification"
*Cause: The create TRIGGER statement is invalid.
*Action: Check the statement for correct syntax.
i googled it but it seems all ok. any idea for what could be wrong?
Triggers are program units. Consequently we must wrap the code body in BEGIN and END. Try this
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
BEGIN
select seq_list_status.nextval into :new.id from dual;
END;
/
Unfortunately the examples in the SQL Reference are not as helpful as we would like. But it does link to other useful documents, such as the App Developers Guide.
you are missing the begin end
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
BEGIN
select seq_list_status.nextval into :new.id from dual;
END;
/

Resources