powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Про триггеры INSTEAD OF вопросы
17 сообщений из 17, страница 1 из 1
Про триггеры INSTEAD OF вопросы
    #39978702
edward_sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, коллеги!
Читал вдумчиво, медленно, перечитывал книгу Роберта Виейра, но не понял нескольких моментов.
1) При одиночной вставке создается виртуальная таблица inserted, в которую заносится новые данные. А при массовой (н-р 10 записей) они все туда вносятся сразу или создается каждый раз эта таблица на каждую запись и срабатывает триггер?
2) В трудах уважаемого Мастера в триггере INSTEAD OF правятся поля ДРУГОЙ таблицы. А как быть, если мне надо поправить поля ВСТАВЛЯЕМОЙ записи (н-р в отдельном поле записи удалить все лидирующие пробелы)? Мне надо работать с таблицей inserted или с целевой?
3) Я просто поправил поле, убрав пробелы и делать более ничего не хочу. Как передать управление далее, чтобы сработали ограничения полей и последующие триггеры?
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978703
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh
Добрый день, коллеги!
Читал вдумчиво, медленно, перечитывал книгу Роберта Виейра, но не понял нескольких моментов.
1) При одиночной вставке создается виртуальная таблица inserted, в которую заносится новые данные. А при массовой (н-р 10 записей) они все туда вносятся сразу или создается каждый раз эта таблица на каждую запись и срабатывает триггер?
2) В трудах уважаемого Мастера в триггере INSTEAD OF правятся поля ДРУГОЙ таблицы. А как быть, если мне надо поправить поля ВСТАВЛЯЕМОЙ записи (н-р в отдельном поле записи удалить все лидирующие пробелы)? Мне надо работать с таблицей inserted или с целевой?
3) Я просто поправил поле, убрав пробелы и делать более ничего не хочу. Как передать управление далее, чтобы сработали ограничения полей и последующие триггеры?
1. Триггер INSTEAD OF - это хранимая процедура, которая вызывается вместо вставки в таблицу, один раз на вызов стейтмента insert или update, при этом все вставляемые записи доступны в псевдо-таблице inserted и updated

2. Триггер AFTER - это хранимая процедура, которая вызывается после вставки в таблицу, один раз на вызов стейтмента insert или update, при этом все вставляемые записи доступны в псевдо-таблице inserted и updated
Соответственно, все ограничения и т.д. уже сработали до вызова этого триггера
edward_sh
3) Я просто поправил поле, убрав пробелы и делать более ничего не хочу. Как передать управление далее, чтобы сработали ограничения полей и последующие триггеры?
Можно сделать триггер INSTEAD OF, записав в таблицу строки из inserted, изменив в запросе вставки это поле.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978707
edward_sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый вечер!
Я уяснил для себя разницу в триггерах AFTER и INSTEAD OF.
Просто остались пока не понятные вопросы, о которых я написал...
К сожалению, Ваш ответ не принес желанного просветления...
1) Таки все записи появляются ОДНОВРЕМЕННО в таблице inserted при массовой вставке или же таблица создается для КАЖДОЙ вставляемой записи, а после отработки триггеров и ограничений удаляется, а для последующей записи создается новая виртуальная таблица?
2) Правильно ли я понял Вас, чтобы мне сделать что-то над полем вставляемой записи, необходимо выбрать его SELECT'ом из таблицы inserted, что-то с ним сделать, и потом при помощи UPDATE обновить поле в целевой (куда вставляется запись) таблице?
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978712
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh
Просто остались пока не понятные вопросы, о которых я написал...
К сожалению, Ваш ответ не принес желанного просветления...
1) Таки все записи появляются ОДНОВРЕМЕННО в таблице inserted при массовой вставке или же таблица создается для КАЖДОЙ вставляемой записи, а после отработки триггеров и ограничений удаляется, а для последующей записи создается новая виртуальная таблица?
Я же написал: "один раз на вызов стейтмента insert или update, при этом все вставляемые записи доступны в псевдо-таблице inserted и updated"

один раз на вызов стейтмента

все вставляемые записи

edward_sh
2) Правильно ли я понял Вас, чтобы мне сделать что-то над полем вставляемой записи, необходимо выбрать его SELECT'ом из таблицы inserted, что-то с ним сделать, и потом при помощи UPDATE обновить поле в целевой (куда вставляется запись) таблице?
Для триггера AFTER да. Учитывая в своём коде, что записей в inserted будет много, так что "записать поле в переменную" не получится. Нужно писать оператор UPDATE с связкой двух таблиц.

А для триггера INSTED OF нет, я же написал, что он выполняется ВМЕСТО

