create or replace procedure createtables
Authid current_user as
begin
execute immediate 'create table newcustomer as select * from customer';
end;
create or replace procedure e
is
begin
createtables;
select * from newcustomer;
end;
I got two procedures above. first one will create a new tables called newcustomer, second procedure will call the first procedure and query to the newcustomer table. when I try to compile this code, it says the table is not yet created, I don't really get it as I have called createtables procedure so I assume I have created the table.
Any help will be appreciated. Thanks
Compiling the second procedure without executing the first procedure first will fail, since the table has not been created.
You cannot compile a procedure that relies on objects that do not exist.
Use EXEC createtables before creating procedure e, and do not call createtables in there.
Procedure e will also not compile because you are not using the results of select * from newcustomer as cursor or store the results into variables.
EDIT:
Instead of procedures, you could use an anonymous block. Put the following into a file and execute it (via SQL*Plus for example):
Create Table newcustomer As Select * From customer;
Begin
Null; --# Do something with your new table in here.
End;
/
Related
I'm using PL/SQL Developer. I'm trying to get query results to excel via vba. Since query is so long, i decided to create table with the query results and then simply get the table results with vba. In order to create table via excel i needed to create procedure with dynamic sql. So this is what i tried so far (even this simple example doesn't work):
create or replace procedure d_x IS
str VARCHAR(81) = 'create table as select 1 as x from dual'
BEGIN
EXECUTE IMMEDIATE str;
END;
Procedure completes without error. But when i try to execute it to create table it throws an error.
Execute statement:
EXECUTE d_x;
The execute statement throws 'ORA-00900' Invalid sql statement error.
I'm kinda new to pl sql so i couldn't find a solution to this.
Any help would be appreciated, thanks.
Procedure you posted can't possibly execute without errors because it is invalid. When fixed, looks like this:
SQL> create or replace procedure d_x IS
2 str VARCHAR(81) := 'create table test as select 1 as x from dual';
3 BEGIN
4 EXECUTE IMMEDIATE str;
5 END;
6 /
Procedure created.
In tools that support execute, you can run it as:
SQL> execute d_x
PL/SQL procedure successfully completed.
SQL> select * from test;
X
----------
1
"Correct" way - which works anywhere - is to enclose it (the procedure) into begin-end block:
SQL> drop table test;
Table dropped.
SQL> begin
2 d_x;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL>
I suggest you do that.
In PL/SQL Developer you can click on the procedure name and choose 'Test', which will generate a calling script as a Test window.
You can only use execute in a Command window, because it's a SQL*Plus command and not part of SQL or PL/SQL, and the Command window is a SQL*Plus emulator.
In a SQL window you could either use a complete PL/SQL block:
begin
d_x;
end
/
or use the SQL call command:
call d_x();
Note that call() requires brackets regardless of whether or not the procedure has any parameters.
The / character is useful as a separator when using PLSQL blocks in a SQL window where you have more than one statement, otherwise PL/SQ Developer won't know where one ends and the next starts.
A Test window can only have one statement and only a single PL/SQL block or SQL statement is allowed, so there is no / character at the end.
I'm a SQL Server DBA currently getting up to speed on Oracle. I'm trying to create something very similar to sp_WhoIsActive for SQL Server but for Oracle without reinventing the wheel. Essentially all I'm doing is selecting some values from v$session and inserting them into a table (poor man's ASH/AWR).
It would seem that in Oracle 12.1, there's a bug when querying dictionary views where it can take forever due to bad parsing logic (Bug 22225899 : SLOW PARSE FOR COMPLEX QUERY). The work-around is to set a session parameter:
alter session set "_optimizer_squ_bottomup"=false;
In T-SQL, I could very easily execute a stored procedure in-session and set this variable at runtime. However in Oracle, it wouldn't seem thats the case.
Sample Code:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(
v_temp NUMBER :=1
) IS
BEGIN
alter session set "_optimizer_squ_bottomup"=false;
INSERT INTO SY_DB_ACTIVITY
SELECT
<fields>
FROM
v$session;
commit;
When I run this, I get the error:
"PLS-00103: Encountered symbol 'ALTER' when expecting one of the following..."
Right now, the only way I know how to do this is via a utility like SQL Plus that initiates an interactive user session. Can anyone give me some direction as to how Oracle handles this situation? I'd like to bundle this up into a SP or a Package and then call it from Oracle Scheduler.
Hre is a simple example how to execute alter session inside of the procedure:
CREATE PROCEDURE SP_DB_ACTIVITY IS
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
END;
/
Here is the way you can combine that with your select and insert statement:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
SELECT 1
INTO v_Id
FROM dual;
INSERT INTO SY_DB_ACTIVITY (id) VALUES(v_Id);
END SP_DB_ACTIVITY;
/
Here is a small DEMO where you can see what will procedure do when you call it and how you can call it. Also, in this example you are calling procedure with and IN parameter. So you can use that parameter for something and in the example above is the procedure without any parameters...
You can also, of course, insert into table directly:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
INSERT INTO SY_DB_ACTIVITY(id)
select 1
from dual;
END SP_DB_ACTIVITY;
/
I have this procedure to create a table 'circle' and insert some radius and corresponding area to it, this is my code
create or replace procedure table1
is
BEGIN
execute immediate'drop table circle';
execute immediate'create table circle (r int, a int)';
end;
declare
r int;
ar float;
begin
for r in 3 .. 7 loop
ar:=3.14*r*r;
INSERT INTO circle VALUES(r,ar);
end loop;
execute immediate 'select * from circle';
end;
But when I run this I get this warning
Warning: Procedure created with compilation errors.
and when I try to find the table I get
SQL> select * from circle;
select * from circle
*
ERROR at line 1:
ORA-00942: table or view does not exist
what is wrong in my code?
In the code mentioned above, you're just creating a procedure. It also needs to be executed successfully before using the table in anonymous block.
I've created your procedure here and the procedure is created successfully.
Just when you try to execute it, handle the exception for when the table circle doesn't exist in your procedure's code and then execute (or call) it. Further, you could use the anonymous block to insert the values in your table.
If the table doesn't exist, attempting to drop it will fail. The rest of the code won't run, so your table is never created
Carry out your drop attempt and catch the error, then proceed
This answer has more info: Oracle: If Table Exists
In my attempts to edit a procedure using the line
CREATE OR DROP PROCEDURE
I have created two procedures with the same name, how can I delete them?
The error I receive whenever I attempt to drop it is
Reference to Rountine BT_CU_ODOMETER was made without a signature, but the routine is not unique in its schema.
SQLSTATE = 42725
I am using DB2
Assuming this is DB2 for LUW.
DB2 allows you to "overload" procedures with the same name but different number of parameters. Each procedure receives a specific name, which can be provided by you or generated by the system and which will be unique.
To determine the specific names of your procedures, run
SELECT ROUTINESCHEMA, ROUTINENAME, SPECIFICNAME FROM SYSCAT.ROUTINES
WHERE ROUTINENAME = 'BT_CU_ODOMETER'
You can then drop each procedure individually:
DROP SPECIFIC PROCEDURE <specific name>
In case you need to drop all the overloads of a given procedure name, here's a handy script based on mustaccio's answer
BEGIN
FOR rec AS
SELECT SPECIFICNAME, ROUTINETYPE
FROM SYSCAT.ROUTINES
WHERE ROUTINENAME = 'ROUTINE_NAME'
DO
IF rec.ROUTINETYPE = 'P' THEN
EXECUTE IMMEDIATE 'DROP SPECIFIC PROCEDURE ' || rec.SPECIFICNAME;
ELSE
EXECUTE IMMEDIATE 'DROP SPECIFIC FUNCTION ' || rec.SPECIFICNAME;
END IF;
END FOR;
END
PROBLEM
When multiple stored procedures are created with the same name but with a different number of parameters, then the stored procedure is considered overloaded. When attempting to drop an overloaded stored procedure using the DROP PROCEDURE statement, the following error could result:
db2 drop procedure SCHEMA.PROCEDURENAME
DB21034E The command was processed as an SQL statement because it was not valid Command Line Processor command. During SQL processing it returned: SQL0476N Reference to routine "SCHEMA.PROCEDURENAME" was made without a signature, but the routine is not unique in its schema. SQLSTATE=42725
CAUSE
The error is returned because the stored procedure is overloaded and therefore the procedure is not unique in that schema. To drop the procedure you must specify the data types that were specified on the CREATE PROCEDURE statement or use the stored procedure's specific name per the examples below.
SOLUTION
In order to drop an overloaded stored procedure you can use either of the following statements:
db2 "DROP PROCEDURE procedure-name(int, varchar(12))"
db2 "DROP SPECIFIC PROCEDURE specific-name"
Note: The specific-name can be identified by selecting the SPECIFICNAME column from syscat.routines catalog view.
A procedure can be dropped like:
DROP PROCEDURE INORUP RESTRICT;
The parameter RESTRICT is required. It avoids dropping a procedure used by a trigger. The procedure package is dropped.
Packages and plans calling the procedure are invalidated.
I am new to Oracle Sql and facing an issue :
I want to create a temporary table inside procedure .
LIKE:
CREATE PROCEDURE P
AS
BEGIN
CREATE TEMPORARY TABLE A(ID int);
END P;
BUT THIS IS GIVING ME AN ERROR
How Can I Create a temporary table inside procedure.
I have seen other answers on stackoverflow but that doesn't answer my question properly
Can you please help me out ?
Why do you want to create a temporary table in a stored procedure in the first place?
It is relatively common to create temporary tables in other databases (SQL Server and MySQL, for example). It is very, very rare to do the same thing in Oracle. In almost every case where you are tempted to create a temporary table in Oracle, there is a better architectural approach. There is a thread over on the DBA stack that discusses alternatives to temporary tables and why they are not commonly needed in Oracle.
Programmatically, you can create objects using dynamic SQL
CREATE OR REPLACE PROCEDURE dont_do_this
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE a( id INTEGER )';
END;
If you create a temporary table dynamically, however, every reference to that table will also need to be via dynamic SQL-- you won't be able to write simple SELECT statements against the table. And the definition of a temporary table in Oracle is global so it is visible to every session. If you have two different sessions both trying to create the same table, the second session will get an error. If you expect the table to have a different definition in different sessions, you've got even more problems.
You could use Dynamic SQL with EXECUTE IMMEDIATE:
CREATE OR REPLACE
PROCEDURE p
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE TEMPORARY TABLE A(id NUMBER)...etc';
END p;
Edit: Obviously you'll have to ensure your syntax is correct within the EXECUTE IMMEDIATE statement.
Hope it helps.
You must declare your procedure as:
create or replace PROCEDURE MYPROCEDURE AUTHID CURRENT_USER IS
script varchar(4000);
BEGIN
script:= 'CREATE GLOBAL TEMPORARY TABLE BNMCODIAGNOSTICASSOCIE_TEMP
ON COMMIT PRESERVE ROWS
as select ........';
EXECUTE IMMEDIATE script;
commit;
END;