修改现有触发器的过程

时间:2016-02-02 08:05:17

标签: 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
          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
  关键字“TRIGGER”附近的语法不正确。

触发器已创建。

2 个答案:

答案 0 :(得分:1)

试试这个..

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

答案 1 :(得分:1)

这是我写过的触发器。

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之前,因为它们是设计的来保持多个但是它会为这个答案添加更多的代码。