Ali*_*n I 1 sql sql-server sql-server-2008-r2
我有一张桌子
PKID FID RESULT
======================
1 1 1
2 1 2
3 1 2
4 1 3
4 2 1
4 2 1
Run Code Online (Sandbox Code Playgroud)
我正在尝试设置一个约束,这样如果已存在FID = 1且RESULT = 3的记录,我就无法在表中插入另一条FID = 1的记录.
我试图创建这样的函数
CREATE FUNCTION MyCheck
(
-- Add the parameters for the function here
@FID int
)
RETURNS bit
AS
BEGIN
IF EXISTS (SELECT PKID FROM MyTable WHERE (RESULT= 3) AND (FID= @FID))
return 1
return 0
END
Run Code Online (Sandbox Code Playgroud)
但是当我使用这个函数创建约束时:
ALTER TABLE MyTable
WITH CHECK ADD CONSTRAINT CK_Code
CHECK (MyCheck(FID) = 0)
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
ALTER TABLE语句与CHECK约束"CK_Code"冲突.冲突发生在数据库"MyDB",表"MyTable",列'FID'中.
有了更新/澄清,是的,我们现在必须使用触发器1.我们不能再声明,因为没有办法查看一组数据,比如说:
FID RESULT
==============
1 1
1 3
1 2
1 2
2 1
2 1
Run Code Online (Sandbox Code Playgroud)
并确定该数据是否合法.如果行是插入的最后一行,则是合法的(1,3).这是不是合法的,如果任何其他行的FID的1是插入的最后一行.
那么,触发它是:
CREATE TRIGGER T_PreventBadInsert
ON MyTable
AFTER INSERT
AS
SET NOCOUNT ON;
IF EXISTS(select * from inserted i inner join MyTable m
on i.PK <> m.PK and i.FID = m.FID
and m.Result = 3)
BEGIN
RAISERROR('Cannot insert a new row once one row has result 3',16,1);
ROLLBACK;
END
Run Code Online (Sandbox Code Playgroud)
请注意,INSERT如果一行违反了要求,这将中止整个语句.它也将中止一个INSERT试图添加两行相同FID,其中一个排的有RESULT3个.
我们可能还想编写一个更新触发器,禁止更改FID任何现有行的值或执行类似的检查,但我不知道您的要求是什么.
如果您使用的是SQL Server 2008或更高版本,则只需过滤索引即可:
CREATE UNIQUE INDEX IX_Max1Result3 ON MyTable (FID) WHERE Result = 3
Run Code Online (Sandbox Code Playgroud)
(并且你的函数/检查不起作用,因为那里没有任何东西可以阻止一行将自己当作"现有"行)
1有一个强有力的词.可能还有其他方法,但我认为触发器可能是最简单的方法.