Q? Correct way to EXECUTE IMMEDIATE DDL
Hi All,
So I'm a little surprised to find that there isn't a builtin feature to "ALTER TABLE x DISABLE ALL CONSTRAINTS". So I'm trying to write a procedure that does that:
procedure change_local_constraints(p_tablename USER_TABLES.TABLE_NAME%TYPE,
p_desired_status status_t,
p_exception_clause exception_t DEFAULT NULL) as
begin
<<table_constraints>>
FOR constraint_rec IN (SELECT constraint_name
FROM user_constraints
WHERE table_name = p_tablename
AND status <> p_desired_status) LOOP
execute immediate 'ALTER TABLE :i_table :i_status CONSTRAINT :i_constraint :i_exception_clause'
using p_tablename, p_desired_status, constraint_rec.constraint_name, p_exception_clause;
END LOOP table_constraints;
end change_local_constraints;
Note: that I've defined a couple of subtypes earlier in my package:
SUBTYPE status_t IS VARCHAR2(10);
SUBTYPE exception_t IS VARCHAR2(100);
Note: the exception parameter is for an " EXCEPTIONS INTO MY_EXCEPTION_TABLE " clause.
When I try to run this I get an error:
ORA-00903: invalid table name
I don't want to concatenate my SQL command together as that opens everything up to SQL Injection attacks. On the other hand, it appears that bind variables can't be used in this situation. Or perhaps in any DDL. Does anyone know of a way to do this or see an error in my code?
Thanks,
Steven
1- Concatenating table and constraint name in your code is not going to pose any risk, becuase if table name is incorrect like 'XYZ; DROP TABLE T;' (fear of intejection), for loop will never execute. And your constraint name is coming from the loop.
2- For p_desired_status you can verify before EXECUTE IMMEDIATE that it contains appropriate keyword only:
IF p_desired_status NOT IN('ENABLE','DIABLE') THEN
raise_application_error(-20100,'Invalid syntax');
END IF;
3- EXCEPTIONS INTO MY_EXCEPTION_TABLE will always be there, so there's no need to accept it in a parameter. And if it does not always have to be there, you can treat it like p_desired_status.
Anwar
Similar Messages
-
Problem wile EXECUTE IMMEDIATE DDL statement in procedure
Hi ,
This is my procedure and it's getting compiled but while executing procedure getting this error,
can anyone please tell me how to fix this?
create or replace procedure construct_Table (name_table IN VARCHAR2)
IS
v_tab_name varchar2(40):=NULL;
v_sql_Stmt varchar2(32767) := NULL;
finalquery varchar2(32767) :=NULL;
cursor tp is
select COLUMN_NAME,DATA_TYPE,DATA_PRECISION,CHAR_LENGTH from all_tab_cols where table_name=name_table;
BEGIN
begin
select TABLE_NAME into v_tab_name from user_tables where table_name=name_table;
EXCEPTION
WHEN no_Data_found
THEN
DBMS_OUTPUT.PUT_LINE('No such table exist');
end;
if(v_tab_name IS NOT NULL)then
finalquery := 'CREATE TABLE '||v_tab_name||'_DUMMY (';
FOR I IN tp LOOP
if(I.data_type='VARCHAR2') then
v_sql_stmt := finalquery ||I.column_name||' '||I.data_type||'('||I.char_length||') ';
elsif(I.data_type='NUMBER') then
v_sql_stmt := finalquery ||I.column_name||' '||I.data_type||'('||I.DATA_PRECISION ||') ';
else
v_sql_stmt := finalquery ||I.column_name||' '||I.data_type ;
end if;
finalquery := v_sql_stmt || ',';
END LOOP;
finalquery := SUBSTR(finalquery,1,LENGTH(finalquery) - 1)||')';
dbms_output.put_line(finalquery);
EXECUTE IMMEDIATE'grant create any table to cmsuser';
EXECUTE IMMEDIATE finalquery;
end if;
END;
/This is the error I am getting
Error starting at line 1 in command:
begin
construct_Table ('EMP');
end;
Error report:
ORA-01031: insufficient privileges
ORA-06512: at "CMSUSER.CONSTRUCT_TABLE", line 30
ORA-06512: at line 2
01031. 00000 - "insufficient privileges"
*Cause: An attempt was made to change the current username or password
without the appropriate privilege. This error also occurs if
attempting to install a database without the necessary operating
system privileges.
When Trusted Oracle is configure in DBMS MAC, this error may occur
if the user was granted the necessary privilege at a higher label
than the current login.
*Action: Ask the database administrator to perform the operation or grant
the required privileges.
For Trusted Oracle users getting this error although granted the
the appropriate privilege at a higher label, ask the database
administrator to regrant the privilege at the appropriate label.Thanks ,
Deekay.Deekay,
If you grant create table privilege and create table in the same procedure, then how you will differentiate that which user you granted the privilege and in which schema, you are creating the table. Here, you are granting to "cmuser", but in the same schema, you are creating the table also. How can a user grant privilege to himself?
Login as DBA, grant create any table privilege to "cmuser" from dba. Then, you can execute you procedure in "cmuser" schema. -
What is the best way to execute immediate particular sql stored in a table
I have a string variable containing row_ids eg "12,24,35,23"
and a table
row_id, sql
1 , "insert into some_table values(23,'Happy');"
6 , "insert into some_other_table values(24,'Sad');"
12 , "insert into some_table values(23,'Crazzzy');"
15 , "insert into some_other_table values(23,'Old');"
23 , "insert into another_table values(23,'Left');"
24 , "insert into stuff_table values(23,'Gold');"
30 , "insert into old_table values(23,'Even');"
35 , "insert into archive_table values(23,"True");"
And I need to write a plsql function that takes the list of row_ids as an argument and executes the sql statements stored in the table that matches.
I am trying a combination of cursor and execute immediate statements to do it at the moment but suspect I am being very inefficient. So any suggestions or examples of similar code anyone knows about would be hugely appreciated.
Cheers
ReubenNot sure why anyone would be doing such a thing as storing their SQL in a table and wanting to dynamically execute it (generally this is bad practice), but if you must...
SQL> select * from testdata;
SQL_ID SQL_TEXT
1 insert into some_table values(23,'Happy');
6 insert into some_other_table values(24,'Sad');
12 insert into some_table values(23,'Crazzzy');
15 insert into some_other_table values(23,'Old');
23 insert into another_table values(23,'Left');
24 insert into stuff_table values(23,'Gold');
30 insert into old_table values(23,'Even');
35 insert into archive_table values(23,'True');
8 rows selected.
SQL> set serverout on
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 v_ids VARCHAR2(4000) := '12,24,35,23';
3 CURSOR cur_fetch IS
4 SELECT sql_text
5 FROM testdata
6 WHERE sql_id IN (SELECT TO_NUMBER(REGEXP_SUBSTR (v_ids, '[^,]+', 1, rownum))
7 FROM DUAL
8 CONNECT BY ROWNUM <= length(regexp_replace(v_ids,'[^,]*'))+1);
9 BEGIN
10 FOR s IN cur_fetch
11 LOOP
12 DBMS_OUTPUT.PUT_LINE(s.sql_text); -- For demo purposes show the sql text
13 -- EXECUTE IMMEDIATE s.sql_text; -- In reality, uncomment this to execute the sql text
14 END LOOP;
15* END;
16 /
insert into some_table values(23,'Crazzzy');
insert into another_table values(23,'Left');
insert into stuff_table values(23,'Gold');
insert into archive_table values(23,'True');
PL/SQL procedure successfully completed.
SQL> -
Can someone explain the reason for why oracle doesnt allow DDL statements to be executed directly in a PL/SQL block?
DDL statements execute an implicit commit before the statement is executed, and the statement itself is also automatically committed.
A pl/sql procedure typically should comprise one logical unit of work.
Both executing DDL and committing every individual record must be considered extreemly poor practice, resulting from brainwashing by the Evil Empire, aka Microsoft, where this is required because the concurrency model is completely different (and unelegant).
So, if you want to stop being a Ringwraith of Sauron, aka William H Gates III, or his amanuensis Saruman, aka Stephen Ballmer, please never ever issue DDL through a stored procedure.
Sybrand Bakker
Senior Oracle DBA -
ORA-14552: cannot perform a DDL in a execute immediate - proc
Hi All,
I am trying to disable triggers in a stored procedure:
PROCEDURE Alter_trigger_DISBALE
IS
BEGIN
execute immediate ('alter trigger BEI_INS_MY DISABLE');
END;
I get the following error:
ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML
Is there a solution for this problem ?
Best Regards
FriedholdHow are you calling the procedure?
I assume that, since your procedure actually compiles, it doesn't have the parenthesis around the EXCEUTE IMMEDIATE string and that there is a CREATE before the PROCEDURE. I hope that "disable" is spelled correctly in the real thing.
Justin
Distributed Database Consulting, Inc.
http://www.ddbcinc.com/askDDBC -
Execute immediate on DDL command
Below sample SQL is 1 of the many code that is running OK in our database. And this code has causes a lot of latch contention to our database and it's being called so many times that cause hard parse.
/* test code */
CREATE OR REPLACE PROCEDURE dsal (p_client_id NUMBER) IS
BEGIN
EXECUTE IMMEDIATE
'create table tmp_dsal_'||p_client_id
' (client_id number, '||
' trade_id number, '||
' ps_id number, '||
' ps_liquid varchar2(2), '||
' status_code varchar2(3) default ''NA'' not null, '||
' start_value_dte date, '||
' end_value_dte date)';
EXECUTE IMMEDIATE 'drop table tmp_dsal_'||p_client_id;
END;
I want to improve it by using bind variable. The below program compile with no error.
CREATE OR REPLACE PROCEDURE dsal (p_client_id NUMBER) IS
BEGIN
EXECUTE IMMEDIATE
'create table tmp_dsal_:client_id'||
' (client_id number, '||
' trade_id number, '||
' ps_id number, '||
' ps_liquid varchar2(2), '||
' status_code varchar2(3) default ''NA'' not null, '||
' start_value_dte date, '||
' end_value_dte date)' using p_client_id;
EXECUTE IMMEDIATE 'drop table tmp_dsal_:client_id' using p_client_id;
END;
When I execute it, I'm getting the below error. I understand DML statement using bind variable in execute immediate command but not sure on DDL. Is there a workaround on issue or this is limitation?
SQL> exec dsal(223);
BEGIN dsal(223); END;
ERROR at line 1:
ORA-00922: missing or invalid option
ORA-06512: at "SYS.DSAL", line 3
ORA-06512: at line 1
Appreciate any comment/help. ThanksAssuming that all of the client load processes run in seperate session, then do this once in the database and use this global temporary table for the loads. A GTT is a permanent object in the database, but the data it contains is only visible to the session that inserts it. Multiple sessions can access the same GTT at the same time, and will never see each other's data.
CREATE TEMPORARY TABLE tmp_dsal (
client_id NUMBER,
trade_id NUMBER,
ps_id NUMBER,
ps_liquid VARCHAR2(2),
status_code VARCHAR2(3) DEFAULT 'NA' NOT NULL,
start_value_dte DATE,
end_value_dte DATE)
ON COMMIT [PRESERVE|DELETE] ROWSThe on commit clause determines what happens to the data in the GTT when the session that created the data issues a commit. DELETE will automaticall delete all of that session's data while PRESERVE will keep the data until the session either explicitly deletes it or the session ends.
John -
Problems using DDL & EXECUTE IMMEDIATE in package
Hi...
I have an 8i package in which I am trying to execute some DDL via EXECUTE IMMEDIATE to create temporary tables from which I then populate a REF_CURSOR by selecting from the last table created in the DDL. The problem is that the compiler doesn't seem to like the DDL.
Here's what I'm using:
CREATE OR REPLACE PACKAGE BODY NEREP_REF
AS
Procedure GetNE_REF (
i_Node IN VARCHAR2,
io_cursor IN OUT t_cursor )
IS
sql_stmt varchar2(200);
v_cursor t_cursor;
BEGIN
sql_stmt := 'CREATE TABLE tmp AS SELECT * FROM nerep4;';
EXECUTE IMMEDIATE sql_stmt;
OPEN v_cursor FOR
SELECT NE_Node, NE_Type, EHA, Status, Curr_Func, TP_Name,
Order_Item_Name, Required_Start, Required_End, Trail_Name
FROM tmp
WHERE NE_Node = i_Node ;
io_cursor := v_cursor;
END GetNE_REF;
END NEREP_REF;
The problem is that when I compile the package I get the errors below:
SQL> @sp_nerep_body
Warning: Package Body created with compilation errors.
SQL> show err
Errors for PACKAGE BODY NEREP_REF:
LINE/COL ERROR
20/7 PL/SQL: SQL Statement ignored
23/14 PLS-00201: identifier 'NE_NODE' must be declared
So it seems that it doesn't like the DDL (have I got the sql_stmt assignment in the wrong place maybe?) and then it complains it can't find the columns, which is reasonable because of course it doesn't know that the table 'tmp' comes from the result of the DDL statement!
If I change the table name in the 'OPEN v_cursor FOR' select clause to a table that already exists (ie: not created in this package) it runs just fine and I get the data I asked for... the problem is that I need to create this table on the fly by using DDL in my package!
This is driving me crazy - basically I need to be able to execute DDL to do various 'create table ... as select ... from ...' statements which eventually builds a final table which I then want to populate using a REF_CURSOR so I can return the results back to ASP via ADO... but I just can't get the DDL bit to work no matter what I try!!
Can anyone see what I'm doing wrong here?
Mike.
nullHere are a some ideas to try:
Remove the extra semicolon from your sql_stmt, so that line reads:
sql_stmt := 'CREATE TABLE tmp AS SELECT * FROM nerep4';
Ensure that you have proper privileges as an individual user, not just through a role, by:
connecting to the database using username system and password manager and granting yourself the proper privileges. For example, if you are user SCOTT, then:
SQL> GRANT CREATE TABLE TO SCOTT;
Then, exit and connect as yourself and try to compile and execute your procedure again.
If that still doesn't work, try testing one little piece at a time until you can identify the part that causes trouble. For example, start with a procedure that does nothing but try to create the tmp table using execute immediate, then add the other pieces, then try to put the procedure in a package. -
Execute immediate with using clause to pass column name dynamically
Hai,
Is there any way using execute immeidate to pass the column name dynamically. I used to pass the column value as dynamic with the help of "Using clause" . But if i use to pass column name, it is giving numberic error at run time. Eg,. for testing has been given below.
1. Column value as dynamic, which is working correctly.
create or replace function testexeimm (acctnum char)
return number as
acctbal number;
begin
execute immediate 'select balance from acct_master where acct_no=:a' into acctbal using acctnum;
return acctbal;
end;
2. Column name as dynamic which is not working
create or replace function testexeimm (colnam char)
return char as
acctbal char;
begin
execute immediate 'select :a from ch_acct_mast where rownum=1' into acctbal using colnam;
return acctbal;
end;
Any help in this regard will be highly appericated.
Regards
SridharSo the variable has to be numeric too:
create or replace function testexeimm (colnam char)
return number as
acctbal number;
begin
execute immediate 'select '|||colnam||' from ch_acct_mast where rownum=1' into acctbal;
return acctbal;
end;Max
http://oracleitalia.wordpress.com -
Using EXECUTE IMMEDIATE with Create Table SQL Statement not working
Hi ,
I am all the privileges given from the SYSTEM user , but still i am not able to create a table under procedure . Please see these and advice.
create or replace procedure sp_dummy as
begin
Execute Immediate 'Create table Dummy99_99 (Dummy_Field number)';
end;
even i tried this way also
create or replace PROCEDURE clearing_Practise(p_file_id in varchar2, p_country in VARCHAR2,p_mapId in VARCHAR2)
AUTHID CURRENT_USER AS
strStatusCode VARCHAR2(6);
BEGIN
EXECUTE IMMEDIATE 'create table bonus(name varchar2(50))';
commit;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('ERROR Creating Table');
END ;William Robertson wrote:
Since the syntax is correct, my guess is you do not have CREATE TABLE system privilege granted directly to your account. A common scenario is that you have this privilege granted indirectly via a role, allowing you to create tables on the command line, but stored PL/SQL is stricter and requires a direct grant and therefore the procedure fails with 'insufficient privileges'.A bit like he's already been told on his first thread...
Using of Execute Immediate in Oracle PLSQL
Generally you would not create tables from stored PL/SQL. Also as you have found out, it's best not to hide exceptions with 'WHEN OTHERS THEN [some message which gives less detail than the one generated by Oracle]'.Again like he was told on the other thread.
There's just no telling some people eh! :) -
Delete From More than 1 table without using execute immediate
Hi,
Am new to PL/SQL, I had been asked to delete few of the table for my ETL jobs in Oracle 10G R2. I have to delete(truncate) few tables and the table names are in another table with a flag to delete it or not. So, when ever I run the job it should check for the flag and for those flag which is 'Y' then for all those tables should be deleted without using the Execute Immediate, because I dont have privilages to use "Execute Immediate" statement.
Can anyone help me in how to do this.
Regards
SenthilThen tell you DBA's, or better yet their boss, that they need some additional training in how Oracle actually works.
Yes, dynamic sql can be a bad thing when it is used to generate hundreds of identical queries that differ ony in the literals used in predicates, but for something like a set of delte table statements or truncate table statements, dynamic sql is no different in terms of the effect on the shared pool that hard coding the sql statements.
This is a bad use of dynamic sql, because it generates a lot of nearly identical statements due to the lack of bind variables. It is the type of thing your DBA's should, correctly, bring out the lead pipe for.
DECLARE
l_sql VARCHAR2(4000);
BEGIN
FOR r in (SELECT account_no FROM accounts_to_delete) LOOP
l_sql := 'DELETE FROM accounts WHERE account_no = '||r.account_no;
EXECUTE IMMEDIATE l_sql;
END LOOP;
END;This will result in one sql statement in the shared pool for every row in accounts_to_delete. Although there is much else wrong with this example, from the bind variable perspective it should be re-written to use bind variables like:
DECLARE
l_sql VARCHAR2(4000);
l_acct NUMBER;
BEGIN
FOR r in (SELECT account_no FROM accounts_to_delete) LOOP
l_sql := 'DELETE FROM accounts WHERE account_no = :b1';
EXECUTE IMMEDIATE l_sql USING l_acct;
END LOOP;
END;However, since you cannot bind object names into sql statements, the difference in terms of the number of statements that end up in the shared pool between this:
DECLARE
l_sql VARCHAR2(4000);
BEGIN
FOR r in (SELECT table_name, delete_tab, trunc_tab
FROM tables_to_delete) LOOP
IF r.delete_tab = 'Y' THEN
l_sql := 'DELETE FROM '||r.table_name;
ELSIF r.trunc_tab = 'Y' THEN
l_sql := 'TRUNCATE TABLE '||r.table_name;
ELSE
l_sql := NULL;
END IF;
EXECUTE IMMEDIATE l_sql;
END LOOP;
END;and something like this:
BEGIN
DELETE FROM tab1;
DELETE FROM tab2;
EXECUTE IMMEDIATE 'TRUNCTE TABLE tab3';
END;or this as a sql script
DELETE FROM tab1;
DELETE FROM tab2;
TRUNCTE TABLE tab3;is absolutley nothing.
Note that if you are truncating some of the tables, and wnat/need to use a stored procedure, you are going to have to use dynamic sql for the truncates anyway since trncate is ddl, and you cannot do ddl in pl/sql wiothout using dynamic sql.
John -
PLSQL table in EXECUTE IMMEDIATE
Hi All,
This is just a sample code.Table name may be changed in next run.
when I run this program ,getting error in EXECUTE IMMEDIATE -" V_FIELDS invalid identifier",Also the way I am doing,that's right?
create table TEMP
col1 VARCHAR2(200),
col2 VARCHAR2(200),
col3 DATE )
DECLARE
v_fields dbms_sql.varchar2a;
v_col_str VARCHAR2(200);
v_insert VARCHAR2(200);
v_idx INTEGER := 0;
v_tab VARCHAR2(30) := 'TEMP';
BEGIN
FOR i IN (SELECT s.column_name, s.data_type
FROM user_tab_cols s
WHERE s.table_name = v_tab
ORDER BY s.column_id)
LOOP
v_col_str := v_col_str || i.column_name || ',';
IF i.data_type = 'DATE'
THEN
v_insert := v_insert || 'TO_DATE(v_fields(' || v_idx || '),' ||
'''MM/DD/YYYY''' || '),';
ELSE
v_insert := v_insert || 'v_fields(' || v_idx || '),';
END IF;
v_idx := v_idx + 1;
END LOOP;
v_insert := '( ' || RTRIM(v_insert, ',') || ' )';
v_col_str := 'INSERT INTO ' || v_tab || ' ( ' || RTRIM(v_col_str, ',') ||
' ) VALUES ';
dbms_output.put_line(v_col_str || v_insert);
v_fields(0) := 1;
v_fields(1) := 'AB';
v_fields(2) := SYSDATE;
EXECUTE IMMEDIATE v_col_str || v_insert;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Err: ' || SQLERRM);
END;
Thanks,The dynamic SQL generated is
INSERT INTO TEMP ( COL1,COL2,COL3 ) VALUES ( v_fields(0),v_fields(1),TO_DATE(v_fields(2),'MM/DD/YYYY') ) PL/SQL engine sends this SQL to SQL engine. And guess what, SQL Engine has no clue what v_fields is. Why? because v_fields a private variable defined in a PL/SQL block for which SQL Engine has zero access.
Try this
DECLARE
v_fields dbms_sql.varchar2a;
v_col_str VARCHAR2(200);
v_insert VARCHAR2(200);
v_idx INTEGER := 0;
v_tab VARCHAR2(30) := 'TEMP';
BEGIN
FOR i IN (SELECT s.column_name, s.data_type
FROM user_tab_cols s
WHERE s.table_name = v_tab
ORDER BY s.column_id)
LOOP
v_col_str := v_col_str || i.column_name || ',';
IF i.data_type = 'DATE'
THEN
v_insert := v_insert || 'TO_DATE(:' || v_idx || ',' ||
'''MM/DD/YYYY''' || '),';
ELSE
v_insert := v_insert || ':' || v_idx || ',';
END IF;
v_idx := v_idx + 1;
END LOOP;
v_insert := '( ' || RTRIM(v_insert, ',') || ' )';
v_col_str := 'INSERT INTO ' || v_tab || ' ( ' || RTRIM(v_col_str, ',') ||
' ) VALUES ';
v_fields(0) := 1;
v_fields(1) := 'AB';
v_fields(2) := to_char(SYSDATE, 'MM/DD/YYYY');
execute immediate v_col_str || v_insert using v_fields(0), v_fields(1), v_fields(2);
END;
/ I personally don't encourage dynamic SQL. Dynamic SQL is always a pain and a result of bad design.
And the most worst thing, the thing that is terrible than dynamic SQL is this
WHEN OTHERS THEN
dbms_output.put_line('Err: ' || SQLERRM);
END; Whats the logic and possible benefit behind this code? Its NONE. Don't do that, NEVER. WHEN OTHERS without a RAISE is a bug in your code. So never do that. And DBMS_OUTPUT is not the correct way to render error message to user. -
Transaction control with execute immediate
Hi, What is the correct way to commit/ rollback transactions when executing a dynamic update statement with execute immediate?
Hi Thanks fo the reply, they don't appear to be. here's my procedure. Is there anything the is obviously wrong?
PROCEDURE p_move_city_numerics ( p_mode IN VARCHAR2,
p_schema IN VARCHAR2,
p_table IN VARCHAR2,
p_destination IN VARCHAR2,
p_city_name IN VARCHAR2,
p_outcome OUT VARCHAR2)
IS
l_valid_object VARCHAR2(200);
l_error_msg VARCHAR2(200);
l_outcome VARCHAR2(2000);
l_sql_count VARCHAR2(2000);
l_sql_update VARCHAR2(2000);
l_record_count NUMBER;
e_object_error EXCEPTION;
BEGIN
l_valid_object := f_is_city_valid (p_schema, p_table, p_destination);
IF l_valid_object != 'VALID' THEN
RAISE e_object_error;
END IF;
l_sql_count := 'SELECT COUNT(*) FROM ' || p_schema || '.' || p_table;
l_sql_count := l_sql_count || ' WHERE UPPER(city) LIKE ' || '''' || '%' || UPPER(p_city_name) || '%' || '''';
l_sql_count := l_sql_count || ' AND ( city LIKE ' || '''' || '%1%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%2%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%3%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%4%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%5%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%6%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%7%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%8%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%9%' || '''';
l_sql_count := l_sql_count || ' OR city LIKE ' || '''' || '%0%' || '''' || ')';
l_sql_update := 'UPDATE ' || p_schema || '.' || p_table;
l_sql_update := l_sql_update || ' SET ' || p_destination || ' = city,';
l_sql_update := l_sql_update || ' city = ' || '''' || p_city_name || '''';
l_sql_update := l_sql_update || ' WHERE UPPER(city) LIKE ' || '''' || '%' || UPPER(p_city_name) || '%' || '''';
l_sql_update := l_sql_update || ' AND ( city LIKE ' || '''' || '%1%' || '''';
l_sql_update := l_sql_update || ' OR ciity LIKE ' || '''' || '%2%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%3%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%4%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%5%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%6%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%7%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%8%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%9%' || '''';
l_sql_update := l_sql_update || ' OR city LIKE ' || '''' || '%0%' || '''' || ')';
IF p_mode = 'SELECT' THEN
EXECUTE IMMEDIATE(l_sql_count) INTO l_record_count;
l_outcome := TO_CHAR(l_record_count) || ' records to be updated!';
ELSIF p_mode = 'UPDATE' THEN
EXECUTE IMMEDIATE(l_sql_count) INTO l_record_count;
EXECUTE IMMEDIATE(l_sql_update);
l_outcome := TO_CHAR(l_record_count) || ' records have been updated!';
COMMIT;
ELSE
l_outcome := ' ERROR - Invalid mode: ' || p_mode || ' has been passed into the function! Valid values are SELECT or UPDATE';
END IF;
EXCEPTION
WHEN e_object_error THEN
IF l_valid_object = 'INVALID_TABLE' THEN
l_outcome := 'ERROR - Not a valid table name: ' || p_schema || '.' || p_table;
ELSIF l_valid_object = 'INVALID_CITY' THEN
l_outcome := 'ERROR - CITY not a valid field in the table: ' || p_schema || '.' || p_table;
ELSIF l_valid_object = 'INVALID_DEST' THEN
l_outcome := 'ERROR - Destination field: ' || p_destination || ' is not a valid field in the table: ' || p_schema || '.' || p_table;
END IF;
WHEN OTHERS THEN
l_error_msg := SQLCODE || '-' || SUBSTR(SQLERRM, 1, 150);
l_outcome := 'ERROR - ' || l_error_msg;
ROLLBACK;
END p_move_city_numerics; -
EXECUTE IMMEDIATE with an update FUNCTION returning VARCHAR2
I need to execute immediate a stored Function (that updates the database) and returns a VARCHAR2 value.
What does my execute immediate statement look like:
EXECUTE IMMEDIATE 'BEGIN my_function_call; END;' RETURNING INTO return_variable;A set of procedures would be far preferable to a set of functions if you're doing DML.
Additionally, I'd get rid of the status value entirely and just raise an exception if there is an error. It's a heck of a lot easier to catch (or propagate) exceptions correctly than to ensure that each and every piece of code that calls these procedures checks the return code and acts appropriately. It's way too easy to miss/ hide an error in a missed return code.
Justin -
Execute immediate and dynamic sql
Dear all;
Just curious....Why do developers still use dynamic sql..and execute immediate, because I always thought dynamic sql were bads and the use of execute immediate as well...
or am I missing something...There are no 'bad' things and 'good' things.
There are 'correctly used' and 'incorrectly used' features.
It depends what you want to do.
One simple example: Oracle 11.2 - you write a package that fetches data from range interval partitioned table (a new partition is created automatically every day when new key values are inserted). If you use static SQL then whenever Oracle creates a new partition then your package gets invalidated and has to be compiled. If your package is heavily used (by many sessions running in parallel) then you may get this:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "PACKAGE.XXXXX" has been invalidated
ORA-06508: PL/SQL: could not find program unit being called: "PACKAGE.XXXXX" Nice, isn't it?
You can avoid this kind of problems by simply using dynamic SQL. You break dependency with the table and your package is not invalidated when new partition is created. -
Hi!
I created a dynamically generated tabular form - the number of columns is not known in advanced. Each cell of the form is a text item generated with apex_item.text().
I want to write an after-submit process that saves the values from the form into a database table. In this process I already know how many columns there are in the report so I want to do the following:
--for each row...
for i in 1..apex_application.g_f01.count loop
-- and for each column in that row (number of columns is in v_col_count)
for j in 1..v_col_count loop
-- get the value of text item
v_query := 'select apex_application.g_f0' || j || '(' || i || ')' || ' from dual';
execute immediate v_query into v_value;
-- now do some DML with v_value
end loop;
end loop;The problem is that I get an error: ORA-06553: PLS-221: 'G_Fxx' is not a procedure or is undefined where xx is the number from the generated query.
My question is - am I doing something wrong or is is just not possible to reference apex_application.g_fxx in "execute immediate"? Will I have to manually check for all 50 possibilites of apex_application.g_fxx? Is there another way?
TIA,
JureWell now I know what was wrong and what you were trying to tell me - apex_application.g_fxx is not visible in "plain" SQL. And now I also have a solution to this problem. The point is to wrap the select statement with begin - end block so that the statement is rendered as pl/sql:
--for each row...
for i in 1..apex_application.g_f01.count loop
-- and for each column in that row (number of columns is in v_col_count)
for j in 1..v_col_count loop
-- get the value of text item
v_query := 'begin select apex_application.g_f0' || j || '(:i)' || ' into :x from dual; end;';
execute immediate v_query using i, out v_value;
-- now do some DML with v_value
end loop;
end loop;This works great :).
Jure
Maybe you are looking for
-
NO DISPLAY FOR POSSIBLE ENTERIES(F4) FOR TRANSACTION
Hi GURU, WE ARE FACING A SITUATION WHERE WHEN WE PRESS (F4) FOR POSSIBLE ENTRIES FOR EXAMPLE IN T.CODE MD04 OR CO01 ITS BLANK AND BELOW THE POP SCREEN ITS SHOWS 16 ENTRIES FOUND. PLEASE HELP REGARDS RAMKUMAR WARIYAR
-
OSB (ALSB 2.6) Unwanted changes to XML messages
I have a customer who would like to pass the following XML to OSB 2.6 (ALSB): </Parameter><Parameter Encoding="plain"><Name>TestParameter2</Name><Value><firsttag><secondtag>text_in_secondtag</secondtag></firsttag></Value></Parameter> The problem is t
-
Find sqltext that consuming a high CPU
hello, I have a linux machine, when i do a top command , i can see a oracle process that consumming a high CPU (PID=12958) I want to find a sql request that correspond to this PID I want to know , what is the view that contain the PID column. PID USE
-
I'm looking for a dot matrix printer for my macbook air, is there any solution?? Please advise. THX....
-
<font face="Times New Roman" color="35349F" size="3"> Hi, for these codes public void onSubmit() { DBTransaction dt; i have got one issue like Error(406,38): variable dt might not have been initialized why? Thanks & Best Regards, HuaMin </font>