Using Alter Statement from a Table in oracle - sql

I have a table like having one column containing this data
Dummy Column
Alter PACKAGE ABC COMPILE;
Alter PACKAGE CDE COMPILE;
Alter PROCEDURE ABC COMPILE;
Alter TRIGGER ABC COMPILE;
I want to make a script such that when i run that it will execute the alter statements line by line and perform the DDL operations.

Something like this should work, obviously assuming you have real DDL statements stored in that dummy column.
for loop over the column when the value is not null
replace the ; by nothing in order to use execute immediate
Example
declare
vsql table.dummy_column%type;
begin
for h in ( select dummy_column from table where dummy_column is not null )
loop
vsql := replace(h.dummy_column,';','');
execute immediate vsql;
end loop;
end;
/

Related

TEMP table in stored procedure oracle 11g

Is there any way to create a temp table with the stored procedure and use the same in the ref cursor in the same stored procedure.
I wrote something like below, it's not working....
CREATE OR REPLACE PROCEDURE USP_TEST(
CUR_QUOTE OUT SYS_REFCURSOR) AS
BEGIN
CREATE GLOBAL TEMPORARY TABLE users1 ON COMMIT PRESERVE ROWS
AS
SELECT 'rb#bot.com' FROM DUAL;
OPEN CUR_QUOTE FOR
SELECT DISTINCT CREATEDBY
FROM QUOTE
WHERE TRUNC(DATEOFENQUIRY)=TRUNC(SYSDATE-1) AND CREATEDBY = users1.EMAIL;
END;
And delete the temp table at the end.
Please suggest with some sample code...
Keep coding :)
If you drop the table then the cursor is invalidated.
From 18c you can use private temporary tables:
create or replace procedure usp_test
( cur_quote out sys_refcursor )
as
begin
execute immediate
'create private temporary table ora$ptt_demo' ||chr(10)||
'on commit drop definition as' ||chr(10)||
'select sysdate -1 as dateofenquiry, ''rb#bot.com'' as createdby' ||chr(10)||
'from dual';
open cur_quote for
'select distinct createdby from ora$ptt_demo where trunc(dateofenquiry) = trunc(sysdate - 1)';
end;
Note that the table name must have the prefix defined by the PRIVATE_TEMP_TABLE_PREFIX parameter (default ORA$PTT_), and you must commit before calling the procedure a second time.

Oracle procedure/function to create a trigger in table

I'm trying to create a procedure that given a table name, it will create a sequence and auto incrementing trigger, all using variables based on the table name.
Code :
CREATE OR REPLACE procedure CREATE_SEQUENTIAL_TR(table_name VARCHAR)
is -- Tried using declare but it wouldn't accept
coluna_cod varchar(100 char);
begin
--Finding the cod column name for this table first
--They start with "PK_CD"
select
COLUMN_NAME
into
coluna_cod
from
ALL_TAB_COLUMNS
where
TABLE_NAME=table_name
and COLUMN_NAME like "PK_CD%";
--Creating the sequence obj
drop sequence "cod" || table_name;
create sequence "cod" || table_name;
--Now creating the trigger
create or replace trigger "cod" || table_name || "tr"
before
UPDATE or INSERT on table_name
for each row
declare
cod number := coluna_cod;
tr_name varchar(100 char) := "cod" || table_name
begin
if UPDATING then
if :new.cod != :old.cod then
:new.cod := :old.cod;
end if;
else -- inserting
:new.cod := tr_name.nextval();
end if;
end;
end;
The complexity of this ended up quite out of the scope of my knowledge.
At the moment it is giving an error on drop sequence "cod" || table_name (Unexpected DROP symbol found) but I'm sure I have made other errors.
Can someone help me figure this logic out?
You can't put DDL statements (like drop or create or alter) directly inside a PL/SQL block. If you want to do DDL inside PL/SQL, you can do an execute immediate:
declare
begin
drop sequence X; -- error
execute immediate 'drop sequence X'; -- works fine
end;
/

Netteza SQL ALTER TABLE in stored procedure alternative?

