如何在sql server 2005中创建更新触发器之前

时间:2010-06-16 09:45:23

标签: sql-server-2005 triggers

无论如何我可以创建一个触发器,它会在更新/删除发生之前执行(然后进行实际的更新/删除)?我怎样才能从表中drop触发?

4 个答案:

答案 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