Как добавить "ЕСЛИ НЕ СУЩЕСТВУЕТ" для создания оператора триггера
Я использую SQL Server 2008 R2. В частности, Microsoft SQL Server 2008 R2 (окончательная первоначальная версия) - 10.50.1600.1 (X64), 2 апреля 2010 г., 15:48:46 Авторское право (c) Microsoft Corporation Standard Edition (64-разрядная версия) в Windows NT 6.1 (сборка 7601: пакет обновления 1). ) (Гипервизор). Я новичок в SQL Server и процедуры/триггеры. У меня есть следующий код для создания триггера (он работает):
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
Как условно создать только если триггер еще не существует? Что я здесь не так делаю? У Qaru есть хорошие примеры IF NOT EXISTS
, но я не могу заставить это работать вместе с 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
Ответы
Ответ 1
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
'
Ответ 2
Лучший способ - проверить объекты и отбросить их, если они существуют до их создания.
Вместо этого, не создавая его вообще, если он существует, я бы подошел к нему по-другому, отбрось его, если он существует, а затем создаст.
Обычно при длинных сценариях длины, если вы хотите обновить определение триггера, вы просто просто добавите это в конце этого script, и ваше определение триггера будет обновлено.
Таким образом, подход должен быть 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 .......
Ответ 3
Некоторые операторы, такие как 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;
Ответ 4
Поскольку в других ответах выше не упоминается важный момент, я написал такой ответ:
Когда мы хотим найти триггер или другой объект в таблице sys.objects
, лучше точно проверить (с помощью схемы или object_id
и т.д.) Предложение where, чтобы избежать неверных результатов с тем же именем.
Рассмотрим, когда другой триггер с тем же именем уже существует в другой схеме...
Поэтому, поскольку таблица 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
Ответ 5
Проверить IF Exist For Trigger
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 Exist для хранимой процедуры, функция также нажатием ссылки ниже
http://www.gurujipoint.com/2017/05/check-if-exist-for-trigger-function-and.html