如何添加" IF NOT NOT EXISTS"创建触发器语句

时间:2015-01-29 21:52:00

标签: sql sql-server tsql if-statement triggers

我使用的是sql server 2008 R2。更具体地说,Microsoft SQL Server 2008 R2(RTM) - 10.50.1600.1(X64)2010年4月2日15:48:46版权所有(c)Windows NT 6.1上的Microsoft Corporation标准版(64位)(Build 7601:Service Pack 1) )(管理程序)。我是sql server和procedures / triggers的新手。我有以下代码来创建一个触发器(它工作):

CREATE TRIGGER [dbo].[Insert_WithdrawalCodes] 
   ON  [dbo].[PupilWithdrawalReason] 
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;
        UPDATE [dbo].[PupilWithdrawalReason] SET DateCreated=dbo.SYSTEMTIME() 
        WHERE WithdrawalCodeID IN (SELECT WithdrawalCodeID FROM inserted)
END

如果触发器尚不存在,我如何有条件地创建?我在这做错了什么? Stackoverflow有很好的例子"如果不存在",但我不能让它与CREATE一起工作。这是我失败的努力之一:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'TR' AND name = 'Insert_WithdrawalCodes')
   exec('CREATE TRIGGER [dbo].[Insert_WithdrawalCodes] ON  [dbo].[PupilWithdrawalReason] AFTER INSERT AS BEGIN SET NOCOUNT ON; UPDATE [dbo].[PupilWithdrawalReason] SET DateCreated=dbo.SYSTEMTIME() WHERE WithdrawalCodeID IN (SELECT WithdrawalCodeID FROM inserted) END')
GO

5 个答案:

答案 0 :(得分:62)

IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[TRIGGERNAME]'))
DROP TRIGGER [dbo].[TRIGGERNAME]
go
IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[TABLENAME]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
CREATE   TRIGGER [dbo].[TRIGGERNAME] ON [dbo].[TABLENAME] FOR INSERT, UPDATE 

AS ...

END

根据您更新的问题...试试这个:

IF NOT EXISTS (select * from sys.objects where type = 'TR' and name = 'Insert_WithdrawalCodes')
EXEC dbo.sp_executesql @statement = N'

CREATE TRIGGER [dbo].[Insert_WithdrawalCodes] 
   ON  [dbo].[PupilWithdrawalReason] 
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;
        UPDATE [dbo].[PupilWithdrawalReason] SET DateCreated=dbo.SYSTEMTIME() 
        WHERE WithdrawalCodeID IN (SELECT WithdrawalCodeID FROM inserted)
END


 '

答案 1 :(得分:12)

最好的方法是检查对象,如果它们存在则删除它们,然后再创建它们。

相反,如果它存在则根本不创建它,我会以另一种方式接近它,如果存在则删除它然后创建。

通常在长度较长的脚本中,如果要更新触发器的定义,只需在该脚本的末尾添加它,您的触发器定义就会更新。

因此,方法应为create the object but drop it if it already exists,而不是dont create it at all if it already exists

IF OBJECT_ID ('[Insert_WithdrawalCodes] ', 'TR') IS NOT NULL
   DROP TRIGGER [Insert_WithdrawalCodes];
GO

CREATE TRIGGER .......

答案 2 :(得分:7)

某些语句(如CREATE TRIGGER)需要成为批处理中的第一个语句(例如,由GO分隔的语句组)。

https://msdn.microsoft.com/en-us/library/ms175502.aspx

或者你可以这样做

IF NOT EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   type = 'TR'
                    AND name = 'Insert_WithdrawalCodes' ) 
BEGIN
    EXEC ('CREATE TRIGGER Insert_WithdrawalCodes ON ...');
END;

答案 3 :(得分:1)

正如上面的其他答案中没有提到的重点,我写了这个答案:

  • 当我们想在sys.objects表中查找触发器或其他对象时,最好在where子句中准确地检查(使用架构或object_id等),以避免同名无效结果。 考虑一下另一个模式中何时已经存在另一个具有相同名称的触发器... 因此,由于sys.object表包含一个schema_id列,因此我们可以使用nametype列之外的其他列来更准确地进行查询,如下面的示例所示。 / p>

  • 正如Microsoft文档在“触发器限制”下提到的here

  

CREATE TRIGGER必须是批处理中的第一条语句,并且可以应用   只能放在一张桌子上。

因此,我们使用EXECUTE来克服此限制:

IF NOT EXISTS (select * from sys.objects where schema_id=SCHEMA_ID('dbo') AND type='TR' and name='Insert_WithdrawalCodes')
BEGIN
   EXECUTE ('CREATE TRIGGER [Insert_WithdrawalCodes] ON [dbo].[PupilWithdrawalReason]
   AFTER INSERT
   AS 
   BEGIN
      SET NOCOUNT ON;
      ...
   END');
END

答案 4 :(得分:0)

检查IF是否存在触发

IF EXISTS (SELECT * FROM sys.objects WHERE [name] = 
                 N'[Trigger_Name]' AND [type] = 'TR')
 BEGIN
 DROP TRIGGER [Trigger_Name]
 Print('Trigger dropped => [Schema].[Trigger_Name]')
 END
 GO

检查存在过程的IF存在,功能也可以通过单击下面的链接 http://www.gurujipoint.com/2017/05/check-if-exist-for-trigger-function-and.html