I just want to add column using execute immediate but I am getting an error. Please let me know the this PL/SQL block is correct or not?
create or replace procedure add_column (xyz in varchar2, abc in varchar2) is
begin
EXECUTE IMMEDIATE 'alter table ' || 'xyz add abc varchar2(20)';
dbms_output.put_line('New column added');
end;
exec add_column ('students', 'time');
error: Error starting at line : 8 in command -
BEGIN add_column ('students', 'time'); END;
ORA-00942: table or view does not exist
ORA-06512: at "HR.ADD_COLUMN", line 4
ORA-06512: at line 1
You need to use string concatanation as:
EXECUTE IMMEDIATE 'alter table ' || xyz || ' add ' || abc || ' varchar2(20)';
Also, DBMS_ASSERT can be used to check for the valid names of the table and column as follows.
EXECUTE IMMEDIATE 'alter table ' || sys.DBMS_ASSERT.SQL_OBJECT_NAME(xyz)
|| ' add ' || sys.DBMS_ASSERT.SQL_OBJECT_NAME(abc) || ' varchar2(20)';
Here, xyz and abc will be replaced with the input parameter names.
Related
I want to create ddl trigger(on create) which will create a dml trigger
But i have error:
ORA-06512: на line 8
00604. 00000 - "error occurred at recursive SQL level %s"
*Cause: An error occurred while processing a recursive SQL statement
(a statement applying to internal dictionary tables).
*Action: If the situation described in the next error on the stack
can be corrected, do so; otherwise contact Oracle Support.
CREATE OR REPLACE TRIGGER test_ddl
after CREATE ON SCHEMA
DECLARE
user_col VARCHAR(5) := 'user_';
time_col VARCHAR(5) := 'time_';
BEGIN
IF ora_dict_obj_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'alter table ' || ora_dict_obj_name || ' add(' || user_col || ' varchar(20), '|| time_col ||' timestamp)'||'';
EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER add_user_time BEFORE INSERT OR UPDATE ON test_tab FOR EACH ROW BEGIN ' || ':' || 'new.time_ := sysdate; END';
END IF;
END;
/
DROP TABLE test_tab PURGE;
/
CREATE TABLE test_tab(ID NUMBER);
At the very least, I expect you want new.time_ to be :new.time_
You are missing a semicolon after the END.
Replace this
EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER add_user_time BEFORE INSERT OR UPDATE ON test_tab FOR EACH ROW BEGIN ' || ':' || 'new.time_ := sysdate; END';
with that
EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER add_user_time BEFORE INSERT OR UPDATE ON test_tab FOR EACH ROW BEGIN ' || ':' || 'new.time_ := sysdate; END;';
Full error messages are:
ORA-00604: error occurred at recursive SQL level 1
ORA-24344: success with compilation error
ORA-06512: at line 8
Important part was:
ORA-24344: success with compilation error
The source code should read:
CREATE OR REPLACE TRIGGER test_ddl
after CREATE ON SCHEMA
DECLARE
user_col VARCHAR(5) := 'user_';
time_col VARCHAR(5) := 'time_';
BEGIN
IF ora_dict_obj_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'alter table ' || ora_dict_obj_name || ' add(' || user_col || ' varchar(20), '|| time_col ||' timestamp)'||'';
EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER add_user_time BEFORE INSERT OR UPDATE ON test_tab FOR EACH ROW BEGIN ' || ':' || 'new.time_ := sysdate; END;';
END IF;
END;
/
DROP TABLE test_tab PURGE;
/
CREATE TABLE test_tab(ID NUMBER);
Just as an explanation: I have put some log messages to see where it exactly fails. Then you can see that the trigger is recursively called upon the CREATE OR REPLACE TRIGGER but with an ora_dict_obj_type = TRIGGER
I'm trying to create a procedure which gives grants to specific schema objects. Procedure seems to compile ok, but it gives an error when execution.
Something is wrong in this simple procedure but I cannot find the reason for this.
Procedure:
create or replace procedure ch.grants_to_schema_objects(
i_target_schema varchar2,
i_target_user varchar2) as
begin
for mt in (SELECT 'GRANT SELECT ON ' || chr(39)
|| i_target_schema || chr(39)
|| '.' || TABLE_NAME || ' TO ' || chr(39)
|| i_target_user || chr(39)
|| ' WITH GRANT OPTION' as grnt
FROM ALL_TABLES
WHERE OWNER = i_target_schema) loop
dbms_output.put_line(mt.grnt);
execute immediate mt.grnt;
end loop;
end;
call:
execute ch.grants_to_schema_objects('SR', 'CH');
Error:
ORA-06512: "CH.GRANTS_TO_SCHEMA_OBJECTS", line 5
ORA-06512: line 1
00903. 00000 - "invalid table name"
*Cause:
*Action:
The CHR(39) is breaking it. Replace it whit CHR(34): it is " you need to separate your username, not '.
Hi there I am trying to build a function to reset a sequence to synch with table ID's which have gotten out of synch with the sequence. Function is as follows:
create or replace
FUNCTION P_FNC_SEQUENCERESET(sourceTable IN VARCHAR2, idField IN VARCHAR2, seqname VARCHAR2) RETURN NUMBER
IS
ln NUMBER;
ib NUMBER;
maxId NUMBER;
newValue NUMBER;
diffValue NUMBER;
interimValue NUMBER;
sqlStmt VARCHAR2(2000);
BEGIN
-- Get the maximum of the id field
EXECUTE IMMEDIATE 'SELECT MAX(' || idField || ') INTO ' || maxId || ' FROM ' || sourceTable;
...code continues...
My understanding of the EXECUTE IMMEDIATE statement leads me to believe that this should be possible, however when executed I get this error:
ORA-00936: missing expression
ORA-06512: at "PSALERT_ADMIN.P_FNC_SEQUENCERESET", line 16
ORA-06512: at line 11
It would need to look something like this:
EXECUTE IMMEDIATE 'SELECT ' || idField ||' FROM ' || sourceTable into maxid;
the keyword "into" is not part of the string that is dynamically executed, but it is part of the syntax of the "execute immediate" statement
https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm
I am trying to create a helper stored proc to save on repeated code.
I wrote the following stored procedure that takes the table name, status_id, and ROWID.
PROCEDURE sp_update_stage_status(p_table_name IN VARCHAR2,
p_status_id IN NUMBER,
p_rowid IN ROWID)
AS
BEGIN
execute immediate 'UPDATE ' || p_table_name
|| ' SET STATUS_ID = ' || p_status_id
|| ' WHERE ROWID = ' || p_rowid;
END;
However whenever I execute it I get the following.
ORA-00904: "AAATQEAAEAAAAHEAAB": invalid identifier
ORA-06512: at "OBR_DEV.PKG_COMMON", line 32
ORA-06512: at "OBR_DEV.PKG_DIRECTORY", line 449
What am I doing wrong here?
You're dropping the contents of rowid in directly without quoting it.
Your query became WHERE ROWID = AAATQEAAEAAAAHEAAB which is comparing the rowid column to the AAATQEAAEAAAAHEAAB column.
It should be WHERE ROWID = 'AAATQEAAEAAAAHEAAB'. Add some quotes to your dynamic SQL and you should be okay.
Or better yet, use bind variables and don't worry about quoting:
EXECUTE IMMEDIATE
'UPDATE ' || p_table_name || ' SET status_id = :status WHERE rowid = :seek_rowid'
USING p_status_id, p_rowid;
You are declaring p_rowid as rowid type, you must declare p_rowid as varchar2(18).
PROCEDURE sp_update_stage_status(
p_table_name IN VARCHAR2,
p_status_id IN NUMBER,
p_rowid IN VARCHAR2(18)
) AS
BEGIN
execute immediate 'UPDATE ' || p_table_name || ' SET STATUS_ID = ' || p_status_id || ' WHERE ROWID = ' || p_rowid;
END;
I'm trying to create a generic procedure to synchronize sequences.
I want to call the procedure and pass name of table, column and sequence but my procedure won't run due to an error.
Procedure:
CREATE OR REPLACE PROCEDURE INCREMENT_SEQ(table_name in varchar2 , id_column in varchar2 , sequence_name in varchar2)
AS
current_value number;
seq_val number := -1;
begin
EXECUTE IMMEDIATE 'select max(' || table_name || '.' || id_column || ') into current_value from ' || table_name ;
WHILE current_value >= seq_val
LOOP
EXECUTE IMMEDIATE 'select ' || sequence_name || '.nextval into seq_val from dual';
end loop;
end;
when I run the script I'm having the following error:
Error at line 2
ORA-00905: missing keyword
ORA-06512: at "TGC100_DEV.INCREMENT_SEQ", line 6
ORA-06512: at line 1
Script Terminated on line 16.
But I have no idea how to solve. Any advice would be helpfull.
You should put INTO clause outside the query:
CREATE OR REPLACE PROCEDURE INCREMENT_SEQ(table_name in varchar2 , id_column in varchar2 , sequence_name in varchar2)
AS
current_value number;
seq_val number := -1;
begin
EXECUTE IMMEDIATE 'select max(' || table_name || '.' || id_column || ') from ' || table_name into current_value;
WHILE current_value >= seq_val
LOOP
EXECUTE IMMEDIATE 'select ' || sequence_name || '.nextval from dual' into seq_val;
end loop;
end;
EXECUTE IMMEDIATE 'select max(' || table_name || '.' || id_column || ') into current_value from ' || table_name ;
It is syntactically incorrect. The INTO clause should be outside of EXECUTE IMMEDIATE statement.
Something like,
EXECUTE IMMEDIATE 'your SQL statement' INTO variable USING value;
UPDATE It is better to have the dynamic SQL as a variable to avoid confusions with so many single quotes and concatenation in the EXECUTE IMMEDIATE statement itself.
The other answer by Aramilo was posted before my answer, but I got confused to see the INTO clause already outside the statement.
For developers, it is always a good practice to first check the dynamic SQL using DBMS OUTPUT before actually executing it. Thus, it saves a lot of time to debug the whole bunch of PL/SQL code. Once confirmed that the dynamic SQL formed is correct, remove the DBMS_OUTPUT and execute the PL/SQL code.