我想创建修改现有触发器的过程。触发器负责阻止使用特定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”附近的语法不正确。
触发器已创建。
答案 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
之前,因为它们是设计的来保持多个但是它会为这个答案添加更多的代码。