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
AID < 50)的導航邏輯有缺陷,導致刪除/更新運算子無法正確定位所有符合條件的列。不要在單一欄位上建立降序索引,因為 SQL Server 可反向掃描升序索引以滿足
ORDER BY col DESC,效能無差異。降序索引主要用於複合索引中(如ORDER BY Col1 ASC, Col2 DESC)。
PRIMARY KEY CLUSTERED (AID ASC),查詢 WHERE AID < 50、ORDER BY AID DESC 均能高效利用索引。CREATE NONCLUSTERED INDEX IX_AID_Desc ON AType (AID DESC),叢集索引保持升序。-- 找出所有單欄降序叢集索引
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 正確性。