我的情况是表有三列ID,值和状态。对于不同的ID,应该只有一个值为1的状态,并且应该允许ID具有多于一个值为0的状态。唯一键将阻止ID具有多于一个状态(0或1)。
有没有办法解决这个问题,可能会使用约束?
由于
答案 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。
编辑:您始终可以在ID
和Value
上使用唯一约束。我想这会给你你想要的东西。
答案 2 :(得分:1)
您可以将其放入插入/更新触发器中以检查以确保只有一个组合存在1值;如果您的条件不满足,您可能会抛出一个可捕获的错误并强制操作回滚。
答案 3 :(得分:1)
如果您可以使用NULL而不是0来表示零状态,那么您可以对该对使用UNIQUE约束,它应该可以工作。由于NULL不是实际值(NULL!= NULL),因此具有多个空值的行不应该冲突。
答案 4 :(得分:0)
所以它分为两个表: 一个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