the*_*ski 34 sql t-sql sql-server triggers if-statement
我正在使用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
Run Code Online (Sandbox Code Playgroud)
仅当触发器尚不存在时,如何有条件地创建?我在这做错了什么?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
Run Code Online (Sandbox Code Playgroud)
JSt*_*ens 63
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
Run Code Online (Sandbox Code Playgroud)
根据您更新的问题...试试这个:
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
'
Run Code Online (Sandbox Code Playgroud)
M.A*_*Ali 13
最好的方法是检查对象,如果它们存在则删除它们,然后再创建它们.
而不是在它存在的情况下根本不创建它,我会以另一种方式接近它,如果存在则删除它然后创建.
通常在长长度脚本中,如果要更新触发器的定义,只需在该脚本的末尾添加它,并更新触发器定义.
所以方法应该是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 .......
Run Code Online (Sandbox Code Playgroud)
小智 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;
Run Code Online (Sandbox Code Playgroud)
由于上面的其他答案没有提到一个重点,我写了这个答案:
当我们想在sys.objects表中查找触发器或其他对象时,最好object_id在 where 子句中准确检查(使用 schema 或等),以避免同名无效结果。考虑当另一个模式中已经存在另一个同名触发器......因此,因为该sys.object表包含一个schema_id列,我们可以使用它name和type列一起使用它来更准确地查询,如下面的示例所示。
正如此处在“触发器限制”下提到的 Microsoft 文档:
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
Run Code Online (Sandbox Code Playgroud)