首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

PL/SQL 以游標複製符合條件資料至另一表:匿名區塊、FETCH 迴圈與批次提交實戰

     編輯:關於SqlServer

核心語法:INSERT ... SELECT(最簡單、最高效)


INSERT INTO target_table (col1, col2, ...)
SELECT col1, col2, ...
FROM source_table
WHERE condition;

單一 SQL 陳述式完成集合操作,原子性、最佳化、無需游標。

游標逐筆複製教學範例(學習用途)

需求:將 components 表中 ID 為 5 的倍數的列,複製到結構相同的 components_copy 表。


DECLARE
  v_id       components.id%TYPE;
  v_sql      VARCHAR2(1000);
  v_count    NUMBER := 0;
  
  -- 定義游標
  CURSOR id_cur IS
    SELECT id FROM components;
BEGIN
  OPEN id_cur;
  LOOP
    FETCH id_cur INTO v_id;
    EXIT WHEN id_cur%NOTFOUND;
    
    -- 條件判斷:ID 為 5 的倍數
    IF MOD(v_id, 5) = 0 THEN
      BEGIN
        -- 動態 SQL 示範(實務建議靜態 SQL)
        v_sql := 'INSERT INTO components_copy SELECT * FROM components WHERE id = :1';
        EXECUTE IMMEDIATE v_sql USING v_id;
        
        v_count := v_count + 1;
        
        -- 批次提交:每 100 筆提交一次
        IF MOD(v_count, 100) = 0 THEN
          COMMIT;
        END IF;
      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          NULL; -- 忽略重複鍵
        WHEN OTHERS THEN
          ROLLBACK; -- 或記錄日誌後決定
          RAISE;
      END;
    END IF;
  END LOOP;
  CLOSE id_cur;
  
  COMMIT; -- 最終提交
  DBMS_OUTPUT.PUT_LINE('Copied: ' || v_count);
EXCEPTION
  WHEN OTHERS THEN
    IF id_cur%ISOPEN THEN CLOSE id_cur; END IF;
    ROLLBACK;
    RAISE;
END;

PL/SQL 區塊結構回顧


[DECLARE]
  -- 宣告區:變數、型別、游標、區域子程序
BEGIN
  -- 執行區:程序性與 SQL 陳述式(必要區段)
[EXCEPTION]
  -- 例外處理區
END;
  • 每個區塊以 ; 結束。
  • DECLARE、EXCEPTION 為選擇性。

游標操作四步驟

  1. 定義:CURSOR cur_name IS SELECT ...
  2. 開啟:OPEN cur_name;
  3. 擷取:FETCH cur_name INTO var_list;
  4. 關閉:CLOSE cur_name;

進階游標寫法:FOR 迴圈隱式游標(推薦)


BEGIN
  FOR rec IN (SELECT * FROM components WHERE MOD(id, 5) = 0) LOOP
    INSERT INTO components_copy VALUES rec;
    -- 隱式游標自動開啟/擷取/關閉,程式碼簡潔
  END LOOP;
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
    RAISE;
END;

大量資料高效替代方案

方案適用場景優勢
INSERT ... SELECT全量/條件複製單一陳述式、原子性、最佳化器最佳路徑
FORALL ... BULK COLLECT需逐列邏輯處理批次綁定、減少 Context Switch、10-100x 加速
CREATE TABLE AS SELECT (CTAS)建新表並複製最快、最小記錄、並行執行
外部表 / Data Pump跨資料庫/異構遷移工具級、支援平行、壓縮、加密

實務建議

  1. 優先用集合操作:INSERT ... SELECT、MERGE、CTAS,避免手寫游標迴圈。
  2. 游標必要時用 FOR 迴圈:自動管理資源,減少洩漏風險。
  3. 批次提交控制交易大小:避免長交易導致 Undo 爆滿、鎖定爭用。
  4. 例外處理不可空:至少記錄錯誤、決定繼續/中止。
  5. 大量資料考慮 NOLOGGING / APPEND Hint:INSERT /*+ APPEND */ INTO ... 最小化重做日誌。

游標是 PL/SQL 基礎技能,但實務中「能用 SQL 解決就不用游標」是效能與可維護性的鐵律。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved