Nano Hash - криптовалюты, майнинг, программирование

Как добавить IF NOT EXISTS для создания оператора триггера

Я использую sql server 2008 R2. В частности, Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) 2 апреля 2010 г. 15:48:46 Авторские права (c) Microsoft Corporation Standard Edition (64-разрядная версия) в Windows NT 6.1 (сборка 7601: пакет обновления 1) ) (Гипервизор). Я новичок в sql-сервере и процедурах / триггерах. У меня есть следующий код для создания триггера (он работает):

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 есть хорошие примеры 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

  • Я обновил свой неудачный пример. Почему не работает код exec? Мой синтаксис неверен в создании? 30.01.2015

Ответы:


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


 '
29.01.2015
  • Я действительно хочу использовать, если не существует. На этот вопрос есть несколько ответов, которые объясняют, почему, если не существует, тем лучше. stackoverflow .com / questions / 937908 /. 30.01.2015
  • Спасибо за ваши старания. Я попробовал этот код и получил следующее: Ошибка 330 SQL03070: этот оператор не распознается в данном контексте. 30.01.2015
  • В какой версии SQL вы находитесь? 30.01.2015
  • Я добавил версию к своему исходному вопросу. 30.01.2015
  • Ваш последний код не вызывает у меня ошибок. Какая у вас ошибка? 30.01.2015
  • Это не работает, когда я развертываю проект базы данных через Visual Studio. Однако на сервере управления sql это работает, поэтому я помечаю как принятый. Спасибо! 30.01.2015
  • Это ошибка: Ошибка 330 SQL03070: этот оператор не распознается в данном контексте. 30.01.2015
  • Если ваше определение триггера содержит буквальные строки (разделенные одинарными кавычками), это нарушит ваше значение nvarchar, передаваемое в оператор ‹at›. Чтобы обойти это, после вашего оператора IF я добавил предложения BEGIN и END. В них я объявил ‹at› выражение nvarchar (max); set ‹at› оператор = N'create trigger .... '+ nchar (39) + N' Ваше буквальное строковое значение в определении триггера, здесь '+ nchar (39) + N' .... остаток от триггера определение;' Инструкция EXEC dbo.sp_executesql ‹at›; Вам понадобится этот забавный материал nchar для каждой буквальной строки в вашем определении триггера. 27.09.2018

  • 2

    Лучший способ - проверить объекты и отбросить их, если они существуют, прежде чем создавать их.

    Вместо того чтобы вообще не создавать его, если он существует, я бы подошел к нему другим способом, отбросил его, если он существует, а затем создал.

    Обычно в длинных скриптах, если вы хотите обновить определение триггера, вы просто добавляете его в конец этого скрипта, и ваше определение триггера будет обновлено.

    Таким образом, подход должен быть 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 .......
    
    29.01.2015
  • Я действительно хочу использовать, если не существует. На этот вопрос есть несколько ответов, которые объясняют, почему, если не существует, тем лучше. stackoverflow .com / questions / 937908 /. 30.01.2015
  • Для тех, кто ищет объяснения: if not exists позволяет проверить, действительно ли объект является триггером. 11.12.2017

  • 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;
    
    29.01.2015
  • Я пробовал это, но это не сработало. Я собираюсь обновить свой вопрос кодом, который не работает - было бы здорово, если бы вы могли понять, почему он не работает. stackoverflow .com / questions / 937908 /. 30.01.2015
  • После EXEC () отсутствует точка с запятой. Попробуйте этот EXEC ('CREATE TRIGGER [dbo]. [Insert_WithdrawalCodes] ON [dbo]. [PupilWithdrawalReason] AFTER INSERT AS BEGIN SET NOCOUNT ON; UPDATE [dbo]. [PupilWithdrawalReason] SET DateCreated = dbo.SYSTEREMTIME () ВЫБЕРИТЕ WithdrawalCodeID ИЗ вставленного) КОНЕЦ '); 30.01.2015
  • Спасибо, что заметили это! 30.01.2015
  • Обратите внимание, что для триггеров DDL вы должны запрашивать sys.server_triggers, а не sys.triggers. Мне потребовалось время, чтобы понять это. 07.10.2016

  • 4

    Поскольку другие ответы выше не упоминали важный момент, я написал этот ответ:

    • Когда мы хотим найти триггер или другой объект в таблице sys.objects, лучше точно проверить (с помощью схемы или object_id и т. Д.) В предложении where, чтобы избежать недействительных результатов с таким же именем. Рассмотрим, когда другой триггер с таким же именем уже существует в другой схеме ... Следовательно, поскольку таблица sys.object содержит столбец schema_id, мы можем использовать его в дополнение к столбцам name и type для более точного запроса, как я предоставил в качестве примера ниже.

    • Как упоминалось в документах Microsoft здесь в разделе" Ограничения триггеров ":

    CREATE TRIGGER должен быть первым оператором в пакете и может применяться только к одной таблице.

    поэтому мы используем ВЫПОЛНИТЬ, чтобы преодолеть это ограничение:

    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
    
    23.04.2019
  • Это недооценивается. 22.05.2019
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..