Sql-Server
我可以添加一個忽略現有違規的唯一約束嗎?
我有一個表,該表目前在一列中有重複的值。
我無法刪除這些錯誤的重複項,但我想防止添加其他非唯一值。
我可以創建一個
UNIQUE
不檢查現有合規性的文件嗎?我曾嘗試使用
NOCHECK
但不成功。在這種情況下,我有一個將許可資訊與“CompanyName”聯繫起來的表
**編輯:**具有相同“公司名稱”的多行是錯誤數據,但我們目前無法刪除或更新這些重複項。一種方法是讓
INSERT
s 使用一個儲存過程,該過程會因重複而失敗……如果可以讓 SQL 自己檢查唯一性,那將是可取的。該數據按公司名稱查詢。對於少數現有的重複項,這將意味著返回並顯示多行……雖然這是錯誤的,但在我們的案例中是可以接受的。目標是防止它在未來發生。在我看來,我必須在儲存過程中執行此邏輯。
答案是“是”。您可以使用過濾索引來執行此操作(有關文件,請參見此處)。
例如,您可以這樣做:
create unique index t_col on t(col) where id > 1000;
這將創建一個唯一索引,僅在新行上,而不是在舊行上。這種特定的公式將允許使用現有值進行重複。
如果您只有少數重複項,則可以執行以下操作:
create unique index t_col on t(col) where id not in (<list of ids for duplicate values here>);
是的,你可以這樣做。
這是一個重複的表:
CREATE TABLE dbo.Party ( ID INT NOT NULL IDENTITY , CONSTRAINT PK_Party PRIMARY KEY ( ID ) , Name VARCHAR(30) NOT NULL ) ; GO INSERT INTO dbo.Party ( Name ) VALUES ( 'Frodo Baggins' ), ( 'Luke Skywalker' ), ( 'Luke Skywalker' ), ( 'Harry Potter' ) ; GO
讓我們忽略現有的,並確保不能添加新的重複項:
-- Add a new column to mark grandfathered duplicates. ALTER TABLE dbo.Party ADD IgnoreThisDuplicate INT NULL ; GO -- The *first* instance will be left NULL. -- *Secondary* instances will be set to their ID (a unique value). UPDATE dbo.Party SET IgnoreThisDuplicate = ID FROM dbo.Party AS my WHERE EXISTS ( SELECT * FROM dbo.Party AS other WHERE other.Name = my.Name AND other.ID < my.ID ) ; GO -- This constraint is not strictly necessary. -- It prevents granting further exemptions beyond the ones we made above. ALTER TABLE dbo.Party WITH NOCHECK ADD CONSTRAINT CHK_Party_NoNewExemptions CHECK(IgnoreThisDuplicate IS NULL); GO SELECT * FROM dbo.Party; GO -- **THIS** is our pseudo-unique constraint. -- It works because the grandfathered duplicates have a unique value (== their ID). -- Non-grandfathered records just have NULL, which is not unique. CREATE UNIQUE INDEX UNQ_Party_UniqueNewNames ON dbo.Party(Name, IgnoreThisDuplicate); GO
讓我們測試一下這個解決方案:
-- cannot add a name that exists INSERT INTO dbo.Party ( Name ) VALUES ( 'Frodo Baggins' ); Cannot insert duplicate key row in object 'dbo.Party' with unique index 'UNQ_Party_UniqueNewNames'. -- cannot add a name that exists and has an ignored duplicate INSERT INTO dbo.Party ( Name ) VALUES ( 'Luke Skywalker' ); Cannot insert duplicate key row in object 'dbo.Party' with unique index 'UNQ_Party_UniqueNewNames'. -- can add a new name INSERT INTO dbo.Party ( Name ) VALUES ( 'Hamlet' ); -- but only once INSERT INTO dbo.Party ( Name ) VALUES ( 'Hamlet' ); Cannot insert duplicate key row in object 'dbo.Party' with unique index 'UNQ_Party_UniqueNewNames'.