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

SQL Server 2000 降序叢集索引 Bug:篩選條件刪除/更新資料遺漏

     編輯:關於SqlServer

SQL Server 2000(Enterprise 與 Personal 版)在單一欄位降序叢集索引上,執行帶篩選條件的 DELETE 或 UPDATE 陳述式時,可能導致符合條件的列未被正確處理,造成資料殘留。Microsoft 已確認為產品缺陷。

重現腳本

-- 建立降序叢集索引資料表
CREATE TABLE AType (
    AID INT NOT NULL,
    Name VARCHAR(20) NOT NULL,
    CONSTRAINT PK_AType PRIMARY KEY CLUSTERED (AID DESC)
);

-- 插入測試資料
INSERT INTO AType VALUES (1, 'a'), (50, 'b'), (100, 'c');

-- 查詢驗證
SELECT * FROM AType WHERE AID < 50;  -- 回傳 AID=1

-- 刪除操作
DELETE FROM AType WHERE AID < 50;

-- 再次查詢:Bug 觸發,AID=1 仍存在!
SELECT * FROM AType WHERE AID < 50;  -- 錯誤回傳 AID=1

根因分析

  • SQL Server 2000 優化器在單欄降序叢集索引上,對篩選述詞(AID < 50)的導航邏輯有缺陷,導致刪除/更新運算子無法正確定位所有符合條件的列。
  • 此 Bug 僅發生在單欄降序叢集索引;複合索引中包含降序欄位、或非叢集索引、或升序叢集索引均不受影響。
  • SQL Server 7.0 無此問題;SQL Server 2005 以降版本已修正。

官方建議規避方案

不要在單一欄位上建立降序索引,因為 SQL Server 可反向掃描升序索引以滿足 ORDER BY col DESC,效能無差異。降序索引主要用於複合索引中(如 ORDER BY Col1 ASC, Col2 DESC)。

實務替代方案

  1. 改用升序叢集索引:PRIMARY KEY CLUSTERED (AID ASC),查詢 WHERE AID < 50、ORDER BY AID DESC 均能高效利用索引。
  2. 若業務強制需降序儲存:在升序 PK 上建立非叢集降序索引 CREATE NONCLUSTERED INDEX IX_AID_Desc ON AType (AID DESC),叢集索引保持升序。
  3. 升級至 SQL Server 2005+:根本解決,並獲得功能與安全性更新。

檢測現有資料庫風險

-- 找出所有單欄降序叢集索引
SELECT 
    OBJECT_SCHEMA_NAME(t.object_id) + '.' + t.name AS TableName,
    i.name AS IndexName,
    COL_NAME(ic.object_id, ic.column_id) AS ColumnName,
    ic.is_descending_key
FROM sys.indexes i
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.tables t ON t.object_id = i.object_id
WHERE i.type_desc = 'CLUSTERED'
  AND i.index_id = 1
  AND (SELECT COUNT(*) FROM sys.index_columns WHERE object_id = i.object_id AND index_id = i.index_id) = 1
  AND ic.is_descending_key = 1;

結語

此為經典 SQL Server 2000 缺陷,現代版本已修正。維護舊系統時,請排查並移除單欄降序叢集索引,改用升序叢集索引配合非叢集索引滿足排序需求,確保 DML 正確性。

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