Например, когда вы вызвали оператор INSERT, вставляя в таблицу 100 записей, триггер INSTED OF может отправить емэйлы в бухгалтерию, и выключать в комнате свет, а записи в таблице после этого не появятся.

Это, повторю, произвольная хранимая процедура, которая делает то, что вы в ней запрограммировали, и к таблице, на которой висит этот триггер, не имеет никакого отношения (кроме того, "что висит на ней").
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978726
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexeyvg,

А еще в INSTED OF можно вставить все 100 записей в таблицу на которую сработал триггер %:)

Видимо у edward_sh конструкция INSTEAD OF [ INSERT/UPDATE/DELETE ] AS не разделяется с действием(ями), которое [INSERT/UPDATE/DELETE]

edward_sh,

Я понимаю это так:

когда используется FOR или AFTER, происходит заданная операция [ INSERT/UPDATE/DELETE ] и после этого у вас есть виртуальные таблицы с данными, которые были [ INSERT/UPDATE/DELETE ], и к ним вы имеете доступ в триггере, который на эти операции активируется


когда используется INSTEAD OF, не происходит операции [ INSERT/UPDATE/DELETE ], а только активируется триггер на вызов этих операций, в котором у вас опять же есть виртуальные таблицы с данными предназначенными для [ INSERT/UPDATE/DELETE ], и дальше вы вольны с этими данными делать что угодно, например при запросе UPDATE [a] FROM [T] и триггере срабатывающем на UPDATE, делать DELETE FROM [t] или print ...
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978759
edward_sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, джентельмены!
Попробую разложить по полочкам результаты топика, а Вы поправьте, где я не прав...
Итак, имеется таблица вида Таблица1:
Поле1 - первичный ключ, с уникальным значением, автоикремент
Поле2 - nvarchar(max)

Имеется массовая вставка (н-р через BULK INSERT) 3 записей (для простоты).
Далее следуют мои шаги, без жесткого соблюдения синтаксиса операторов (опять таки ради простоты)

1) Создаю триггер CREATE TRIGGER trg_Name ON Таблица1 INSTEAD OF INSERT
2) В теле триггера пишу нечто похожее @переменная1 = SELECT Поле2 from inserted
3)@переменная1 = функция(@переменная1)
4)UPDATE inserted set Поле2 = @переменная1
5) поскольку мне надо поправить только одно поле, просто оканчиваю описание триггера
6) после окончания действий в триггере автоматически продолжится выполнение последующих
действий (проверка CHECK и т.д.)
7) SQL сервер автоматически передвинет указатель на следующую новую копию вставляемой строки
8) Сработают снова пункты 2-7 и так, до последней записи

Правильно ли я понимаю работу этого триггера? Кстати, еще один тонкий момент. При массовой вставке
сначала все данные внесутся в таблицу inserted, а потом для каждой записи будет вызываться триггер?
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978801
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh
Имеется массовая вставка (н-р через BULK INSERT) 3 записей (для простоты).

В таком случае для BULK INSERT нужно указать опцию FIRE_TRIGGERS, иначе триггеры не сработают.

edward_sh
При массовой вставке
сначала все данные внесутся в таблицу inserted, а потом для каждой записи будет вызываться триггер?

Триггер вызовется 1 раз для всего батча. Это же всё в документации есть.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978810
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh
Добрый день, джентельмены!
Попробую разложить по полочкам результаты топика, а Вы поправьте, где я не прав...
Итак, имеется таблица вида Таблица1:
Поле1 - первичный ключ, с уникальным значением, автоикремент
Поле2 - nvarchar(max)

Имеется массовая вставка (н-р через BULK INSERT) 3 записей (для простоты).
Далее следуют мои шаги, без жесткого соблюдения синтаксиса операторов (опять таки ради простоты)

1) Создаю триггер CREATE TRIGGER trg_Name ON Таблица1 INSTEAD OF INSERT
2) В теле триггера пишу нечто похожее @переменная1 = SELECT Поле2 from inserted
3)@переменная1 = функция(@переменная1)
4)UPDATE inserted set Поле2 = @переменная1
5) поскольку мне надо поправить только одно поле, просто оканчиваю описание триггера
6) после окончания действий в триггере автоматически продолжится выполнение последующих
действий (проверка CHECK и т.д.)
7) SQL сервер автоматически передвинет указатель на следующую новую копию вставляемой строки
8) Сработают снова пункты 2-7 и так, до последней записи

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


начиная с пункта 2) у вас уже логика может поехать, не говоря о том что пункт 4) вообще не выполним.

осознайте следующее: триггер срабатывает на одну отдельную инструкцию insert.
если одна отдельная инструкция вставляет 100 строк, то триггер запустится только один раз, а не 100.

