2015-11-03 38 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;