1.情景展示
情景一:
刪除PRIMARY_INDEX_TEST表中,MINDEX_ID字段為空的數據
情景二:
刪除VIRTUAL_CARD_TEST表中的臟數據
2.解決方案
情景一的解決方案:
DELETE FROM PRIMARY_INDEX_TEST WHERE MINDEX_ID IS NULL
情景二的解決方案:
最簡單的方法,見文末 2019/10/17
2018/12/10
方案1:使用快速游標法(刪除一次提交一次);
1 --快速游標法 2 BEGIN 3 FOR TEMP_CURSOR IN (SELECT ID 4 FROM VIRTUAL_CARD3 5 WHERE INSTR(NAME, '*') > 0 6 UNION 7 SELECT ID 8 FROM VIRTUAL_CARD3 9 WHERE INSTR(NAME, '#') > 0 10 UNION 11 SELECT ID 12 FROM VIRTUAL_CARD3 13 WHERE INSTR(NAME, '/') > 0 14 UNION 15 SELECT ID 16 FROM VIRTUAL_CARD3 17 WHERE INSTR(NAME, '+') > 0 18 UNION 19 SELECT ID 20 FROM VIRTUAL_CARD3 21 WHERE INSTR(NAME, '!') > 0 22 UNION 23 SELECT ID 24 FROM VIRTUAL_CARD3 25 WHERE INSTR(NAME, '.') > 0) LOOP 26 /* LOOP循環的是TEMP_CURSOR(逐條讀取TEMP_CURSOR) */ 27 DELETE FROM VIRTUAL_CARD3 WHERE VIRTUAL_CARD3.ID = TEMP_CURSOR.ID; 28 COMMIT; --提交 29 END LOOP; 30 END;
執行時間:
方案2:更多游標使用方法,見文末推薦;
方案3:使用存儲過程按id進行逐條刪除。
1 CREATE OR REPLACE PROCEDURE DELETE_TABLE_BATCH(V_ROWS IN NUMBER /*刪除多少條數據后進行提交*/) IS 2 /** 3 * 內容: 4 * 日期:2018/12/05 5 * 作者:Marydon 6 * 版本:1.0 7 */ 8 I NUMBER(10); --聲明變量,用於記錄次數 9 BEGIN 10 FOR TEMP_TABLE IN (SELECT ID 11 FROM VIRTUAL_CARD_TEST 12 WHERE INSTR(NAME, '*') > 0 13 UNION 14 SELECT ID 15 FROM VIRTUAL_CARD_TEST 16 WHERE INSTR(NAME, '#') > 0 17 UNION 18 SELECT ID 19 FROM VIRTUAL_CARD_TEST 20 WHERE INSTR(NAME, '/') > 0 21 UNION 22 SELECT ID 23 FROM VIRTUAL_CARD_TEST 24 WHERE INSTR(NAME, '+') > 0 25 UNION 26 SELECT ID 27 FROM VIRTUAL_CARD_TEST 28 WHERE INSTR(NAME, '!') > 0 29 UNION 30 SELECT ID 31 FROM VIRTUAL_CARD_TEST 32 WHERE INSTR(NAME, '.') > 0) LOOP 33 /* LOOP循環的是TEMP_TABLE(逐條讀取TEMP_TABLE) */ 34 DELETE VIRTUAL_CARD_TEST WHERE VIRTUAL_CARD_TEST.ID = TEMP_TABLE.ID; 35 I := I + 1; --刪除一次,+1 36 IF I >= V_ROWS THEN 37 COMMIT; --提交 38 I := 0; --重置 39 END IF; 40 END LOOP; 41 EXCEPTION 42 /* 輸出異常信息 */ 43 WHEN OTHERS THEN 44 DBMS_OUTPUT.PUT_LINE('異常編號:' || SQLCODE); 45 DBMS_OUTPUT.PUT_LINE('異常信息:' || SQLERRM); 46 ROLLBACK; --回滾 47 END DELETE_TABLE_BATCH;
創建並運行該存儲過程
刪除16522條數據,用了6分21秒,比方式一慢太多了。
方案4:
將要保留的數據插入到新表
1 --將要保留的數據插入到新表 2 CREATE TABLE VIRTUAL_CARD_TEMP2 AS( 3 SELECT * 4 FROM VIRTUAL_CARD2 5 WHERE INSTR(NAME, '*') = 0 6 AND INSTR(NAME, '#') = 0 7 AND INSTR(NAME, '/') = 0 8 AND INSTR(NAME, '+') = 0 9 AND INSTR(NAME, '!') = 0 10 AND INSTR(NAME, '.') = 0)
刪除原來的表
--刪除原表 drop table VIRTUAL_CARD2
將新建的表進行重命名成刪除表的名稱。
說明:原來的表有過存在外鍵約束等關系時,並沒有進行測試,因為該表沒有索引之類東西,自己測試的時候一定要慎重!!!
方案5:使用in函數
DELETE FROM VIRTUAL_CARD_TEMP WHERE ID_CARD IN (SELECT T1.ID_CARD FROM VIRTUAL_CARD_TEMP T1 WHERE INSTR(T1.NAME, '*') > 0 UNION SELECT T1.ID_CARD FROM VIRTUAL_CARD_TEMP T1 WHERE INSTR(T1.NAME, '#') > 0 UNION SELECT T1.ID_CARD FROM VIRTUAL_CARD_TEMP T1 WHERE INSTR(T1.NAME, '/') > 0 UNION SELECT T1.ID_CARD FROM VIRTUAL_CARD_TEMP T1 WHERE INSTR(T1.NAME, '+') > 0 UNION SELECT T1.ID_CARD FROM VIRTUAL_CARD_TEMP T1 WHERE INSTR(T1.NAME, '!') > 0 UNION SELECT T1.ID_CARD FROM VIRTUAL_CARD_TEMP T1 WHERE INSTR(T1.NAME, '.') > 0)
說明:ID_CARD字段必須具有唯一性。
寫在最后
哪位大佬如若發現文章存在紕漏之處或需要補充更多內容,歡迎留言!!!
相關推薦: