在存储过程中动态添加表名

时间:2019-06-23 13:11:58

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

我一直在尝试寻找在查询中动态更改表名的方法,但到目前为止还没有找到可行的方法。该查询具有重复的代码(每个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;

2 个答案:

答案 0 :(得分:1)

您需要使用EXECUTE IMMEDIATE Statement

  

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

对于example

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

答案 1 :(得分:1)

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

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进行了少许更改。