как создать перед обновлением триггер в sql server 2005 - PullRequest
1 голос
/ 16 июня 2010

Есть ли в любом случае, где я могу создать триггер, который будет выполняться до того, как произойдет обновление / удаление (а затем произойдет фактическое обновление / удаление)? и как я могу drop триггер из таблицы?

Ответы [ 4 ]

1 голос
/ 16 июня 2010

Эта статья от Microsoft объясняет синтаксис создания триггеров.

http://msdn.microsoft.com/en-us/library/ms189799.aspx

На самом деле нет триггера «до», но вы можете использовать триггер INSTEAD OF, который позволяетвам нужно прыгнуть вместо того, чтобы предпринять какое-либо действие, а затем определить свое собственное действие.

Я использовал эту технику для контроля версий данных.

CREATE TRIGGER [dbo].[Documents_CreateVersion] 
   ON  [dbo].[Documents] 
   INSTEAD OF UPDATE

AS 
BEGIN

  DECLARE @DocumentID int
  SELECT DocumentID  = DocumentID FROM INSERTED

  -- do something

END

INSERTED - это немного неправильно здесь, но он содержит подробную информацию о действии до того, как оно произойдет, затем вы можете определить свое собственное действие с этими данными.

Редактировать:

Согласно комментариям под моим ответом,Мой пример может быть опасным, если несколько строк обновляются одновременно.Мое приложение не позволяет этого, так что в этом случае все в порядке.Я бы согласился, что вышесказанное - плохая практика, независимо от того.

1 голос
/ 16 июня 2010

для сброса триггера используйте:

--SQL Server 2005+, drop the trigger, no error message if it does not exist yet
BEGIN TRY DROP TRIGGER dbo.TrigerYourTable END TRY BEGIN CATCH END CATCH
GO

--drop trigger pre-SQl Server 2005, no error message if it does not exist yet
if exists (select * from sysobjects where id = object_id(N'[dbo].[TrigerYourTable ]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
    drop trigger [dbo].[TrigerYourTable ]
GO

OP сказал в комментарии:

... предположим, что мне нужно проверить дочерний счет пользователя в perticular, если это большечем 5 не обновлять пользователя. Как я могу сделать это, используя вместо триггера?

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

--create the trigger
CREATE TRIGGER dbo.TrigerYourTable ON dbo.YourTable
   AFTER UPDATE
AS 
SET NOCOUNT ON

IF EXISTS (SELECT
               1
               FROM INSERTED                      i
                   INNER JOIN YourChildrenTable   c ON i.ParentID=c.ParentID
               GROUP BY i.ParentID
               HAVING COUNT(i.ParentID)>5
          )
BEGIN
    RAISERROR('Count of children can not exceed 5',16,1)
    ROLLBACK
    RETURN
END

GO

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

Если childcount является столбцом в затронутой таблице, тогда используйте триггер, подобный этому, чтобы применить логику:

--create the trigger
CREATE TRIGGER dbo.TrigerYourTable ON dbo.YourTable
   AFTER UPDATE
AS 
SET NOCOUNT ON

IF EXISTS (SELECT 1 FROM INSERTED WHERE childcount>5)
BEGIN
    RAISERROR('Count of children can not exceed 5',16,1)
    ROLLBACK
    RETURN
END

GO

Если вы просто хотите игнорировать обновление для любых строк, которыенарушите правило, попробуйте следующее:

--create the trigger
CREATE TRIGGER dbo.TrigerYourTable ON dbo.YourTable
   INSTEAD OF UPDATE
AS 
SET NOCOUNT ON

UPDATE y
    SET col1=i.col1
       ,col2=i.col2
       ,col3=i.col3
       ,....  --list all columns except the PK column!
    FROM dbo.YourTable       y
        INNER JOIN INSERTED  i on y.PK=i.PK
    WHERE i.childcount<=5
GO

Он будет обновлять только строки с количеством дочерних элементов менее 5, игнорируя все затронутые строки, которые не соответствуют требованию (без сообщения об ошибке).

0 голосов
/ 01 марта 2012

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

IF OBJECT_ID ('dbo.MyTableTrigger', 'TR') IS NOT NULL
   DROP TRIGGER dbo.MyTableTrigger;
GO

CREATE TRIGGER MyTableTrigger
ON dbo.MyTable
FOR INSERT, UPDATE 
AS
DECLARE @Col1ID INT
DECLARE @Col2ID INT

SELECT @Col1ID = Col1ID, @Col2ID = Col2ID FROM inserted
IF ((@Col1ID IS NOT NULL) AND (@Col2ID IS NOT NULL))
BEGIN
  RAISERROR ('Col1ID and Col2ID cannot both be in MyTable at the same time.', 16, 10);
END
0 голосов
/ 16 июня 2010

для сброса триггера - use database_name

IF EXISTS (SELECT name FROM sysobjects
  WHERE name = 'tgr_name' AND type = 'TR')    
DROP TRIGGER tgr_name
GO
...