Sql-Server

我可以添加一個忽略現有違規的唯一約束嗎?

  • July 8, 2020

我有一個表,該表目前在一列中有重複的值。

我無法刪除這些錯誤的重複項,但我想防止添加其他非唯一值。

我可以創建一個UNIQUE不檢查現有合規性的文件嗎?

我曾嘗試使用NOCHECK但不成功。

在這種情況下,我有一個將許可資訊與“CompanyName”聯繫起來的表

**編輯:**具有相同“公司名稱”的多行是錯誤數據,但我們目前無法刪除或更新這些重複項。一種方法是讓INSERTs 使用一個儲存過程,該過程會因重複而失敗……如果可以讓 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'.

引用自:https://dba.stackexchange.com/questions/43823