Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server触发器活动卡_Sql_Sql Server_Database_Triggers - Fatal编程技术网

SQL Server触发器活动卡

SQL Server触发器活动卡,sql,sql-server,database,triggers,Sql,Sql Server,Database,Triggers,我有以下表格: 卡(IDCard、IDPerson、余额、活动) 个人(个人) 每次插入新卡时,我都需要检查该卡是否已经属于某个人。如果是这样的话,我需要将“活动”更改为“假”,并且新卡必须收到上一张卡的余额,并且状态必须为“真” select count(c.IDPerson) from cards c, inserted i where c.IDPerson = i.IDPerson; if @@ROWCOUNT > 0 begin print'this card a

我有以下表格:

  • 卡(IDCard、IDPerson、余额、活动)
  • 个人(个人)
每次插入新卡时,我都需要检查该卡是否已经属于某个人。如果是这样的话,我需要将“活动”更改为“假”,并且新卡必须收到上一张卡的余额,并且状态必须为“真”

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
当我在cards表中插入一条新记录时,旧卡确实会变为false(0),但新卡也会保持active等于false。 这是在卡片表上的后插入


有人能告诉我如何解决这个问题吗?

尽管您的触发器正在事务中运行,但我认为它仍然能够自我更新

当您更新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
我已经创建了一个副本,我相信你在这方面的要求

用户marc_s说您应该在这里使用连接语法也是正确的。您的整个操作可以在一个更简洁的语句中完成

UPDATE c
SET c.Active = 0
FROM Cards c
INNER JOIN Inserted i
ON i.IDPERSON = c.IDPERSON
AND i.IDCARD != c.IDCARD

如果不合适,则使用
。请记住,触发器可以同时处理多行

显式的
join
执行所需的筛选。这有点复杂,但您可以使用两个
join
s来完成:

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;

你想在哪里处理这件事?例如,您的所有插入都将通过SP进行吗?-在ANSI-92 SQL标准(25年前)中,用正确的ANSI
JOIN
语法替换了老式的逗号分隔的表列表样式,并且它的使用非常方便discouraged@Larnu不,不会的。我正在使用常规插入进行测试。插入到值中…您可能希望在此处使用
而不是
触发器,但是,我更愿意控制SP的插入过程,并停止盲目应用模式,而无需特殊原因。当方法具有有益效果时,应选择该方法。在单个语句可以完成所有需要的工作的情况下,此模式通常只会创建额外的工作,而没有任何好处。