PL SQL-使用动态SQL生成删除语句

时间:2015-11-03 01:05:34

标签: oracle stored-procedures plsql

我想使用PL SQL创建一个存储过程,允许我查找包含特定列的所有表,然后从那些在该列中具有特定值的表中删除记录。

例如,我想查找所有具有“year”列的表,然后删除所有具有年份“2012”的表中的所有记录(今年将是执行时输入的参数)

我的尝试是创建一个存储过程,使用游标获取具有此“year”列的所有表,然后使用动态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关键字但未找到。这是用于我的目的的最佳方法吗?

2 个答案:

答案 0 :(得分:3)

必须是这样的:

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;

答案 1 :(得分: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;