我有下表:
每次插入新卡时,我都需要检查该卡是否已经属于某个人。如果是这样,我需要将active更改为false,新卡必须收到前一张卡的余额,并且状态必须为true。
select count(c.IDPerson)
from cards c, inserted i
where c.IDPerson = i.IDPerson;
if @@ROWCOUNT > 0
begin
print'this card already exists'
select c.IDPerson, c.Balance, c.Active
INTO #tmp
FROM Cards c, inserted i
where c.IDCard = i.IDCard
update Cards
set Active = 0
from #tmp
where #tmp.IDPerson = Cards.IDPerson;
end
当我在卡表中插入新记录时,旧卡确实变为假(0),但是新卡也保持活动状态,等于假。 这是在插入卡片后的表格中。
有人可以告诉我如何解决该问题吗?
答案 0 :(得分:2)
尽管触发器在事务中运行,但我认为它仍然能够更新自身。
当您更新INSERTED.IDPERSON = CARD.IDPERSON的位置时-这包括您已插入的记录;因此所有记录都更新为Active = false。
相反,您应该这样做
update Cards
set Active = 0
from #tmp
where #tmp.IDPerson = Cards.IDPerson
AND Cards.IDCARD != #tmp.IDCARD --This is the new condition
我已经创建了一份我相信您在此DBFiddle Link
中询问的内容的副本用户marc_s也正确地说您应该在此处使用JOIN语法。您的整个操作可以用一个简洁得多的语句完成
UPDATE c
SET c.Active = 0
FROM Cards c
INNER JOIN Inserted i
ON i.IDPERSON = c.IDPERSON
AND i.IDCARD != c.IDCARD
答案 1 :(得分:0)
if
是不合适的。请记住,触发器可以同时处理多行。
显式join
执行所需的过滤。这有点复杂,但是您可以使用两个join
来做到这一点:
update c2
set Active = (case when c2.IDCard = i.IDCard then 1 else 0 end)
from Cards c
inserted i
on c.IDCard = i.IDCard join
Cards c2
on c.IDPerson = c2.IDPerson;