在存储过程中动态添加一个 table 名称

Add a table name dynamically in a stored procedure

我一直在尝试寻找在查询中动态更改 table 名称的方法,但到目前为止还没有找到可行的方法。该查询具有重复代码(每个 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 解决方案建议采用以下格式,但它给出的错误消息是 "Table L_Temp does not exist":

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;

当所有目标 table 包含相似的列名称时,是否有一种方法可以动态更改 table 名称?

*已编辑 * 为附加更新语句示例添加的代码:

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;

您需要使用EXECUTE IMMEDIATE Statement

The EXECUTE IMMEDIATE statement executes a dynamic SQL statement or anonymous PL/SQL block. You can use it to issue SQL statements that cannot be represented directly in PL/SQL, or to build up statements where you do not know all the table names

对于example

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

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

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,因为您使用的 table 快捷方式和列名称似乎与其余代码不匹配。