假设我有一个表Level1
:
Id int PK
Deleted bit
和另一个表Level2
:
Id int
Deleted bit
Level1id int
我可以在FK
上添加Level2
,以使Level1id
与Level1.Id
匹配,这可以确保父项存在。
但是,如果我想确保当INSERTed
中的匹配记录的Level2
位= 0时,只能确保Level1
中的Deleted
记录,该怎么办?
此外,当Deleted
中的任何子记录的Level1
位= 0时,如何防止Level2
中的Deleted
标志被设置为1?
即所有子记录必须具有Deleted
= 1,然后父记录才能具有Deleted
= 1
我猜想我可能必须编写一个触发器,但是希望有一个更优雅的解决方案...
答案 0 :(得分:0)
You can do this with a foreign key constraint, but you need to add some more information.
First a unique constraint that includes the bit:
alter table level1 add constraint unq_level1_id, deleted
unique (delete, id);
Then, add a constant 0
value to level2
alter table level2 add (cast(0 as bit)) as deleted_0 persisted;
Then, add in the foreign key constraint:
alter table level2 add constraint fk_level2_id_deleted
foreign key (level1id, deleted) references table1(id, deleted);
答案 1 :(得分:0)
As mentioned by others, you could implement this logic in an application, or in stored procedures, but to do it in the database, the following functions and CHECK
constraints should give you what you're looking for.
These will only run/check for the row you're interested in when you do an INSERT
/UPDATE
.
CREATE FUNCTION Level1Deleted (@Id int, @Deleted bit)
RETURNS bit
AS
BEGIN
IF @Deleted = 1
RETURN 0
ELSE
RETURN
(
SELECT L1.Deleted
FROM
Level2 L2
JOIN Level1 L1 ON L2.Level1Id = L1.Id
WHERE L2.Id = @Id
)
;
END
GO
ALTER TABLE Level2
WITH CHECK
ADD CONSTRAINT CHK_Level1Deleted
CHECK (Level1Deleted(Id, Deleted) = 0)
GO
CREATE FUNCTION Level2NotFullyDeleted (@Id int, @Deleted bit)
RETURNS bit
AS
BEGIN
IF @Deleted = 0
RETURN 0
ELSE
RETURN
(
SELECT CAST(COUNT(*) AS bit)
FROM
Level1 L1
JOIN Level2 L2 ON L1.Id = L2.Level1id
WHERE
L1.Id = @Id
AND L2.Deleted = 0
)
;
END
GO
ALTER TABLE Level1
WITH CHECK
ADD CONSTRAINT CHK_Level2FullyDeleted
CHECK (Level2NotFullyDeleted(Id, Deleted) = 0)
GO