Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2005 如何在SQLServer2005中创建更新前触发器_Sql Server 2005_Triggers - Fatal编程技术网

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
,则失败。确保“只有一个”由只处理一行的触发器强制执行。在我的应用程序中,这种性质的更新将失败,因为它生成一个返回多个值的子查询,因此无需进行检查。不过,我要说的是,您好,在进行更新删除之前,您需要执行的实际原因是什么?