Код: sql
1.
insert into [dbo].[tbl] values (1), (2), (3); --добавится три строки, триггер сработает один раз, в inserted на момент выполнения триггер а будет 3 строки.



Код: sql
1.
2.
insert into [dbo].[tbl] values (1), (2) --добавится две строки, тригер сработает первый раз, в inserted будет 2 строки
insert into [dbo].[tbl] values (3), (4), (5) --добавится три строки, триггер сработает второй раз, в inserted будет 3 строки



при этом разница в триггерах for/after от instead of в том, что в первых данные по окончании триггера если нет отката транзакции будут присутствовать в таблице (если вы их конечно не удалите вручную)

а в триггере instead of вам в теле триггера нужно явно вызвать инструкцию insert в вашу таблицу, иначе вставки не произойдет

и тут сложность с применением identity колонки, поскольку на момент срабатывания триггера instead of в логической таблице inserted колонка идентификации не наполняется данными

зачем вы вообще выбрали тип используемого триггера как instead of вместо for/after?
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978817
edward_sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, джентельмены!
То, что популярно Вы объяснили я и хотел выяснить своим вопросом.
Почему выбран триггер INSTEAD OF?
Все очень просто - поле фамилия (или номер документа) не может содержать пробелов как таковых.
Они мною запрещены для ввода CHECK'ом для полей.
Поскольку пользователи очень часто копируют\вставляют в поля ввода данные, например из ворда или экселя,
попадаются лидирующие\ конечные пробелы (чаще всего).
По роду деятельности мне необходимо выгружать данные из экселя в базу ФРДО (федеральная база по дипломам).
Очень напрягает, когда из-за того, что в поле фамилия есть конечный пробел, все записи отбрасываются.
Что мешает их ликвидировать на уровне проверки данных и отбрасыванию лишних пробелов программными средствами
SQL тамошними программистами - для меня загадка. Вот и не хочу походить на них, чтобы меня будущие пользователи (как я сейчас)
не вспоминали "добрым словом".

To Felix_ff:
Если не трудно поясните свои мысли по поводу съезда логики с п2
Почему п4 не выполним? Ведь таблица inserted хоть и виртуальная, но таблица?
Поможет ли мне переменная @@RowCount при движении по таблице inserted?
Если как я первоначально в первом посте предполагал, что мне надо из триггера самому обновлять целевую таблицу, то как действительно быть с уникальным значением? Считывать последний из таблицы и присваивать новое значение новой записи?

Одно прояснилось - другое замутилось :(
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978822
londinium
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторВ теле триггера пишу нечто похожее @переменная1 = SELECT Поле2 from inserted
Представьте себе, что произойдет, если в таблице inserted будет больше одной строки. Какое значение в этом случае будет у @переменная1 ?
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978829
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh
Почему выбран триггер INSTEAD OF?
Все очень просто - поле фамилия (или номер документа) не может содержать пробелов как таковых.
Триггер тут не нужен, от слова "совсем". Для достижения желаемого, достаточно добавить вычисляемые столбцы или создать представление с нужными действиями по очистке данных.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978859
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To Felix_ff:
Если не трудно поясните свои мысли по поводу съезда логики с п2
Почему п4 не выполним? Ведь таблица inserted хоть и виртуальная, но таблица?
Поможет ли мне переменная @@RowCount при движении по таблице inserted?
Если как я первоначально в первом посте предполагал, что мне надо из триггера самому обновлять целевую таблицу, то как действительно быть с уникальным значением? Считывать последний из таблицы и присваивать новое значение новой записи?


Мне тоже интересно, возможно ли такое? :) Всегда считал, что inserted и deleted можно только читать, но не изменять

в документации написано
Инструкции триггеров DML используют две особые таблицы: deleted и inserted. SQL Server автоматически создает эти таблицы и управляет ими. Эти временные таблицы, находящиеся в оперативной памяти, используются для проверки результатов изменений данных и для установки условий срабатывания триггеров DML. Нельзя в этих таблицах изменять данные напрямую или выполнять над ними операции языка описания данных DDL, например инструкцию CREATE INDEX.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39978882
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
godsql
To Felix_ff:
Если не трудно поясните свои мысли по поводу съезда логики с п2
Почему п4 не выполним? Ведь таблица inserted хоть и виртуальная, но таблица?
Поможет ли мне переменная @@RowCount при движении по таблице inserted?
Если как я первоначально в первом посте предполагал, что мне надо из триггера самому обновлять целевую таблицу, то как действительно быть с уникальным значением? Считывать последний из таблицы и присваивать новое значение новой записи?


