2015-07-13 151 views
2

這是我的表:創建唯一約束最初禁用

CREATE TABLE [dbo].[TestTable] 
(
    [Name1] varchar(50) COLLATE French_CI_AS NOT NULL, 
    [Name2] varchar(255) COLLATE French_CI_AS NULL, 
    CONSTRAINT [TestTable_uniqueName1] UNIQUE ([Name1]), 
    CONSTRAINT [TestTable_uniqueName1Name2] UNIQUE ([Name1], [Name2]) 
) 

ALTER TABLE [dbo].[TestTable] 
ADD CONSTRAINT [TestTable_uniqueName1] 
UNIQUE NONCLUSTERED ([Name1]) 

ALTER TABLE [dbo].[TestTable] 
ADD CONSTRAINT [TestTable_uniqueName1Name2] 
UNIQUE NONCLUSTERED ([Name1], [Name2]) 
GO 

ALTER INDEX [TestTable_uniqueName1] 
    ON [dbo].[TestTable] 
    DISABLE 
GO 

我的想法是使/取決於客戶應用禁用一個或其他唯一contraint。通過這種方式,我可以捕捉到我的c#代碼中拋出的異常,並向GUI顯示特定的錯誤消息。現在

,我的問題是改變列Name1 & Name2的整理,我需要讓他們區分大小寫(French_CS_AS)。要改變這些字段,我必須刪除這兩個約束並重新創建它。根據解釋的模式,我不能創建一個啓用的約束,然後禁用它,因爲有些客戶,我有一個或其他約束的重複鍵。

對於我的更新腳本,我的想法號碼1是

  1. 保存在臨時表
  2. 降啓用的約束的約束
  3. 阿爾特列
  4. 創建禁用唯一約束名稱
  5. 根據保存的值以點1啓用特定約束。

我的問題是在第4點,我找不到如何使用ALTER TABLE語句創建禁用的唯一約束。是否有可能直接在sys.indexes表中創建它?

我的想法號2是

  1. 重命名TestTable的到TestTableCopy
  2. 重新創建TestTable的新欄整理,否則相同的架構(索引,FK,觸發器,...)
  3. 禁用在TestTable的特異性目的唯一約束上
  4. 從TestTableCopy數據遷移到TestTable的
  5. 降TestTableCopy

以這種方式,我擔心的是鬆散與其他表/相關性的鏈接,因爲它是我數據庫中的中心表。

有沒有其他辦法可以實現我的目標?

如有必要,我可以使用唯一索引而不是唯一約束。

+0

爲什麼不能忘記Unique約束並檢查自己並在向表中添加記錄時捕獲異常? – CiucaS

+0

因爲可以從多種方式插入記錄(使用t-sql,從我的c#應用程序中...)。我希望數據庫檢查我的數據。 – stephanejulien

+0

創建存儲過程以將記錄插入到表中,可以將它用於所有需要的插入類型。在存儲過程中,根據需要檢查約束。那將是我會這樣做的方式。改變表格不是一個好習慣。 – CiucaS

回答

1

看起來不可能在已具有重複值的列上創建唯一索引。

所以,而不是具有禁用唯一索引或者:

  • 不具有索引(此時是與具有從視查詢處理器點禁用指數),
  • 或創建一個非唯一索引。

對於那些您的客戶擁有唯一數據的實例創建唯一索引。對於那些客戶擁有非唯一數據的實例,可以創建非唯一索引。

+0

你是對的!我以許多方式搜索,無法創建禁用的唯一約束或禁用的唯一索引。我的解決方案是放棄我的約束,改變我的列,並只重新創建最初啓用的那些。 – stephanejulien

0
CREATE PROCEDURE [dbo].[spUsers_AddUsers] 
@Name1 varchar(50) , 
@Name2 varchar(50) , 
@Unique bit 
AS 

declare @err int 
begin tran 
    if @Unique = 1 begin 
if not exists (SELECT * FROM Users WHERE Name1 = @Name1 and Name2 = @Name2) 
begin 
    INSERT INTO Users (Name1,Name2) 
    VALUES (@Name1,@Name2) 
    set @err = @@ERROR 
end else 
begin 
    UPDATE Users 
    set Name1 = @Name1, 
    Name2 = @Name2 
    where Name1 = @Name1 and Name2 = @Name2 
    set @err = @@ERROR 
end 

end else begin 
    if not exists (SELECT * FROM Users WHERE Name1 = @Name1) 
    begin 
     INSERT INTO Users (Name1,Name2) 
     VALUES (@Name1,@Name2) 
     set @err = @@ERROR 
    end else 
    begin 
    UPDATE Users 
    set Name1 = @Name1, 
     Name2 = @Name2 
    where Name1 = @Name1 
    set @err = @@ERROR 
end 


if @err = 0 commit tran 
    else rollback tran 

因此,首先檢查是否需要唯一的Name1和Name2或Name1。然後,如果你根據你的限制進行插入/更新。

+0

我瞭解你的方法,但只有在我無法更改我的表時纔會考慮。我的所有數據庫都設計有限制,我認爲這不是一個壞方法。 – stephanejulien

+0

事實並非如此,我一直都在使用約束條件,並且它們在每個數據庫中都是非常重要的部分,但是您的情況似乎有些過時,並且我從來沒有遇到它(每次都必須更改約束條件)。 – CiucaS