【问题标题】:Add a table name dynamically in a stored procedure在存储过程中动态添加表名
【发布时间】:2019-11-05 12:45:04
【问题描述】:

我一直在尝试寻找在查询中动态更改表名的方法,但到目前为止还没有找到可行的方法。该查询有重复的代码(每个 case 语句中大约有 150 行代码),所以我试图找到一种更好的方法。

我当前的程序如下所示:

CREATE OR REPLACE PROCEDURE PROC_MY_TEST (P_INPUTVAR       NUMBER,
                                          P_OUT        OUT SYS_REFCURSOR)
AS
BEGIN
   CASE P_INPUTVAR
      WHEN 1
      THEN
         OPEN P_OUT FOR
            WITH CTE
                 AS (SELECT COL_M, COL_N
                       FROM TBL_TEST
                      WHERE COL_G = 'mycondition1')
            SELECT COL_M, COL_N
              FROM TABLE_A a LEFT JOIN CTE m ON a.col1 = b.col1
             WHERE a.col2 = 'xyz' AND b.col4 = 'abc';
      WHEN 2
      THEN
         OPEN P_OUT FOR
            WITH CTE
                 AS (SELECT COL_M, COL_N
                       FROM TBL_TEST
                      WHERE COL_G = 'mycondition1')
            SELECT COL_M, COL_N
              FROM TABLE_B a LEFT JOIN CTE m ON a.col1 = b.col1
             WHERE a.col2 = 'xyz' AND b.col4 = 'abc';
      WHEN 3
      THEN
         OPEN P_OUT FOR
            WITH CTE
                 AS (SELECT COL_M, COL_N
                       FROM TBL_TEST
                      WHERE COL_G = 'mycondition1')
            SELECT COL_M, COL_N
              FROM TABLE_C a LEFT JOIN CTE m ON a.col1 = b.col1
             WHERE a.col2 = 'xyz' AND b.col4 = 'abc';
      WHEN 4
      THEN
         OPEN P_OUT FOR
            WITH CTE
                 AS (SELECT COL_M, COL_N
                       FROM TBL_TEST
                      WHERE COL_G = 'mycondition1')
            SELECT COL_M, COL_N
              FROM TABLE_D a LEFT JOIN CTE m ON a.col1 = b.col1
             WHERE a.col2 = 'xyz' AND b.col4 = 'abc';
   END CASE;
END;

一些 SQL 解决方案建议使用以下格式,但它给出了“表 L_Temp 不存在”的错误消息:

CREATE OR REPLACE PROCEDURE PROC_MY_TEST (P_INPUTVAR       NUMBER,
                                          P_OUT        OUT SYS_REFCURSOR)
AS
   L_Temp   VARCHAR2 (200);   
BEGIN
   L_Temp :=
      CASE P_INPUTVAR
         WHEN 1 THEN 'TABLE_A'
         WHEN 2 THEN 'TABLE_B'
         WHEN 3 THEN 'TABLE_C'
         WHEN 4 THEN 'TABLE_D'
         ELSE NULL
      END;

   OPEN P_OUT FOR
      WITH CTE
           AS (SELECT COL_M, COL_N
                 FROM TBL_TEST
                WHERE COL_G = 'mycondition1')
      SELECT COL_M, COL_N
        FROM L_Temp a LEFT JOIN CTE m ON a.col1 = b.col1
       WHERE a.col2 = 'xyz' AND b.col4 = 'abc';
END;

当所有目标表都包含相似的列名时,我们是否可以动态更改表名?

*已编辑 * 为其他更新语句示例添加了代码:

CREATE OR REPLACE PROCEDURE PROC_MY_TEST (P_INPUTVAR       NUMBER,
                                          P_OUT        OUT SYS_REFCURSOR)
AS
   L_Temp   VARCHAR2 (200);
   L_Total  NUMBER;
BEGIN
   L_Temp :=
      CASE P_INPUTVAR
         WHEN 1 THEN 'TABLE_A'
         WHEN 2 THEN 'TABLE_B'
         WHEN 3 THEN 'TABLE_C'
         WHEN 4 THEN 'TABLE_D'
         ELSE NULL
      END;

   OPEN P_OUT FOR
      WITH CTE
           AS (SELECT COL_M, COL_N
                 FROM TBL_TEST
                WHERE COL_G = 'mycondition1')
      SELECT COL_M, COL_N
        FROM L_Temp a LEFT JOIN CTE m ON a.col1 = b.col1
       WHERE a.col2 = 'xyz' AND b.col4 = 'abc';

      SELECT TOTAL INTO L_Total FROM L_Temp;

      UPDATE TBL_TEST2 
      SET a.TOTAL = l_Total 
      WHERE a.col2 = 'xyz';

END;

【问题讨论】:

    标签: sql oracle stored-procedures plsql dynamic-sql


    【解决方案1】:

    你需要使用EXECUTE IMMEDIATE Statement

    EXECUTE IMMEDIATE 语句执行动态 SQL 语句或匿名 PL/SQL 块。您可以使用它来发出不能在 PL/SQL 中直接表示的 SQL 语句,或者构建您不知道所有表名的语句

    对于example

    execute immediate '
      update ' || myTable || '
     ...
    ';
    

    【讨论】:

      【解决方案2】:

      您需要将语句创建为字符串,然后将语句作为光标打开:

      CREATE OR REPLACE PROCEDURE PROC_MY_TEST (P_INPUT_VAR IN  NUMBER,
                                                P_OUT       OUT SYS_REFCURSOR)
      AS
        strTable  VARCHAR2(30);
        strStmt   VARCHAR2(32767);
      BEGIN
        strTable := CASE P_INPUT_VAR
                      WHEN 1 THEN 'TABLE_A'
                      WHEN 2 THEN 'TABLE_B'
                      WHEN 3 THEN 'TABLE_C'
                      WHEN 4 THEN 'TABLE_D'
                    END;
      
        strStmt := 'WITH CTE AS (SELECT COL_M, COL_1, COL_4 ' ||
                                 ' FROM TBL_TEST ' ||
                                 ' WHERE COL_G = ''mycondition1'') ' ||
                   'SELECT COL_M, COL_N ' ||
                    ' FROM ' || strTable || ' t ' ||
                    ' LEFT JOIN CTE m ' ||
                      ' ON t.COL1 = m.COL_1 ' ||
                    ' WHERE a.COL2 = ''xyz'' AND ' ||
                          ' m.COL_4 = ''abc''';
      
        OPEN P_OUT FOR strStmt;
      END PROC_MY_TEST;
      

      请注意,我稍微更改了 SQL,因为您使用的表快捷方式和列名似乎与其余代码不匹配。

      【讨论】:

      • 谢谢,这看起来很漂亮。会试一试。如果在 OPEN P_OUT FOR Strstmt 之后立即进入更新语句的另一个选择,您是否也知道查询会如何? ?如果有帮助,我已将其添加到示例中。
      • 别担心,我已经弄清楚了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-22
      • 1970-01-01
      • 1970-01-01
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多