无论如何我可以创建一个触发器,它会在更新/删除发生之前执行(然后进行实际的更新/删除)?我怎样才能从表中drop
触发?
答案 0 :(得分:1)
microsoft的这篇文章解释了创建触发器的语法。
http://msdn.microsoft.com/en-us/library/ms189799.aspx
没有真正的'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
INSERTED在这里有点用词不当,但它包含动作发生之前的详细信息,然后您可以使用该数据定义自己的动作。
修改强>
根据我的回复下面的评论,如果一次更新多行,我的示例可能会很危险。我的申请不允许这样做,所以在这种情况下它很好。无论如何,我都同意以上是不好的做法。
答案 1 :(得分:1)
删除触发器使用:
--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不要更新用户。我可以做什么 使用而不是触发?
你真的不需要阻止原始更新,你可以让它发生,然后在触发器中检查问题并在必要时回滚。当您需要JOIN来确定受影响行的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
它只会更新子计数小于5的行,忽略所有不符合要求的受影响行(无错误消息)。
答案 2 :(得分:0)
删除触发器 - use database_name
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'tgr_name' AND type = 'TR')
DROP TRIGGER tgr_name
GO
答案 3 :(得分:0)
这是一个简单的触发器,用于检查列值,并在更新或插入之前触发,并引发错误。
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