2014-02-06 3 views
0

У меня есть триггер SQL в таблице, который будет запускаться после вставки, обновления и удаления.MSSQL Trigger - Issue

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

CREATE TRIGGER [dbo].[DATA_CACHE] 
    ON [dbo].[DATA_USAGE] 
for Insert,Update,Delete 
AS 
BEGIN 
    if(select COUNT(*) from inserted)>0 
    begin 
     if (select COUNT(*) from deleted)>0 
     BEGIN 
      --update 
      INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
      SELECT 2, ins.ID, ins.DATE, ins.COUNT 
      from inserted ins 
     END 
     else 
     begin 
      -- insert 
      INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
      SELECT 1, ins.ID, ins.DATE, ins.COUNT 
      from inserted ins 
     end 
    END 
    else 
    BEGIN 
     -- delete 
     INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
     SELECT 3, del.ID, del.DATE, del.COUNT 
     from deleted del 
    end 
END 
SELECT * FROM CACHE_UPDATE_TABLE 

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

Означает ли это, что каждый раз, когда запускается триггер, выполняется этот оператор выбора? это мой первый вопрос (вопрос А). Может быть, это глупо, но я немного смущен этим.

Мой второй вопрос (вопрос B) Я столкнулся с проблемой блокировки на CACHE_UPDATE_TABLE, может ли это быть причиной блокировки? Также есть задание SQL, которое выполняется каждую минуту, чтобы проверить таблицу CACHE_UPDATE_TABLE, а затем я выполняю некоторую операцию (связанный с сервером) и удаляю эти записи из CACHE_UPDATE_TABLE после того, как я закончен. Из-за этого может возникнуть проблема блокировки? и если да, то как мне это противостоять?

Мой третий вопрос (вопрос C) Это лучший способ сделать эту операцию с помощью триггеров или я могу сделать это по-другому? Правильно ли установлен триггер?

-Полная помощь будет оценена ... Спасибо.

+0

У вас много вопросов, поэтому вы не получили никаких ответов. Я, например, могу частично ответить A и полностью ответить на C, но не B. – OGHaza

ответ

1

У вас есть много различных вопросов там, которые, вероятно, почему вы не получили никакого ответа, но я расскажу, что я могу.

A) На самом деле это довольно интересный вопрос. Я бы предположил, что он ничего не сделает - он будет выполнен, когда вы создадите триггер, но затем не будет частью триггера, однако я заметил нечетное поведение с этим, прежде чем я протестировал с помощью простой хранимой процедуры:

CREATE PROCEDURE dbo.test (@i INT) AS 
BEGIN 
    SELECT @i 
END; 
SELECT 'hi' 
GO 

Выполнение хранимой процедуры вызывает SELECT 'hi' огня, а также SELECT @i. У меня до сих пор нет ответа на ваш вопрос, но я бы определенно удостоверился, что у него не будет никакого рассеянного SQL вне триггера, когда вы создадите его только по этой причине.

Я только что исследовал это немного больше, и, судя по всему, конец хранимой процедуры находится там, где первый послепосле процедуры (который SQL Server автоматически добавляет в конец, если вы его не используете). Таким образом, вы можете определить всю свою процедуру после END - вы все равно можете использовать параметры.

Это, кажется, потому что BEGIN и END не являются обязательной частью определения хранимой процедуры - они на самом деле не что указует на начало и конец хранимой процедуры, они просто не связан BEGIN...END блока, как вы можно положить после и IF заявление. Вы можете иметь столько блоков BEGIN...END, сколько хотите в определении процедуры, или вообще ничего.

C) Я бы точно сменил ваш курок.Вы значительно усложнили его, объединив три триггера без повторного использования какого-либо кода. Единственная причина для объединения триггеров INSERT, UPDATE и DELETE заключается в том, что вам не нужно дублировать код. Вы должны либо:

  • Имейте 3 отдельных триггера, каждый из которых содержит только релевантные INSERT - таким образом вы удаляете всю условную логику.
  • Сохраните их вместе, но выработайте только CODE, используя некоторую условную логику и получите только 1 INSERT.

Я был бы соблазн пойти с 3 отдельных триггеров, или по крайней мере Выделим удаления триггера, а затем использовать CASE del.ID IS NULL THEN 1 ELSE 2 END для CODE на спусковом INSERT/UPDATE. Но вы могли бы объединить их с (непроверенными):

INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
SELECT CASE WHEN del.ID IS NULL THEN 1 
      WHEN ins.ID IS NULL THEN 3 
      ELSE 2 END 
    ,ISNULL(ins.ID, del.ID) 
    ,ISNULL(ins.DATE, del.DATE) 
    ,ISNULL(ins.COUNT, del.COUNT) 
FROM deleted del 
FULL OUTER JOIN inserted ins ON del.ID = ins.ID 
+0

Спасибо за ответ. Присоединение к триггеру все еще кажется дорогим. В моем триггере у меня есть только два условия, которые будут проверяться каждый раз, и вставка будет проходить. Я не думаю, что это будет дорого по производительности. Возможно, я ошибаюсь, я проверю это. Но да, довольно странно, как отреагировала ваша процедура, после утверждения END, что бы вы ни добавили, похоже, что она выполняется в любом случае. –

+0

В этих обстоятельствах также не будет дорого, но заявления 'IF' предотвращают кэширование хороших планов запросов, поэтому я бы поставил большие деньги, которые' JOIN' будет выполнять лучше, но только для того, чтобы знать, было бы ориентироваться. Лучшая производительность, несомненно, будет связана с тремя отдельными триггерами, которые будут иметь идеальные планы выполнения, кэшированные. – OGHaza

+0

Отредактировал свой ответ с немного дополнительной информацией о A – OGHaza

0

Просто удалить что

SELECT * FROM CACHE_UPDATE_TABLE 
+0

Чувак, я уже удалил его ... Я хотел знать, почему он запускается, когда он находится вне кулачка. –

Смежные вопросы