Skip to content
Advertisement

Using declared variables in SQL Oracle query FOR LOOP

I’m attempting to write a query script where I declare a variable and then use them in a select statement in Oracle SQL.
Basically script should check if parent tables’ entries are used in referenced table or not. if not –> delete the entry from REF table. So far I have this

DECLARE

tableToCompare sys_refcursor;

TYPE TableNameType IS RECORD (
        table_name          ALL_TABLES.TABLE_NAME%TYPE
        , ref_table_name ALL_CONSTRAINTS.r_constraint_name%TYPE
        );
        
        tableName TableNameType;
        
    PROCEDURE LOG_MSG(msg VARCHAR2)
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('->'||msg);
    END;

BEGIN
LOG_MSG('[PROCESS] -> starts');

-- find all parent tables for reference tables starting with REF_
    OPEN tableToCompare FOR
            SELECT ac.table_name, substr(ac.r_constraint_name, 0, LENGTH(ac.r_constraint_name) - 3)  as ref_table_name
              FROM all_constraints ac
             WHERE 1 = 1 AND ac.constraint_type = 'R'
                   AND ac.r_constraint_name IN
                            (SELECT constraint_name
                               FROM all_constraints
                              WHERE table_name like 'REF_%');
                                 
    LOOP
        FETCH tableToCompare INTO tableName;
        EXIT WHEN tableToCompare%NOTFOUND;

        LOG_MSG('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name );
        
        DELETE  REF_STYLE_TYPE rst 
            WHERE NOT EXISTS (SELECT TYP_CD from STYLE_FORMAT rp WHERE rp.TYP_CD = rst.TYP_CD)
                AND NOT EXISTS (SELECT TYP_CD from STYLE_REQ rp WHERE rp.TYP_CD = rst.TYP_CD)
                AND NOT EXISTS (SELECT TYP_CD from STYLE_ADD_EX rp WHERE rp.TYP_CD = rst.TYP_CD);
                
     --   DELETE tableName.ref_table_name rst 
    --        WHERE NOT EXISTS (SELECT TYP_CD from tableName.table_name rp WHERE rp.TYP_CD = rst.TYP_CD)
      --          AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+1 rp WHERE rp.TYP_CD = rst.TYP_CD)
       --         AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+2 rp WHERE rp.TYP_CD = rst.TYP_CD);

      LOG_MSG('DONE!');
    
     END LOOP; 
END;

So far LOG_MSG('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name ); I got a msg log that lists me the variables but I have no idea how to combine that in query DELETE above.

Any ideas or suggestions how it could be automized to this ?

     --   DELETE tableName.ref_table_name rst 
    --        WHERE NOT EXISTS (SELECT TYP_CD from tableName.table_name rp WHERE rp.TYP_CD = rst.TYP_CD)
      --          AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+1 rp WHERE rp.TYP_CD = rst.TYP_CD)
       --         AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+2 rp WHERE rp.TYP_CD = rst.TYP_CD);

Advertisement

Answer

You can’t reference table names as bind variables. In that case, use EXECUTE IMMEDIATE. I’m a big fan of cursor for loops so I used that. Note that this code is not tested.

DECLARE
  PROCEDURE LOG_MSG(msg VARCHAR2)
  IS
  BEGIN
      DBMS_OUTPUT.PUT_LINE('->'||msg);
  END;
  l_delete_stmt VARCHAR2(4000);
BEGIN
  log_msg('[PROCESS] -> starts');
  l_delete_stmt := 
q'!DELETE #TABLE_NAME# rst 
            WHERE NOT EXISTS (SELECT TYP_CD from STYLE_FORMAT rp WHERE rp.TYP_CD = rst.TYP_CD)
                AND NOT EXISTS (SELECT TYP_CD from STYLE_REQ rp WHERE rp.TYP_CD = rst.TYP_CD)
                AND NOT EXISTS (SELECT TYP_CD from STYLE_ADD_EX rp WHERE rp.TYP_CD = rst.TYP_CD)!';
                
  FOR r IN 
  (
    SELECT ac.table_name, substr(ac.r_constraint_name, 0, LENGTH(ac.r_constraint_name) - 3)  as ref_table_name
      FROM all_constraints ac
     WHERE 1 = 1 AND ac.constraint_type = 'R'
           AND ac.r_constraint_name IN
                    (SELECT constraint_name
                       FROM all_constraints
                      WHERE table_name like 'REF_%')  
  ) LOOP
    log_msg('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name );
    log_msg('Delete statement: ' || REPLACE(l_delete_stmt,'#TABLE_NAME#',r.ref_table_name) );
    EXECUTE IMMEDIATE REPLACE(l_delete_stmt,'#TABLE_NAME#',r.ref_table_name);
    log_msg('DONE!');
  END LOOP;
END;
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement