最初禁用创建唯一约束

时间:2015-07-13 06:53:36

标签: tsql sql-server-2008-r2 unique-constraint unique-index

这是我的表:

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

我的想法是根据客户应用启用/禁用一个或其他独特的约束。通过这种方式,我可以在我的c#代码中捕获抛出的异常,并向GUI显示特定的错误消息。

现在,我的问题是改变列Name1&的整理。 Name2,我需要让它们区分大小写(French_CS_AS)。要更改这些字段,我必须删除这两个约束并重新创建它。根据解释的模式,我无法创建一个启用的约束,然后禁用它,因为有些客户,我有一个或其他约束的重复键。

对于我的更新脚本,我的想法1是

  1. 在临时表中保存已启用约束的名称
  2. 删除约束
  3. 更改列
  4. 创建 DISABLED 唯一约束
  5. 根据点1中保存的值启用特定约束。
  6. 我的问题在第4点。我找不到如何使用ALTER TABLE语句创建禁用的唯一约束。是否可以直接在sys.indexes表中创建它?

    我的想法2是

    1. 将TestTable重命名为TestTableCopy
    2. 使用新字段排序规则重新创建TestTable,否则使用相同的模式(索引,FK,触发器......)
    3. 禁用TestTable中的特定唯一约束
    4. 将数据从TestTableCopy迁移到TestTable
    5. Drop TestTableCopy
    6. 通过这种方式,我担心会丢失与其他表/依赖项的某些链接,因为它是我数据库中的中心表。

      有没有其他方法可以实现我的目标?

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

2 个答案:

答案 0 :(得分:1)

看起来无法在已具有重复值的列上创建唯一索引。

所以,不要使用禁用的唯一索引:

  • 根本没有索引(这与从查询处理器的角度来看具有禁用的索引相同),
  • 或创建非唯一索引。

对于那些客户端具有唯一数据的实例,创建唯一索引。对于那些客户端具有非唯一数据的实例,请创建非唯一索引。

答案 1 :(得分: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。然后,如果您根据约束条件进行插入/更新。