PL SQL - 使用动态 SQL 生成删除语句
Posted
技术标签:
【中文标题】PL SQL - 使用动态 SQL 生成删除语句【英文标题】:PL SQL- Using Dynamic SQL to Generate Delete Statements 【发布时间】:2015-11-03 01:05:33 【问题描述】:我想使用 PL SQL 创建一个存储过程,它允许我查找包含特定列的所有表,然后从那些表中删除在该列中具有特定值的记录。
例如,我想查找所有具有“年”列的表,然后从所有具有“2012”年的表中删除所有记录(今年将是执行时输入的参数)
我在这方面的尝试是创建一个存储过程,使用游标获取所有具有“年”列的表,然后使用动态 SQL 循环遍历该游标,这将生成我的删除语句,我可以执行。
CREATE OR REPLACE PROCEDURE year_deletion
(
p_year NUMBER --Input of the year for records to be deleted
)
IS
CURSOR c1 --Cursor that will find all tables that have the YEAR column
IS
SELECT owner, table_name
FROM all_tab_columns
WHERE column_name = 'YEAR'
AND owner = 'GTP';
BEGIN
FOR i IN c1 LOOP --Loop through all of the tables that the cursor found, generate a SQL statement for each table that will delete all of the records that have the year of p_year
EXECUTE IMMEDIATE ('SELECT * FROM' ||i.table_name|| 'WHERE YEAR = '||p_year||';');
END LOOP;
END;
免责声明:出于测试目的,我使用 Select * From 而不是 DELETE * From,当此过程正确执行时,我将更改它。
到目前为止,这个存储过程可以正确编译,但在执行过程中给我一个错误,即预期有 FROM 关键字但未找到。这是为我的目的使用的最佳方法吗?
【问题讨论】:
您需要在 FROM 之后添加空格,所以应该是 FROM ' 而不是 ...FROM'我> || operator 会将 i.table_name 粘贴到 FROM 上,然后你就会有一个 FROMi.table_name 这样的词,这当然不是编译器要找的 另外你必须在 'WHERE YEAR =... 中添加一个空格应该是 ' WHERE YEAR =' 您也可以在循环内添加一个异常块,在这种情况下至少打印错误。例如,如果您有一些表,其中 YEAR 是一个字符串并且具有字符串值,那么您的 sql 将失败,并且 lopp 将在该点停止。 【参考方案1】:一定是这样的:
EXECUTE IMMEDIATE 'DELETE FROM ' ||i.table_name|| ' WHERE YEAR = :theYear' USING p_year;
注意FROM
和WHERE
之前的空格。
您不能简单地将DELETE
替换为SELECT ...
进行测试,因为对于SELECT,您必须有一个INTO
子句。
你的整个过程可以是这样的
CREATE OR REPLACE PROCEDURE year_deletion(p_year IN NUMBER) IS
CURSOR c1 IS
SELECT owner, table_name
FROM all_tab_columns
WHERE column_name = 'YEAR'
AND owner = 'GTP';
res NUMBER;
BEGIN
FOR i IN c1 LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM ' ||i.table_name|| ' WHERE YEAR = :theYear' INTO res USING p_year;
DBMS_OUTPUT.PUT_LINE (res ||' rows will be deleted from table '||i.table_name );
EXECUTE IMMEDIATE
'DELETE FROM ' ||i.table_name|| ' WHERE YEAR = :theYear' USING p_year;
END LOOP;
END;
【讨论】:
【参考方案2】:Hello you can try the below code. It will surely help you out.
CREATE OR REPLACE PROCEDURE year_deletion(
p_year IN NUMBER --Input of the year for records to be deleted
)
IS
BEGIN
FOR i IN (SELECT owner,
table_name
FROM all_tab_columns
WHERE column_name = 'YEAR'
AND owner = 'GTP')
LOOP --Loop through all of the tables that the cursor found, generate a SQL statement for each table that will delete all of the records that have the year of p_year
EXECUTE IMMEDIATE 'DELETE FROM ' ||i.table_name|| ' WHERE YEAR = '||p_year;
END LOOP;
END;
【讨论】:
以上是关于PL SQL - 使用动态 SQL 生成删除语句的主要内容,如果未能解决你的问题,请参考以下文章