代码之家  ›  专栏  ›  技术社区  ›  Michael Blackburn

SQL我可以在表上有一个“条件唯一”约束吗?

  •  10
  • Michael Blackburn  · 技术社区  · 16 年前

    在我的职业生涯中,我有过几次这样的经历,而我当地的同龄人似乎都无法回答。假设我有一个表,其中有一个“Description”字段,它是一个候选键,只是有时用户会在过程的中途停止。所以对于25%的记录,这个值是空的,但是对于所有不为空的记录,它必须是唯一的。

    5 回复  |  直到 16 年前
        1
  •  34
  •   Arthur    16 年前

    如果您使用的是SQL Server 2008,则索引筛选器可能是您的解决方案:

    http://msdn.microsoft.com/en-us/library/ms188783.aspx

    CREATE UNIQUE INDEX [IDX_Blah] ON [tblBlah] ([MyCol]) WHERE [MyCol] IS NOT NULL
    
        2
  •  3
  •   Tom H zenazn    16 年前

    对于尚未完成的描述,我不会将它们与最终确定的描述放在同一个表中。最后一个表将在描述上有一个唯一的索引或主键。

    CREATE TABLE Test_Conditionally_Unique
    (
        my_id   INT NOT NULL,
        active  BIT NOT NULL DEFAULT 0
    )
    GO
    CREATE VIEW dbo.Test_Conditionally_Unique_View
    WITH SCHEMABINDING
    AS
        SELECT
            my_id
        FROM
            dbo.Test_Conditionally_Unique
        WHERE
            active = 1
    GO
    CREATE UNIQUE CLUSTERED INDEX IDX1 ON Test_Conditionally_Unique_View (my_id)
    GO
    
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (1, 0)
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (1, 0)
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (1, 0)
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (1, 1)
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (2, 0)
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (2, 1)
    INSERT INTO dbo.Test_Conditionally_Unique (my_id, active)
    VALUES (2, 1)    -- This insert will fail
    

    您也可以对空/值描述使用相同的方法。

        3
  •  0
  •   Andomar    16 年前

    下面是一个技巧,使用计算列可以有效地在SQL Server中允许可为null的唯一约束:

    create table NullAndUnique 
        (
        id int identity, 
        name varchar(50),
        uniqueName as case 
            when name is null then cast(id as varchar(51)) 
            else name + '_' end,
        unique(uniqueName)
        )
    
    insert into NullAndUnique default values
    insert into NullAndUnique default values -- Works
    insert into NullAndUnique default values -- not accidentally :)
    insert into NullAndUnique (name) values ('Joel')
    insert into NullAndUnique (name) values ('Joel') -- Boom!
    

    它基本上使用 id 当 name 为空。这个 + '_' 是为了避免名称可能是数字的情况,比如 1 ,可能会与 身份证件 .

        4
  •  0
  •   KM.    16 年前

    我不完全清楚您的预期用途或表,但您可以尝试使用一对一关系。将这个“有时”唯一的列拆分为一个新表,在新表中的该列上创建唯一索引,并使用原始表PK将FK返回到原始表。只有当“唯一”数据应该存在时,才在这个新表中有一行。

    TableA
    ID    pk
    Col1  sometimes unique
    Col...
    

    新表:

    TableA
    ID
    Col...
    
    TableB
    ID   PK, FK to TableA.ID
    Col1 unique index
    
        5
  •  -1
  •   Adam Musch    16 年前

    甲骨文有。完全空的键不由B索引 Oracle中的索引树,Oracle使用B 树索引以强制唯一约束。

    CREATE UNIQUE INDEX idx_versioning_id ON mytable 
      (CASE active_flag WHEN 0 THEN NULL ELSE active_flag END,
       CASE active_flag WHEN 0 THEN NULL ELSE id_column   END);
    
    推荐文章