来自另一个表的带有循环的 SQL 触发器
Posted
技术标签:
【中文标题】来自另一个表的带有循环的 SQL 触发器【英文标题】:SQL Trigger with loop from another table 【发布时间】:2021-08-29 08:13:50 【问题描述】:我有 2 张桌子:
表 A
create table A
(id int identity(1,1)
,KeyWord1 nvarchar(50)
,KeyWord2 nvarchar(50)
,KeyWord3 nvarchar(50)
)
表 B
Create table B
(id int identity(1,1)
,Address nvarchar(150)
,Chk int
)
表 A 包含以下值:
insert into A
values
(166, 'elyse', 'vry')
,(243, 'virginia', 'beach')
,(134, 'aris', 'adium')
表 B 包含以下值:
insert into B
values
('35 stadium street, 134 Paris', null)
,('243, Stadiumù road from Paris', null)
当在表 B 上创建新行时,我的目标是使用表 A 中的出现次数设置列 B.chk。
例如:
insert into B
values
('166, road to Champs elysee - 14215 Cdx Evry', null)
表 B 上的触发器应将 B.Chk 设置为 1,因为以下查询与表 A 匹配
select count(*) from inserted
where b.Address like '%166%'
and b.Address like '%elyse%'
and b.Address like '%vry%'
为此,我应该在表 B 上创建一个触发器,但不知道如何在另一个表上“循环”。 我应该使用 for、while 还是 cursor?
【问题讨论】:
循环是什么意思,你打算循环什么? SQL 是声明性语言,它接受带有where
条件的select
语句并返回没有循环的答案
样本数据,以及应该匹配和不匹配的示例将非常有帮助。
触发器几乎总是一个坏主意。您真的需要立即填充此字段吗?还是您只是想生成一份报告来确定这一点?
不需要循环,但如果你不需要在触发器中进行非sargable查找对其性能没有好处 列立即更新,您应该定期安排此过程。 tag您的特定数据库平台。
是的,我需要一个触发器,因为该列的值将从另一个应用程序启动工作流。
【参考方案1】:
您的触发器需要被构造为将inserted
虚拟表视为一个集合,就像在任何其他 SQL 语句中一样。
您不需要也不应该使用局部变量来保存触发器中的值,因为触发器对受影响的行集进行操作。
请尝试以下方法:
create or alter trigger TR_Update_B
on dbo.B
after insert
as
set nocount on;
with t as (
select i.id, Count(*) qty
from inserted i
join a on
i.Address like '%' + a.KeyWord1 + '%'
and i.Address like '%' + a.KeyWord2 + '%'
and i.Address like '%' + a.KeyWord3 + '%'
group by i.id
)
update b set
b.chk=t.qty
from t
join b on b.id=t.id;
【讨论】:
【参考方案2】:你说得对,我不需要循环,但插入后需要立即设置 chk 列。
这是我的触发器:
Create trigger TR_Update_B
ON dbo.B
AFTER insert
AS
BEGIN
SET NOCOUNT ON;
DECLARE @docNo int
DECLARE @Result int
SELECT @DocNo=id FROM inserted;
SET @Result= (select count(*) from b
join a
on b.Address like '%'+a.KeyWord1+'%'
and b.Address like '%'+a.KeyWord2+'%'
and b.Address like '%'+a.KeyWord3+'%'
where b.id=@DocNo)
Update b set Chk = @Result where id=@DocNo
END
【讨论】:
从这里我可以看到你想要做什么。不幸的是,您创建了一个具有经典且常见缺陷的触发器,因为您的触发器假定不会插入超过一行。如果插入 2 行,@docNo
的值是多少?触发器每条语句触发 一次,因此如果您插入 10 行,它将运行一次,@docNo
将是一个(随机)Id
。以上是关于来自另一个表的带有循环的 SQL 触发器的主要内容,如果未能解决你的问题,请参考以下文章
SQL语句循环一张表的一个字段ID,根据这个字段的内容去修改另一张表,