在存储过程中动态添加一个 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 快捷方式和列名称似乎与其余代码不匹配。
我一直在尝试寻找在查询中动态更改 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 快捷方式和列名称似乎与其余代码不匹配。