【问题标题】:Using declared variables in SQL Oracle query FOR LOOP在 SQL Oracle 查询 FOR LOOP 中使用声明的变量
【发布时间】:2021-05-18 07:01:21
【问题描述】:

我正在尝试编写一个查询脚本,在其中声明一个变量,然后在 Oracle SQL 的 select 语句中使用它们。
基本上脚本应该检查是否在引用表中使用了父表的条目。 如果不是 --> 从 REF 表中删除该条目。 到目前为止我有这个

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;

到目前为止LOG_MSG('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name ); 我得到了一个 msg 日志,其中列出了我的变量,但我不知道如何在上面的查询 DELETE 中组合它。

有什么想法或建议可以自动化吗?

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

【问题讨论】:

  • 您不能使用绑定变量来引用表 - 请参阅此答案:stackoverflow.com/questions/9723931/…
  • @KoenLostrie,如何检查引用表中的条目是否在不编写硬字符串的情况下使用是另一种选择吗?
  • 您可以连接一个字符串并使用EXECUTE IMMEDIATE
  • 我举个例子

标签: sql oracle plsql types


【解决方案1】:

您不能将表名作为绑定变量引用。在这种情况下,请使用EXECUTE IMMEDIATE。我是 cursor for loops 的忠实粉丝,所以我使用了它。请注意,此代码未经测试。

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多