Sql 修改现有触发器的过程

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

我想创建修改现有触发器的过程。触发器负责阻止使用特定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_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语句-如果记录被阻止,是否有方法显示消息?