Sql server 2005 如何在SQLServer2005中创建更新前触发器
我是否可以创建一个触发器,该触发器将在更新/删除发生之前执行(然后实际更新/删除发生)?如何从表中删除触发器?要删除触发器-Sql server 2005 如何在SQLServer2005中创建更新前触发器,sql-server-2005,triggers,Sql Server 2005,Triggers,我是否可以创建一个触发器,该触发器将在更新/删除发生之前执行(然后实际更新/删除发生)?如何从表中删除触发器?要删除触发器-请使用数据库名称 IF EXISTS (SELECT name FROM sysobjects WHERE name = 'tgr_name' AND type = 'TR') DROP TRIGGER tgr_name GO 这篇来自微软的文章解释了创建触发器的语法 实际上并没有“before”触发器,但您可以使用一个INSTEAD OF触发器,它允许您跳
请使用数据库名称
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'tgr_name' AND type = 'TR')
DROP TRIGGER tgr_name
GO
这篇来自微软的文章解释了创建触发器的语法 实际上并没有“before”触发器,但您可以使用一个INSTEAD OF触发器,它允许您跳转到尝试的任何操作的位置,然后定义您自己的操作 我已经使用这种技术对数据进行版本控制
CREATE TRIGGER [dbo].[Documents_CreateVersion]
ON [dbo].[Documents]
INSTEAD OF UPDATE
AS
BEGIN
DECLARE @DocumentID int
SELECT DocumentID = DocumentID FROM INSERTED
-- do something
END
“插入”在这里有点用词不当,但它包含了操作发生之前的详细信息,然后您可以使用该数据定义自己的操作
编辑:
根据我下面的回复,如果同时更新多行,我的示例可能会很危险。我的应用程序不允许这种情况,所以在这种情况下可以。我同意,不管怎样,上述做法都是不好的。放弃触发器使用:
--SQL Server 2005+, drop the trigger, no error message if it does not exist yet
BEGIN TRY DROP TRIGGER dbo.TrigerYourTable END TRY BEGIN CATCH END CATCH
GO
--drop trigger pre-SQl Server 2005, no error message if it does not exist yet
if exists (select * from sysobjects where id = object_id(N'[dbo].[TrigerYourTable ]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
drop trigger [dbo].[TrigerYourTable ]
GO
OP在评论中说:
…假设我要查一下孩子的数量
一个特定的用户,如果超过
5不要更新用户。我该怎么办
用它代替触发器
您实际上不需要阻止原始更新,您可以让它发生,然后在触发器中检查问题并在必要时回滚。这是当您需要联接以确定受影响行的childcount
时,如何为一个或多个受影响行强制执行逻辑:
--create the trigger
CREATE TRIGGER dbo.TrigerYourTable ON dbo.YourTable
AFTER UPDATE
AS
SET NOCOUNT ON
IF EXISTS (SELECT
1
FROM INSERTED i
INNER JOIN YourChildrenTable c ON i.ParentID=c.ParentID
GROUP BY i.ParentID
HAVING COUNT(i.ParentID)>5
)
BEGIN
RAISERROR('Count of children can not exceed 5',16,1)
ROLLBACK
RETURN
END
GO
如果违反逻辑,它将抛出错误,并且原始命令将回滚
如果childcount
是受影响表中的一列,则使用如下触发器强制执行逻辑:
--create the trigger
CREATE TRIGGER dbo.TrigerYourTable ON dbo.YourTable
AFTER UPDATE
AS
SET NOCOUNT ON
IF EXISTS (SELECT 1 FROM INSERTED WHERE childcount>5)
BEGIN
RAISERROR('Count of children can not exceed 5',16,1)
ROLLBACK
RETURN
END
GO
如果只想忽略任何违反规则的行的更新,请尝试以下操作:
--create the trigger
CREATE TRIGGER dbo.TrigerYourTable ON dbo.YourTable
INSTEAD OF UPDATE
AS
SET NOCOUNT ON
UPDATE y
SET col1=i.col1
,col2=i.col2
,col3=i.col3
,.... --list all columns except the PK column!
FROM dbo.YourTable y
INNER JOIN INSERTED i on y.PK=i.PK
WHERE i.childcount<=5
GO
——创建触发器
在dbo.YourTable上创建触发器dbo.TrigerYourTable
而不是更新
作为
不计较
更新y
设置col1=i.col1
,col2=i.col2
,col3=i.col3
,.... --列出除PK列以外的所有列!
来自dbo.youry表y
在y.PK上插入的内部联接i=i.PK
其中i.childcount这里有一个简单的触发器,用于检查列值,并在更新或插入之前激发,并引发错误
IF OBJECT_ID ('dbo.MyTableTrigger', 'TR') IS NOT NULL
DROP TRIGGER dbo.MyTableTrigger;
GO
CREATE TRIGGER MyTableTrigger
ON dbo.MyTable
FOR INSERT, UPDATE
AS
DECLARE @Col1ID INT
DECLARE @Col2ID INT
SELECT @Col1ID = Col1ID, @Col2ID = Col2ID FROM inserted
IF ((@Col1ID IS NOT NULL) AND (@Col2ID IS NOT NULL))
BEGIN
RAISERROR ('Col1ID and Col2ID cannot both be in MyTable at the same time.', 16, 10);
END
假设我必须检查特定用户的childcount
,如果超过5
,请不要更新该用户。如何使用而不是触发器进行更新?千万不要以这种方式对触发器进行编码!假设插入的表中只有一行,如果有多行,这将失败。很好。我的特别示例是一个永远不会发生多个更新的表。这是一个坏例子!谢谢。即使应用程序只影响一行,最好总是编写触发器来处理多行。如果在影响所有行的表上运行某个一次性脚本,则(假定一行)触发器将失败。如果对多行等运行手动更新,会怎么样?如果应用程序发生更改怎么办?最好编写一个触发器来接受多行。如果不想,请将代码添加到触发器中,以从插入的计数(*)或从删除的计数(*),如果>1
,则失败。确保“只有一个”由只处理一行的触发器强制执行。在我的应用程序中,这种性质的更新将失败,因为它生成一个返回多个值的子查询,因此无需进行检查。不过,我要说的是,您好,在进行更新删除之前,您需要执行的实际原因是什么?