Sql server 在表上设置触发器以限制插入、删除和更新操作的数量

Sql server 在表上设置触发器以限制插入、删除和更新操作的数量,sql-server,triggers,ssms,dml,Sql Server,Triggers,Ssms,Dml,例如:如果用户在给定时间点对特定表执行操作X+1次以上,触发将启动。这不是触发的工作方式。每当对触发器所属的对象运行与触发器相关的DML时,触发器就会“激发”。但这闻起来像是一种味道。为什么您要阻止用户在一秒钟内执行例如20INSERT语句(每个语句影响1行),但允许他们处理3个语句,每个语句影响10000行?或者你只是想阻止人们使用RBAR操作?如果是这样,教他们如何编写基于集合的SQL。实现此场景的目的是限制用户查询可以在表中修改的记录数。这是为了避免由于错误或故意而对表进行大量更新。例如,

例如:如果用户在给定时间点对特定表执行操作X+1次以上,触发将启动。

这不是
触发
的工作方式。每当对触发器所属的对象运行与触发器相关的DML时,
触发器就会“激发”。但这闻起来像是一种味道。为什么您要阻止用户在一秒钟内执行例如20
INSERT
语句(每个语句影响1行),但允许他们处理3个语句,每个语句影响10000行?或者你只是想阻止人们使用RBAR操作?如果是这样,教他们如何编写基于集合的SQL。实现此场景的目的是限制用户查询可以在表中修改的记录数。这是为了避免由于错误或故意而对表进行大量更新。例如,用户将无法对特定表运行批量更新查询或删除查询。老实说,这似乎更像是员工在(愚蠢地)编写语句之前应该检查他们的工作,如
updateyourtable SET IsActive=0,其中IsActive=1。这与插入有什么关系呢?这听起来像是寻找问题的解决方案。我们都可以承认(即使是我们这些有经验的人)我们有时会运行这样的查询,但是,这就是为什么开发和登台环境,首先用选择取代更新是如此重要;我个人建议在触发器中使用
THROW
而不是
ROLLBACK
。事务处理应该在触发器之外完成,您还可以传递一个有用的错误。
create table dbo.targetTable
(
    id int,
    colA varchar(10)
);
go
create or alter trigger dbo.DMLxTimes on dbo.targetTable
for insert, update, delete
as
begin
    /*
        --old days..
        IF @@ROWCOUNT > 5
        begin
            rollback;
        end
    --*/

    declare @maxrows int = 5; --maximum number of rows allowed per dml action

    if 
    (select count(*) from inserted) > @maxrows
    or
    (select count(*) from deleted) > @maxrows
    begin
        rollback;
    end
end
go

insert into dbo.targetTable(id, colA)
values (0, 'a'),(0, 'a'),(0, 'a'),(0, 'a'),(0, 'a'); --5 rows inserted
go
insert into dbo.targetTable(id, colA)
values (0, 'a'),(0, 'a'),(0, 'a'),(0, 'a'),(0, 'a'),(0, 'a'); --6 rows inserted ... error
go
insert into dbo.targetTable(id, colA)
values (0, 'a'),(0, 'a'); --2 rows inserted
go

--all updated, error
update dbo.targetTable
set colA = colA;
go

--ok
update top(5) dbo.targetTable
set colA = colA;
go

delete top (4) from dbo.targetTable;
go

--ok
update top(15) dbo.targetTable
set colA = colA;
go