Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Запретить срабатывать триггеру если изменения делает другой триггер  [new]
Chippollino.01
Member

Откуда: изнемагаю
Сообщений: 35527
Chippollino.01
Есть две таблицы
изменения из в первой таблицы логируются триггером UPDATE во вторую
при вставке в первую есть триггер на INSERT, который инициализирует поля таблицы при вставке значением из третьей таблицы,
но при отработке инструкции update в этом триггере срабатывает триггер на UPDATE

Можно ли запретить триггеру на UPDATE срабатывать если он вызван изменениями вносимыми триггером на INSERT,
чтобы логировались только изменения привнесенные извне?

+
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Table_1]') AND type in (N'U'))
DROP TABLE [dbo].[Table_1]
GO

CREATE TABLE [dbo].[Table_1](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[tt] [datetime] NOT NULL,
	[note] [varchar](20) NULL,
 CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Table_1] ADD  CONSTRAINT [DF_Table_1_tt]  DEFAULT (getdate()) FOR [tt]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Table_2]') AND type in (N'U'))
DROP TABLE [dbo].[Table_2]
GO


CREATE TABLE [dbo].[Table_2](
	[ID] [int] NULL,
	[tt] [datetime] NULL,
	[note] [varchar](10) NULL
) ON [PRIMARY]

GO

IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[t1ins]'))
DROP TRIGGER [dbo].[t1ins]
GO

CREATE TRIGGER [dbo].[t1ins]
   ON  [dbo].[Table_1]
   AFTER INSERT
AS 
BEGIN
	UPDATE T 
	SET note=T.note +'(ins)'
	FROM dbo.Table_1 T INNER JOIN inserted TIns ON T.ID=TIns.ID
END

GO

IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[t1upd]'))
DROP TRIGGER [dbo].[t1upd]
GO


CREATE TRIGGER [dbo].[t1upd]
   ON  [dbo].[Table_1]
   AFTER UPDATE
AS 
BEGIN
	INSERT INTO Table_2 (ID, tt, note)
	SELECT     ID, tt, note+'upd'
	FROM         deleted
END

GO
7 апр 14, 13:54    [15843354]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
iap
Member

Откуда: Москва
Сообщений: 47157
Chippollino.01,

может, TRIGGER_NESTLEVEL заюзать?
7 апр 14, 13:56    [15843373]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
iap
Member

Откуда: Москва
Сообщений: 47157
Можно также использовать CONTEXT_INFO для проверки в триггере
7 апр 14, 14:00    [15843417]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
Chippollino.01
Member

Откуда: изнемагаю
Сообщений: 35527
все получилось , спасибо.
IF  trigger_nestlevel() < 2
7 апр 14, 14:25    [15843666]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
invm
Member

Откуда: Москва
Сообщений: 9889
Chippollino.01
все получилось , спасибо.
IF  trigger_nestlevel() < 2
Что будете делать, если появится триггер с update, который нужно будет логировать?
7 апр 14, 14:38    [15843763]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8962
автор
Можно ли запретить триггеру на UPDATE срабатывать если он вызван изменениями вносимыми триггером на INSERT,
чтобы логировались только изменения привнесенные извне?


По мне так эта стратегия неверна, т.к. Вы получите изменения в таблице, которые не отражены в журнале.
Т.к. своими руками нарушите целостность журнала. Попробуйте добавить для журнала поле suser_name(), например.
7 апр 14, 15:03    [15843975]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
sphinx_mv
Member [заблокирован]

Откуда:
Сообщений: 1672
Chippollino.01
Есть две таблицы
изменения из в первой таблицы логируются триггером UPDATE во вторую
при вставке в первую есть триггер на INSERT, который инициализирует поля таблицы при вставке значением из третьей таблицы,
но при отработке инструкции update в этом триггере срабатывает триггер на UPDATE

Можно ли запретить триггеру на UPDATE срабатывать если он вызван изменениями вносимыми триггером на INSERT,
чтобы логировались только изменения привнесенные извне?

+
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Table_1]') AND type in (N'U'))
DROP TABLE [dbo].[Table_1]
GO

