DECLARE @OldId VARCHAR(50), @CustomerID VARCHAR(50);
DECLARE My_Cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT CustomerID, OldId FROM Customer WHERE Area = 'bj'; -- 只讀、順向、無捲動
OPEN My_Cursor;
FETCH NEXT FROM My_Cursor INTO @CustomerID, @OldId;
WHILE @@FETCH_STATUS = 0
BEGIN
-- 逐行業務邏輯
DECLARE @OtherPro VARCHAR(500), @StatusID VARCHAR(200), @UserId VARCHAR(200), @FinalUserId VARCHAR(200);
SELECT @OtherPro = OtherPro, @StatusID = CustomerStatusID, @UserId = UserID
FROM bjsunmis.dbo.Customer WHERE CustomerID = @OldId;
SELECT @FinalUserId = UserID FROM Users WHERE OldId = @UserId;
INSERT INTO CustomerOtherInfo (CustomerID, OtherPro, CustomerStatusID, UserID)
VALUES (@CustomerID, @OtherPro, @StatusID, @FinalUserId);
FETCH NEXT FROM My_Cursor INTO @CustomerID, @OldId;
END
CLOSE My_Cursor;
DEALLOCATE My_Cursor;
GO
| 選項 | 說明 | 建議 |
|---|---|---|
| LOCAL | 僅批次/SP 內可見 | ✅ 預設 GLOBAL 易衝突 |
| FAST_FORWARD | FORWARD_ONLY + READ_ONLY 優化 | ✅ 只讀順向最快 |
| FORWARD_ONLY | 僅支援 FETCH NEXT | ✅ 不需捲動 |
| READ_ONLY | 不可更新底表 | ✅ 避免鎖升級 |
| STATIC | 複製結果到 tempdb | 大資料慎用 |
| KEYSET | 固定鍵集,資料變動可見 | 中等資料 |
| DYNAMIC | 即時反映所有變動 | 最慢、鎖最久 |
INSERT...SELECT、MERGE、CTE)-- 原游標邏輯:逐行查詢並插入
-- 改為單一陳述式
INSERT INTO CustomerOtherInfo (CustomerID, OtherPro, CustomerStatusID, UserID)
SELECT c.CustomerID, c2.OtherPro, c2.CustomerStatusID, u.UserID
FROM Customer c
JOIN bjsunmis.dbo.Customer c2 ON c2.CustomerID = c.OldId
JOIN Users u ON u.OldId = c2.UserID
WHERE c.Area = 'bj';
原則:能用單一 SQL 解決的,堅決不用游標。