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
    Reuben

    Not 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>

  • EXECUTE IMMEDIATE - DDL

    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
    Friedhold

    How 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. Thanks

    Assuming 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.
    null

    Here 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
    Sridhar

    So 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
    Senthil

    Then 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.

  • [Solved] Reference apex_application.g_fXX in "execute immediate" statement

    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,
    Jure

    Well 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

  • Dot Matrix printer for Mac OS

    I'm looking for a dot matrix printer for my macbook air, is there any solution?? Please advise. THX....

  • Not initialized

    <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>