Pull to refresh

Триггеры, изменяющие значение в столбце при изменении в другом столбце

Здравствуйте! Я продемонстрирую как создать на MS SQL триггер, который запишет полное наименование документа в столбец с названием p4758 таблицы attr379 на основании данных в столбцах этой же таблицы.

  • P4744 — вид документа, ссылка на таблицу attr125, нам необходимо взять значение из P560
  • P4727 — дата документа
  • P4726 — номер документа.

Я создам данный триггер средствами конфигуратора платформы Клиент Коммуникатор и затем подробно опишу, что получилось.

Вот структура таблицы:



Создаем хранимое вычисление:

  1. Добавила название вида документа

  2. Добавила текстовые связки " №" и " от "
  3. Добавила «номер документа» и «дата документа»

  4. Нажала на кнопку «Ок».

Теперь перехожу в Management Studio и смотрю, что у меня получилось.

В базе данных создался новый триггер на таблице attr379. Содержимое триггера:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[iuAttr379->P4758] ON [dbo].[Attr379]
AFTER INSERT,UPDATE AS

SET NOCOUNT ON

IF OBJECT_ID (N'tempdb..#UPDATE_ATTR_P4758', N'U') IS NOT NULL return
IF NOT (UPDATE(P4758) OR UPDATE(P4744) OR UPDATE(P4726) OR UPDATE(P4727)) return

CREATE TABLE #UPDATE_ATTR_P4758 (ObjID INT)

INSERT #UPDATE_ATTR_P4758
SELECT DISTINCT ObjectID FROM INSERTED

IF @@ROWCOUNT > 0
EXEC dbo.[_SCUpdateAttr379->P4758]

DROP TABLE #UPDATE_ATTR_P4758

Триггер действует только на добавление записи и редактирование определенных полей.
Разберем построчно:

"IF OBJECT_ID (N'tempdb..#UPDATE_ATTR_P4758', N'U') IS NOT NULL return"

Эта строка необходима для того, чтобы не было зацикливания, это как метка «Мы здесь были — больше нам сюда не надо»

"IF NOT (UPDATE(P4758) OR UPDATE(P4744) OR UPDATE(P4726) OR UPDATE(P4727)) return"

Если не менялись данные в столбцах, от которых зависит название документа, то ничего делать и не надо.

"CREATE TABLE #UPDATE_ATTR_P4758 (ObjID INT)"

Если всё же требуется изменить название документа, то создаем временную таблицу.

"INSERT #UPDATE_ATTR_P4758
SELECT DISTINCT ObjectID FROM INSERTED"

Наполняем временную таблицу уникальными ID. Можно еще добавить условие и отобрать только те строки, где произошло изменение в столбцах: p4744, p4727, p4726. Это было бы оправдано в случае, если в таблице много столбцов, т.к. во временную таблицу помещаются все изменившиеся строки, но среди них может быть только одна строка из 1000, в которой требуется изменить название документа.

"IF @@ROWCOUNT > 0
EXEC dbo.[_SCUpdateAttr379->P4758]"

Если в нашей временной таблице есть записи, то запускаем процедуру изменения наименования документа (её конфигуратор тоже создал автоматически, подробно описывать её не буду):

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[_SCUpdateAttr379->P4758] AS

IF OBJECT_ID (N'tempdb..#UPDATE_ATTR_P4758', N'U') IS NULL
begin
  RAISERROR(N'Procedure dbo.[_SCUpdateAttr379->P4758] is need the special table #UPDATE_ATTR_P4758 for correct work!',16,1)
  return
end

SET NOCOUNT ON

DECLARE @T Table (ObjectID int, P4758 nvarchar(255))

INSERT @T
SELECT 
a0.ObjectID,
a1.P560 + ' № ' +  a0.P4726 + ' от ' + a0.P4727
FROM [dbo].[Class379] a0 WITH(UPDLOCK,HOLDLOCK)
 JOIN #UPDATE_ATTR_P4758 u ON a0.ObjectID = u.ObjID
 LEFT JOIN [dbo].[Class125] a1 ON a1.ObjectID=a0.P4744

WHERE a0.ObjectID > 0
UPDATE a
SET
  a.P4758 = t.P4758
FROM [dbo].[Attr379] a, @T t
where a.ObjectID = t.ObjectID

"DROP TABLE #UPDATE_ATTR_P4758"

Последняя строка в триггере. Если мы до неё дошли, то значит уже пора удалять временную таблицу.

Подводим итоги. Чтобы создать триггер, который меняет данные в самой таблице при изменении значений в этой же таблице:

  1. Надо поставить защиту от зацикливания, в данном примере используется временная таблица
  2. Ограничить список строк, в которых будем проводить изменения, т.к. именно это влияет на производительность выполнения операции.
  3. Только если в нашем списке оказались строки, в которых требуются изменения, то выполнить действия.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.