I want to alter a table within a For loop in Netteza SQL. I know that Netteza does not allow alter table in a stored procedure. As quoted:
"These SQL commands are also prohibited within the body of a Netezza stored procedure."
Are there any alternatives for doing so? I am a beginner in Netteza. I also don't know if my loop format is correct?
CREATE OR REPLACE PROCEDURE "SP_Automate_Table"()
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
vSQL1 varchar(30000) ;
BEGIN
FOR i in 2011..2014
LOOP
For j in 1..12
Loop
call "SP_Count"(i, j);
vSQL1:='alter table X add columnX INT';
....
...
..
EXECUTE immediate vSQL1;
END LOOP;
END LOOP;
END;
END_PROC;
Starting with v7.1 you can declare an AUTOCOMMIT ON block in a stored procedure, and in this block you can call statements that would otherwise be prohibited within a stored procedure.
CREATE OR REPLACE PROCEDURE ADMIN.SP_ALTER_LOOP(INTEGER, INTEGER)
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
pStartVal ALIAS FOR $1;
pCount ALIAS FOR $2;
vSQL varchar(30000);
BEGIN
BEGIN AUTOCOMMIT ON
for i in 1 .. pCount LOOP
vSQL := 'ALTER TABLE CLAIM_' || pStartVal + i-1 || ' ADD COLUMN (COL2 BIGINT);';
EXECUTE IMMEDIATE vSQL;
END LOOP;
END;
END;
END_PROC;
Prior to v7.1, I don't know of a way you can alter a table structure from with a stored procedure.
Note that in the general case of ALTER TABLE (whether scripted like this or manual), be sure to perform a groom of each altered table after the ALTER operation.
GROOM TABLE tablename VERSIONS;
Your loop statement is syntactically correct, but there is no way to issue alter statements from within nzplsql.
I would suggest doing a bash script as an alternative, repeatedly calling nzsql.
for i in $(seq 2011 2014); do
for j in $(seq 1 12); do
nzsql -c "call \"SP_Count\"($i, $j);"
nzsql -c "alter table X add columnX INT;"
done
done
I can't really imagine a use case where you'd want to dynamically add columns by calling a stored procedure from within a database that couldn't also be covered by doing it outside the database.

How to create a table inside of a procedure in Oracle?

I want to create a table inside of a procedure. I tried to put the create query in a string then execute immediate the string. For example:
create or replace procedure hr.temp is
var1 varchar2(4000);
begin
var1:='create table hr.temp(
id number)';
execute immediate var1;
end temp;
But when I execute this procedure I get the error:
ORA-00911: invalid character
ORA-06512: at "SYS.TEMP", line 6
.
.
.
Is there any way I can do this?
Try this. It should work...
create or replace procedure hr.temp is
var1 varchar2(4000);
BEGIN
var1:='create table hr.temp2(
id number)';
EXECUTE IMMEDIATE var1;
end temp;
the answer of m.r 'a_horse_with_no_name' is right. The first point is I should not create a table in sys schema.
The second point is in a dynamic sql I should not use ; character in dynamic sql.

Ora-04072: INVALID TRIGGER TYPE

I'm trying to execute the following SQL statement on Oracle 11g. I'm not experienced when it comes to Oracle and I'm not sure why this is failing. This query was provided to me by our developer.
I was attempting to execute this through the SQL worksheet in OEM.
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG BEFORE
INSERT OR UPDATE ON tbl_AdminCommands FOR EACH ROW
BEGIN
IF inserting
AND :new.ADMINCOMMANDID IS NULL THEN
SELECT TBL_ADMINCOMMANDS_SEQ.nextval INTO :new.ADMINCOMMANDID FROM DUAL;
END IF;
END;
ALTER TRIGGER TBL_ADMINCOMMAND_TRG ENABLE;
The code you show works for me, but only as two separate commands:
1)
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG BEFORE
INSERT OR UPDATE ON tbl_AdminCommands FOR EACH ROW
BEGIN
IF inserting
AND :new.ADMINCOMMANDID IS NULL THEN
SELECT TBL_ADMINCOMMANDS_SEQ.nextval INTO :new.ADMINCOMMANDID FROM DUAL;
END IF;
END;
2)
ALTER TRIGGER TBL_ADMINCOMMAND_TRG ENABLE;
Try doing them one at a time.
As an aside, this line:
SELECT TBL_ADMINCOMMANDS_SEQ.nextval INTO :new.ADMINCOMMANDID FROM DUAL;
can be simplified to this in 11G:
:new.ADMINCOMMANDID := TBL_ADMINCOMMANDS_SEQ.nextval;
In fact, the whole trigger can be simplified to:
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG
BEFORE INSERT ON tbl_AdminCommands
FOR EACH ROW
WHEN (NEW.ADMINCOMMANDID IS NULL)
BEGIN
:new.ADMINCOMMANDID := TBL_ADMINCOMMANDS_SEQ.nextval;
END;
If you are using SQL*Plus, you should end your PL/SQL commands with a single forward slash on a line by itself:
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG
BEFORE INSERT OR UPDATE ON tbl_AdminCommands
FOR EACH ROW
BEGIN
IF inserting AND :new.ADMINCOMMANDID IS NULL
THEN
SELECT TBL_ADMINCOMMANDS_SEQ.nextval
INTO :new.ADMINCOMMANDID
FROM DUAL;
END IF;
END;
/
ALTER TRIGGER TBL_ADMINCOMMAND_TRG ENABLE;
Also note that if your trigger uses IF inserting you could do only a trigger BEFORE INSERT.