使用约束检查sql唯一值

时间:2011-10-20 20:13:48

标签: sql sql-server-2005 unique unique-constraint check-constraints

我的情况是表有三列ID,值和状态。对于不同的ID,应该只有一个值为1的状态,并且应该允许ID具有多于一个值为0的状态。唯一键将阻止ID具有多于一个状态(0或1)。

有没有办法解决这个问题,可能会使用约束?

由于

7 个答案:

答案 0 :(得分:4)

您可以创建一个索引视图,该视图将维护ID[Status] = 1唯一的约束。

create view dbo.v_YourTable with schemabinding as
select ID
from dbo.YourTable
where [Status] = 1

go

create unique clustered index UX_v_UniTest_ID on v_YourTable(ID)

在SQL Server 2008中,您可以使用唯一的过滤索引。

答案 1 :(得分:1)

如果表格可能有重复的ID值,则检查约束对您的情况不起作用。我认为唯一的方法是使用触发器。如果您正在寻找一个例子,那么我可以发一个。但总而言之,使用触发器来测试插入/更新的ID是否具有在同一ID上重复的状态1。

编辑:您始终可以在IDValue上使用唯一约束。我想这会给你你想要的东西。

答案 2 :(得分:1)

您可以将其放入插入/更新触发器中以检查以确保只有一个组合存在1值;如果您的条件不满足,您可能会抛出一个可捕获的错误并强制操作回滚。

答案 3 :(得分:1)

如果您可以使用NULL而不是0来表示零状态,那么您可以对该对使用UNIQUE约束,它应该可以工作。由于NULL不是实际值(NULL!= NULL),因此具有多个空值的行不应该冲突。

答案 4 :(得分:0)

恕我直言,这基本上是一个规范化问题。名为“id”的列不唯一地寻址一行,因此它永远不会是PK。至少需要一个新的(代理)键(元素)。约束本身不能表达为“在行内”的表达式,因此它必须用FK表示。

所以它分为两个表: 一个PK = id,一个FK REFERENCING two.sid

两个PK =代理键,FK id REFERENCING one.id 原始有效载荷“价值”也存在于此。

“一位变量”消失,因为它可以用EXISTS表示。 (实际上一个表指向持有令牌的行)

[我希望Postgres规则系统可以用来使用上面的两个表模型来模拟OP的预期行为。但那将是一个丑陋的黑客...]

EDIT / UPDATE:

Postgres支持部分/条件索引。 (不知道ms-sql)

DROP TABLE tmp.one;
CREATE TABLE tmp.one
    ( sid INTEGER NOT NULL PRIMARY KEY -- surrogate key
    , id INTEGER NOT NULL
    , status INTEGER NOT NULL DEFAULT '0'
    /* ... payload */
    );
INSERT INTO tmp.one(sid,id,status) VALUES
  (1,1,0) , (2,1,1) , (3,1,0)
, (4,2,0) , (5,2,0) , (6,2,1)
, (7,3,0) , (8,3,0) , (9,3,1)
  ;

CREATE UNIQUE INDEX only_one_non_zero ON tmp.one (id)
    WHERE status > 0 -- "partial index" 
    ;

\echo this should succeed
BEGIN ;
UPDATE tmp.one SET status = 0 WHERE sid=2;
UPDATE tmp.one SET status = 1 WHERE sid=1;
COMMIT;

\echo this should fail
BEGIN ;
UPDATE tmp.one SET status = 1 WHERE sid=4;
UPDATE tmp.one SET status = 0 WHERE sid=9;
COMMIT;

SELECT * FROM tmp.one ORDER BY sid;

答案 5 :(得分:0)

我想出了一个解决方案

首先创建一个函数

CREATE FUNCTION [dbo].[Check_Status] (@ID int)
RETURNS INT
AS
BEGIN
 DECLARE @r INT;
 SET @r =
  (SELECT SUM(status) FROM dbo.table where ID= @ID);
 RETURN @r;
END

其次在表格

中创建约束
([dbo].[Check_Status]([ID])<(2))

通过这种方式,一个ID可以具有单个状态(1)和尽可能多的状态(0)。

答案 6 :(得分:0)

create function dbo.IsValueUnique
(
     @proposedValue varchar(50)
    ,@currentId int
)
RETURNS bit
AS
/*
--EXAMPLE
print dbo.IsValueUnique() -- fail
print dbo.IsValueUnique(null) -- fail
print dbo.IsValueUnique(null,1) -- pass
print dbo.IsValueUnique('Friendly',1) -- pass
*/
BEGIN
    DECLARE @count  bit

    set @count =
    (
        select      count(1)
        from        dbo.MyTable
        where       @proposedValue is not null
        and         dbo.MyTable.MyPkColumn != @currentId
        and         dbo.MyTable.MyColumn = @proposedValue
    )

    RETURN case when @count = 0 then 1 else 0 end
END
GO
ALTER TABLE     MyTable
WITH CHECK
add constraint  CK_ColumnValueIsNullOrUnique
CHECK           ( 1 = dbo.IsValueNullOrUnique([MyColumn],[MyPkColumn]) )
GO