CREATE TABLE [dbo].[Table_1](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[tt] [datetime] NOT NULL,
	[note] [varchar](20) NULL,
 CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Table_1] ADD  CONSTRAINT [DF_Table_1_tt]  DEFAULT (getdate()) FOR [tt]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Table_2]') AND type in (N'U'))
DROP TABLE [dbo].[Table_2]
GO


CREATE TABLE [dbo].[Table_2](
	[ID] [int] NULL,
	[tt] [datetime] NULL,
	[note] [varchar](10) NULL
) ON [PRIMARY]

GO

IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[t1ins]'))
DROP TRIGGER [dbo].[t1ins]
GO

CREATE TRIGGER [dbo].[t1ins]
   ON  [dbo].[Table_1]
   AFTER INSERT
AS 
BEGIN
	UPDATE T 
	SET note=T.note +'(ins)'
	FROM dbo.Table_1 T INNER JOIN inserted TIns ON T.ID=TIns.ID
END

GO

IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[t1upd]'))
DROP TRIGGER [dbo].[t1upd]
GO


CREATE TRIGGER [dbo].[t1upd]
   ON  [dbo].[Table_1]
   AFTER UPDATE
AS 
BEGIN
	INSERT INTO Table_2 (ID, tt, note)
	SELECT     ID, tt, note+'upd'
	FROM         deleted
END

GO
Использование вложенных триггеров
Не оно?
7 апр 14, 15:41    [15844376]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
Prolog
Member

Откуда: Москва
Сообщений: 2793
Вариант:

insert-триггер создать с опцией WITH EXECUTE AS USER = 'nolog'
в update-триггере проверять IF USER_NAME() = 'nolog' ...
7 апр 14, 15:53    [15844485]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
aleks2
Guest
Может рекурсию триггеров запретить на сервере?
7 апр 14, 18:32    [15845565]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
IF Update(Note) ...
... WHERE Deleted.Note [NOT] LIKE '...'
Или переработать механизм/подход.
8 апр 14, 03:55    [15846972]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
iap
Member

Откуда: Москва
Сообщений: 47157
aleks2
Может рекурсию триггеров запретить на сервере?
Рекурсия триггеров - это непосредственный вызов триггера из него самого же.
А тут из триггера UPDATE вызывается INSERT в другую таблицу, а уже из триггера на этот INSERT
опять запускается триггер для первой таблицы.
Это рекурсией не считается с точки зрения параметра сервера.
8 апр 14, 09:20    [15847293]     Ответить | Цитировать Сообщить модератору
 Re: Запретить срабатывать триггеру если изменения делает другой триггер  [new]
sphinx_mv
Member [заблокирован]

Откуда:
Сообщений: 1672
iap
aleks2
Может рекурсию триггеров запретить на сервере?
Рекурсия триггеров - это непосредственный вызов триггера из него самого же.
А тут из триггера UPDATE вызывается INSERT в другую таблицу, а уже из триггера на этот INSERT
опять запускается триггер для первой таблицы.
Это рекурсией не считается с точки зрения параметра сервера.
Вообще-то считается...
Использование вложенных триггеров
Рекурсивные триггеры
Триггер AFTER не вызывает самого себя рекурсивно, если только не установлен параметр базы данных RECURSIVE_TRIGGERS.
Существует два типа рекурсии.
  • Прямая рекурсия
    Такая рекурсия происходит, когда триггер срабатывает и выполняет действие, вызывающее повторное срабатывание того же триггера. Например, приложение обновляет таблицу T3; это вызывает срабатывание триггера Trig3. Триггер Trig3 снова обновляет таблицу T3, при этом триггер Trig3 срабатывает еще раз.
    ...
  • Косвенная рекурсия
    Косвенная рекурсия возникает, когда триггер срабатывает и выполняет действие, которое вызывает срабатывание другого триггера того же типа.
    ...
    Когда для параметра базы данных RECURSIVE_TRIGGERS устанавливается значение OFF, предотвращается только прямая рекурсия триггеров AFTER. Чтобы отключить косвенную рекурсию триггеров AFTER, присвойте параметру сервера nested triggers значение 0.
  • 8 апр 14, 10:22    [15847537]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить