Sql 修改现有触发器的过程
我想创建修改现有触发器的过程。触发器负责阻止使用特定ID更新的行。我尝试了以下方法:Sql 修改现有触发器的过程,sql,sql-server,database,Sql,Sql Server,Database,我想创建修改现有触发器的过程。触发器负责阻止使用特定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 raiserr
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_id如下:2,3,4,5,9,52。但当我尝试创建此过程时,出现了错误:
Msg 156,15级,状态1,程序更改触发,第4行
关键字“触发器”附近的语法不正确
触发器已创建。请尝试此操作
CREATE PROCEDURE Change_trigger
@List_of_ids varchar(4000)
AS
begin
declare @sql varchar(8000)
set @sql ='
ALTER TRIGGER blocks
ON ttt
INSTEAD OF update
AS
BEGIN
if exists (SELECT Id_ttt FROM inserted where Id_ttt 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' ;
exec (@sql);
END
这是我要写的触发器,一次
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;
正如我在上面提到的,我通常建议不要使用XML,或者在使用varchar之前使用它们中的任何一个,因为它们被设计用来保存多个值,但它会为这个答案添加更多的代码。与其不断修改触发器,为什么不只使用一个包含触发器随后引用的禁用ID的表呢?然后,如果需要这个过程,这个过程就可以填充这个表。顺便说一句,SQLServer内置了用于处理多值表值参数XML的类型。瓦查尔不是他们中的一员,而且你的扳机坏了。IN运算符要求其左侧有一个标量值。当inserted包含多行时,触发器将生成一个错误。当然,一次更新可能会影响阻止列表中的某些行,而不影响阻止列表中的某些行。你想如何处理这种情况?目前,所有这些更新都将被拒绝,但这是你想要的,还是仅仅是你制作这个触发器的一个意外呢?@Damien_the_unsiver,谢谢你的评论。那么,如何在一个查询中处理多行更新?当我想保持触发器的状态时,只是阻止特定的ID?您还打算在其他表中存储被禁止的ID。很有趣。但我需要过程,因为这个阻塞ID会改变。我需要过程,因为这个阻塞ID会改变——而不是改变表中的值有多困难?也就是说,数据库一直在做的事情?因此,我会让另一个表包含阻塞ID。触发器将在更新/删除子句之前检查,而不是检查更新ID是否在该表中,如果是-消息,如果不是-更新。我将有一个带有参数的过程/函数,用于在该表中添加或删除ID。对吗?太好了,程序已经创建好了。但是当我尝试执行它时,我得到了这个错误:Msg 102,级别15,状态1,过程更改,第40行,对象Id_ttt附近的语法不正确。。我使用以下命令执行:exec Change_trigger@List_of_Id='2,4,6'从插入的Id_ttt中选择Id_ttt,其中Id_ttt位于@List_of_Id中。这是正确的systax吗?您不能只查询。你可能正在寻找存在。此外,Xardas报告的错误可能仅通过为触发器的开始添加匹配的结束来修复。编辑了答案。我错过了@Damien_不信者感谢我不用创建过程,我可以直接从我的应用程序中添加/删除ttt_阻塞表中的行,对吗?我不需要procedure@XardasLord-是的,这就是为什么我在回答中提到是否有必要,或者在评论中是否需要这个过程。我有一个问题,有没有办法保持这样的条件:如果将SELECT Id\u ttt FROM插入SELECT Id\u ttt FROM ttt\u blocked并在记录被阻止时显示错误消息?但我指的是更新几行的查询。插入一些循环或其他内容?或者使用允许混合更新的update语句-如果记录被阻止,是否有方法显示消息?