2015-11-03 110 views
1

我想创建一个使用PL SQL的存储过程,它允许我查找包含特定列的所有表,然后从那些表中删除具有特定值的表中的记录柱。PL SQL-使用动态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关键字但未找到。这是用于我的目的的最佳方法吗?

+5

你需要* FROM后添加空格*所以不是* ... FROM * – Hawk

+3

'*,它应该从*' ||操作符将i.table_name粘贴到FROM,然后您将会得到一个像FROMi.table_name这样的单词,这当然不是编译器寻找的内容 – Hawk

+0

还需要在'WHERE YEAR = =中添加空格= ...它应该'WHERE YEAR =' – Aitor

回答

3

是必须是这样的:

EXECUTE IMMEDIATE 'DELETE FROM ' ||i.table_name|| ' WHERE YEAR = :theYear' USING p_year; 

FROMWHERE之前的空间。

您不能简单地将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; 
0
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;