sql - tSQL触发器逻辑,有IF子句更好,还是IN子句更好?

标签 sql sql-server triggers sql-server-2012

我一直在尝试创建触发器来减少需要编写的客户端代码。我编写了以下两个 tSQL 触发器,它们似乎都产生相同的结果,我只是想知道哪一个是更正确的方法。如果这有什么区别的话,我正在使用 SQL Server 2012。

  • 哪一个使用的资源较少
  • 执行速度更快
  • 更安全地抵御攻击
  • 等等...
CREATE TRIGGER tr_ProductGroup_INSERT_GroupMap
    ON [qmgmt].[dbo].[ProductGroup]
    After INSERT
AS
BEGIN
    if (
           select count([inserted].[groupID]) 
           from [inserted] 
           where [inserted].[groupID] = 1
       ) = 0
    begin
        insert into [qmgmt].[dbo].[GroupMap]([parentGroupID], [childGroupID])
        select  1, [inserted].[groupID]
        from [inserted]
    end
END
GO


CREATE TRIGGER tr_ProductGroup_INSERT_GroupMap
    ON [qmgmt].[dbo].[ProductGroup]
    After INSERT
AS
BEGIN
    insert into [qmgmt].[dbo].[GroupMap]([parentGroupID], [childGroupID])
    select  1, [inserted].[groupID]
    from [inserted]
    Where[inserted].[groupID] in 
        (
            select [inserted].[groupID] 
            from [inserted] 
            where [inserted].[groupID] <> 1
        )
END
GO

更新:

根据这里的一些评论,我正在使用插入内容。无论我使用哪个触发器,GroupMap 表都有相同的结果。

insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('root', 'The root of all groups')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('orphans', 'This is where the members of deleted groups go')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('SMGMT', 'Support Management')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('ST1', 'Support Tier 1')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('ST2', ' Support Tier 2')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('ST3', 'Support Tier 3')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('SaaSMGMT', 'Express Management')
insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) values ('SaaSSup', 'Support Express')

最佳答案

由于评论太小,无法放入此示例,因此我将其放入答案中。人们说您的触发器在功能上不同的原因是,尽管您的测试逐行插入,但当您在一次操作中将多行插入表中时,触发器也会触发。根据您的示例,您可以尝试以下操作:

insert into [qmgmt].[dbo].[ProductGroup]([groupName], [groupDescription]) 
SELECT 'root', 'The root of all groups'
UNION ALL
SELECT 'orphans', 'This is where the members of deleted groups go'
UNION ALL
SELECT 'SMGMT', 'Support Management'

执行此查询时,inserted 表将保存 3 行,并且(取决于数据)2 个触发器代码示例的结果可能会给出不同的结果。

别担心,这是一个常见的误解。 SQL 的经验法则是始终考虑记录集,而不是“带有字段的单个记录”。


至于你的问题(是的,我想要一个真正的答案=)

我建议对第二个进行变体。

CREATE TRIGGER tr_ProductGroup_INSERT_GroupMap
    ON [qmgmt].[dbo].[ProductGroup]
    After INSERT
AS
BEGIN
    insert into [qmgmt].[dbo].[GroupMap]([parentGroupID], [childGroupID])
    select  1, [inserted].[groupID]
    from [inserted]
   where [inserted].[groupID] <> 1        
END

这样,服务器只需运行一次inserted,决定“保留”哪些记录,然后立即将它们存储到目标表中。

现在的问题是,这是否符合您的要求......

关于sql - tSQL触发器逻辑,有IF子句更好,还是IN子句更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22967608/

相关文章:

mysql - 使用 Sakila 的子查询问题

MySql 使用连接时是否绝对需要使用带有列名的表别名?

php - 选择字段名称中的一个值出现在多行中的行

sql - 选择相关表中具有一定行数的行数

sql - 空字符串查询的 Coldfusion 查询

sql-server - 使用输出参数执行存储过程?

sql-server - 将数据库和 Web 服务器分开时,RDS 性能真的很差吗?

sql - 更高效的SQLite触发器来“汇总”多行

mysql - 是否可以创建在任何表中的任何插入时触发的触发器?

Postgresql 分区表删除触发器失败