我想创建修改现有触发器的过程。触发器负责阻止使用特定 ID 更新的行。我试过类似的东西:
CREATE PROCEDURE Change_trigger
@List_of_ids varchar(8000)
AS
ALTER TRIGGER blocks
ON ttt
INSTEAD OF update
AS
BEGIN
If (SELECT Id_ttt FROM inserted) IN (@List_of_ids)
BEGIN
raiserror('You cannot modify this record.', 12, 1)
RETURN
END
UPDATE ttt
SET
field1 = INSERTED.field1
FROM INSERTED
WHERE INSERTED.Id_ttt = ttt.Id_ttt
END
参数 @List_of_ids
将是这样的:2,3,4,5,9,52
。但是,当我尝试创建此过程时出现错误:
Msg 156, Level 15, State 1, Procedure Change_trigger, Line 4
Incorrect syntax near the keyword 'TRIGGER'.
触发器已创建。
最佳答案
这是我写过的触发器。
ALTER TRIGGER blocks
ON ttt
INSTEAD OF update
AS
BEGIN
SET NOCOUNT ON
UPDATE t
SET
field1 = i.field1
FROM INSERTED i
inner join
ttt t
on i.Id_ttt = t.Id_ttt
left join
ttt_blocked on tb
on
i.Id_ttt = tb.Id_ttt
WHERE
tb.Id_ttt is null
END
请注意,此触发器不再为被阻止的更新抛出错误,但它确实允许发生混合更新(一些行被阻止,一些行没有)。没有一种干净的方法可以在仍然部分应用触发器中的更新的同时引发错误。
然后我会有一个表(上面引用):
CREATE TABLE ttt_blocked (
Id_ttt int not null,
constraint PK_ttt_blocked PRIMARY KEY (Id_ttt)
)
然后,如有必要,我将创建一个过程来维护此表,而不是不断更改数据库架构:
CREATE PROCEDURE Change_blocking
@BlockedIDs xml
AS
--Better option would be table-valued parameters
--but I've chosen to do XML today
--We expect the XML to be of the form
--<blocks>
-- <id>10</id>
-- <id>15</id>
--</blocks>
MERGE INTO ttt_blocked t
USING (select x.id.value('text()[1]','int')
from @BlockedIDs.nodes('/blocks/id') x(id)) s(Id_ttt)
ON
t.Id_ttt = s.Id_ttt
WHEN NOT MATCHED THEN INSERT (Id_ttt) VALUES (s.Id_ttt)
WHEN NOT MATCHED BY SOURCE THEN DELETE;
正如我在上面提到的,我通常会推荐 Table-Valued Parameters而不是 XML(它们中的任何一个都在 varchar
之前,因为它们被设计以保存多个值)但它会为此答案添加更多代码。
关于sql - 修改现有触发器的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35147997/