Мне тоже интересно, возможно ли такое? :) Всегда считал, что inserted и deleted можно только читать, но не изменять

в документации написано
Инструкции триггеров DML используют две особые таблицы: deleted и inserted. SQL Server автоматически создает эти таблицы и управляет ими. Эти временные таблицы, находящиеся в оперативной памяти, используются для проверки результатов изменений данных и для установки условий срабатывания триггеров DML. Нельзя в этих таблицах изменять данные напрямую или выполнять над ними операции языка описания данных DDL, например инструкцию CREATE INDEX.

не возможно, в случае попытки изменения этих таблиц получите ошибку 286
https://docs.microsoft.com/ru-ru/sql/relational-databases/errors-events/database-engine-events-and-errors?view=sql-server-ver15

edward_sh,
Если не трудно поясните свои мысли по поводу съезда логики с п2
Почему п4 не выполним? Ведь таблица inserted хоть и виртуальная, но таблица?
Поможет ли мне переменная @@RowCount при движении по таблице inserted?
Если как я первоначально в первом посте предполагал, что мне надо из триггера самому обновлять целевую таблицу, то как действительно быть с уникальным значением? Считывать последний из таблицы и присваивать новое значение новой записи?

Одно прояснилось - другое замутилось :(


Вам уже пояснили по пункту два: вы в скалярную переменную загоняете значение из таблицы (то есть из множества значений)
если к примеру в inserted на тот момент будет несколько строк то ваш
Код: sql
1.
select @variable = (select [val] from inserted) 


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

если хотите париться с получением identity в триггере instead of можете почитать про финт ушами с merge + output внутри триггера
но это если честно извращение.

invm дал Вам вполне дельную рекомендацию что результат которого вы добиваетесь вполне достижым без использования триггеров.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39979016
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh,

ETL задачи лучше решать средствами Integration services, там и пробелы можно выкинуть, и форматировать ФИО и еще много чего.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39979019
edward_sh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый вечер, джентельмены!
Похоже, что некоторые читают только последние сообщения, не прочив суть вопроса.
To invm:
Имеется таблица со структурой:
РК int
Фамилия nvarchar(max)

На поле фамилия стоит CHECK [а-я-]
Про какое вычисляемое поле Вы говорите? Как поможет представление (view) исправить проблему с пробелами, если сработает CHECK и запись будет отброшена?
Я не зря спросил про @@RowCount (если верить описанию, то эта переменная содержит кол-во строк последней операции, в данном случае, кол-во вставленных строк в таблице )

To gotsql:
Вы путаете DDL и DML (первое управляет структурой таблицы, например создание индексов, второе управляет данными insert, update, delete). Я не изменяю структуру таблицы, я меняю содержимое строки таблицы...

Если у уважаемого сообщества есть более разумные предложения - раза 2 в неделю буду читать топик. Сейчас в отпуске, на даче...
Буду пытаться штудировать буржуйские источники информации...
По результатам, естественно отпишусь...
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39979033
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh,

Код: sql
1.
2.
3.
4.
5.
6.
7.
DROP TABLE IF EXISTS [dbo].[tbl_ClientList];
CREATE TABLE [dbo].[tbl_ClientList] (
     [RID] BIGINT IDENTITY(1, 1),
     [FIO] VARCHAR(MAX)
);

INSERT INTO [dbo].[tbl_ClientList] VALUES ('Петров Перт Петрович'), ('СидоровСидр Сидорович'), ('Козлов Уася какойтотам     ');



Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE VIEW [dbo].[v_ClientList]
WITH SCHEMABINDING
AS
SELECT
     [RID],
     RTRIM([FIO]) AS [FIO] --и любые другие преобразования колонки что Вам нужны
FROM [dbo].[tbl_ClientList];



далее используете view вместо таблицы

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

загружаете данные с stage-таблицу, модифицируете, переливаете в боевую таблицу. как альтернатива используйте SSIS для заливки данных оно как раз как ETL решение прекрасно подходит.
...
Рейтинг: 0 / 0
Про триггеры INSTEAD OF вопросы
    #39979062
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
edward_sh
РК int
Фамилия nvarchar(max)

На поле фамилия стоит CHECK [а-я-]
Про какое вычисляемое поле Вы говорите?
А подумать не?
Код: sql
1.
2.
3.
4.
5.
6.
declare @t table (id int primary key, s nvarchar(100), s1 as rtrim(ltrim(s)) persisted, check (s1 not like '%[^а-я-]%'));

insert into @t values (1, N' ааа  ');
insert into @t values (1, N'  б бб  ');

select id, '[' + s + ']', '[' + s1 + ']' from @t;
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Про триггеры INSTEAD OF вопросы
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]