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 '.
Related
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.
I am trying to create a procedure to dump out specific data from few tables:
CREATE OR REPLACE PROCEDURE Lab9_View IS
--declare the variable
o_Id orders.OrderID%type;
o_date orders.orderdate%type;
s_date orders.shippeddate%type;
c_name customers.companyname%type;
s_country orders.shippeddate%type;
--define CURSOR for select
CURSOR Lab9_View IS
SELECT OrderId, OrderDate, ShippedDate, CompanyName, ShipCountry
FROM Orders JOIN Customers ON
customers.customerid = orders.CustomerId WHERE ORDERDATE BETWEEN '2019-08-14' AND '2019-08-23';
--exceution begin here
BEGIN
--heading line
dbms_output.put_line(' Harry''s Lab9 - Orders by COuntry Aug. 14th-23rd ');
dbms_output.put_line(' Order #' || ' '|| ' Order Date' || ' ' || 'Shipped Date' || " " || 'Company Name' || ' ' || 'Ship Country');
--execute the select
OPEN Lab9_View;
--retrieve each row from result in loop
LOOP
FETCH Lab9_View into o_id, o_date, s_date, c_name, s_country;
--end of result reach
EXIT WHEN Lab9_View%notfound;
--dump out data
dbms_output.put_line(o_id || ' '|| o_date || ' ' || s_date || " " || c_name || ' ' || s_country);
END LOOP;
--close cursor
CLOSE Lab9_View;
END;
I keep on getting this error:
ORA-24344: success with compilation error
ORA-06512: at "SYS.WWV_DBMS_SQL_APEX_200100", line 581
ORA-06512: at "SYS.DBMS_SYS_SQL", line 1658
ORA-06512: at "SYS.WWV_DBMS_SQL_APEX_200100", line 567
ORA-06512: at "APEX_200100.WWV_FLOW_DYNAMIC_EXEC", line 2127
3. o_Id orders.OrderID%type;
4. o_date orders.orderdate%type;
5. s_date orders.shippeddate%type;
6. c_name customers.companyname%type;
7. s_country orders.shippeddate%type;
I can't spot anything different from my professor's lab notes. Can anyone see anything wrong with my code?
Thank you
You have double quotes instead of single quotes between two of the columns in your put_line commands.
(Just to preempt - I know how hacky and flawed this approach is. It's just going to be a personal use thing to make a certain task easier.)
For this example, I want to create two dynamic SQL insert statements which insert the first two results from ALL_TABLES into GT_DUMMY, padded with an input value.
CREATE GLOBAL TEMPORARY TABLE GT_DUMMY
( Test_Field VARCHAR(100)
);
CREATE OR REPLACE PROCEDURE LOAD_GT_DUMMY
( Insert_String VARCHAR
)
IS
BEGIN
FOR col IN
( SELECT 'INSERT INTO GT_DUMMY VALUES(' || CHR(39) || Insert_String || Table_Name || CHR(39) || ');' AS insertStatement
FROM ALL_TABLES
WHERE ROWNUM <= 2
) LOOP
DBMS_OUTPUT.put_line(col.insertStatement);
-- Result of EXEC LOAD_GT_DUMMY('SOMETHING'); :
-- INSERT INTO GT_DUMMY VALUES('SOMETHINGDUAL');
-- INSERT INTO GT_DUMMY VALUES('SOMETHINGSYSTEM_PRIVILEGE_MAP');
-- This command fails when
EXECUTE IMMEDIATE col.insertStatement;
END LOOP;
END;
The inserts are well formed and will execute if I just run them standalone, but the EXECUTE IMMEDIATE col.insertStatement; command is not working. The procedure compiles, but when I try to run
EXEC LOAD_GT_DUMMY('SOMETHING');
I get an error
ORA-00933: SQL command not properly ended
ORA-06512: at "MY_SCHEMA.LOAD_GT_DUMMY", line 14
ORA-06512: at line 1
Any thoughts? Is my syntax off?
Best.
Remove the terminating semi-colon; dynamic SQL doesn't like it.
SELECT 'INSERT INTO GT_DUMMY VALU... <snip> ... || CHR(39) || ');'
^
|
here
Try with INTO v_result in the end of EXECUTE statement
EXECUTE IMMEDIATE col.insertStatement INTO v_result;
P.S. don't forget to declare v_result variable
You can check similar example down here
Remove the colon in sql statement and execute it will work
FOR col IN
( SELECT 'INSERT INTO GT_DUMMY VALUES(' || CHR(39) || Insert_String || Table_Name || CHR(39) || ')' AS insertStatement
FROM ALL_TABLES
WHERE ROWNUM <= 2
) LOOP
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.