|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
Добрый день, коллеги! Читал вдумчиво, медленно, перечитывал книгу Роберта Виейра, но не понял нескольких моментов. 1) При одиночной вставке создается виртуальная таблица inserted, в которую заносится новые данные. А при массовой (н-р 10 записей) они все туда вносятся сразу или создается каждый раз эта таблица на каждую запись и срабатывает триггер? 2) В трудах уважаемого Мастера в триггере INSTEAD OF правятся поля ДРУГОЙ таблицы. А как быть, если мне надо поправить поля ВСТАВЛЯЕМОЙ записи (н-р в отдельном поле записи удалить все лидирующие пробелы)? Мне надо работать с таблицей inserted или с целевой? 3) Я просто поправил поле, убрав пробелы и делать более ничего не хочу. Как передать управление далее, чтобы сработали ограничения полей и последующие триггеры? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2020, 19:32 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh Добрый день, коллеги! Читал вдумчиво, медленно, перечитывал книгу Роберта Виейра, но не понял нескольких моментов. 1) При одиночной вставке создается виртуальная таблица inserted, в которую заносится новые данные. А при массовой (н-р 10 записей) они все туда вносятся сразу или создается каждый раз эта таблица на каждую запись и срабатывает триггер? 2) В трудах уважаемого Мастера в триггере INSTEAD OF правятся поля ДРУГОЙ таблицы. А как быть, если мне надо поправить поля ВСТАВЛЯЕМОЙ записи (н-р в отдельном поле записи удалить все лидирующие пробелы)? Мне надо работать с таблицей inserted или с целевой? 3) Я просто поправил поле, убрав пробелы и делать более ничего не хочу. Как передать управление далее, чтобы сработали ограничения полей и последующие триггеры? 2. Триггер AFTER - это хранимая процедура, которая вызывается после вставки в таблицу, один раз на вызов стейтмента insert или update, при этом все вставляемые записи доступны в псевдо-таблице inserted и updated Соответственно, все ограничения и т.д. уже сработали до вызова этого триггера edward_sh 3) Я просто поправил поле, убрав пробелы и делать более ничего не хочу. Как передать управление далее, чтобы сработали ограничения полей и последующие триггеры? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2020, 19:42 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
Добрый вечер! Я уяснил для себя разницу в триггерах AFTER и INSTEAD OF. Просто остались пока не понятные вопросы, о которых я написал... К сожалению, Ваш ответ не принес желанного просветления... 1) Таки все записи появляются ОДНОВРЕМЕННО в таблице inserted при массовой вставке или же таблица создается для КАЖДОЙ вставляемой записи, а после отработки триггеров и ограничений удаляется, а для последующей записи создается новая виртуальная таблица? 2) Правильно ли я понял Вас, чтобы мне сделать что-то над полем вставляемой записи, необходимо выбрать его SELECT'ом из таблицы inserted, что-то с ним сделать, и потом при помощи UPDATE обновить поле в целевой (куда вставляется запись) таблице? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2020, 19:59 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh Просто остались пока не понятные вопросы, о которых я написал... К сожалению, Ваш ответ не принес желанного просветления... 1) Таки все записи появляются ОДНОВРЕМЕННО в таблице inserted при массовой вставке или же таблица создается для КАЖДОЙ вставляемой записи, а после отработки триггеров и ограничений удаляется, а для последующей записи создается новая виртуальная таблица? один раз на вызов стейтмента все вставляемые записи edward_sh 2) Правильно ли я понял Вас, чтобы мне сделать что-то над полем вставляемой записи, необходимо выбрать его SELECT'ом из таблицы inserted, что-то с ним сделать, и потом при помощи UPDATE обновить поле в целевой (куда вставляется запись) таблице? А для триггера INSTED OF нет, я же написал, что он выполняется ВМЕСТО Например, когда вы вызвали оператор INSERT, вставляя в таблицу 100 записей, триггер INSTED OF может отправить емэйлы в бухгалтерию, и выключать в комнате свет, а записи в таблице после этого не появятся. Это, повторю, произвольная хранимая процедура, которая делает то, что вы в ней запрограммировали, и к таблице, на которой висит этот триггер, не имеет никакого отношения (кроме того, "что висит на ней"). ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2020, 20:17 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
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 ... ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2020, 22:09 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
Добрый день, джентельмены! Попробую разложить по полочкам результаты топика, а Вы поправьте, где я не прав... Итак, имеется таблица вида Таблица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, а потом для каждой записи будет вызываться триггер? ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 06:39 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh Имеется массовая вставка (н-р через BULK INSERT) 3 записей (для простоты). В таком случае для BULK INSERT нужно указать опцию FIRE_TRIGGERS, иначе триггеры не сработают. edward_sh При массовой вставке сначала все данные внесутся в таблицу inserted, а потом для каждой записи будет вызываться триггер? Триггер вызовется 1 раз для всего батча. Это же всё в документации есть. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 09:46 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
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.
Код: sql 1. 2.
при этом разница в триггерах for/after от instead of в том, что в первых данные по окончании триггера если нет отката транзакции будут присутствовать в таблице (если вы их конечно не удалите вручную) а в триггере instead of вам в теле триггера нужно явно вызвать инструкцию insert в вашу таблицу, иначе вставки не произойдет и тут сложность с применением identity колонки, поскольку на момент срабатывания триггера instead of в логической таблице inserted колонка идентификации не наполняется данными зачем вы вообще выбрали тип используемого триггера как instead of вместо for/after? ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 10:04 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
Спасибо, джентельмены! То, что популярно Вы объяснили я и хотел выяснить своим вопросом. Почему выбран триггер INSTEAD OF? Все очень просто - поле фамилия (или номер документа) не может содержать пробелов как таковых. Они мною запрещены для ввода CHECK'ом для полей. Поскольку пользователи очень часто копируют\вставляют в поля ввода данные, например из ворда или экселя, попадаются лидирующие\ конечные пробелы (чаще всего). По роду деятельности мне необходимо выгружать данные из экселя в базу ФРДО (федеральная база по дипломам). Очень напрягает, когда из-за того, что в поле фамилия есть конечный пробел, все записи отбрасываются. Что мешает их ликвидировать на уровне проверки данных и отбрасыванию лишних пробелов программными средствами SQL тамошними программистами - для меня загадка. Вот и не хочу походить на них, чтобы меня будущие пользователи (как я сейчас) не вспоминали "добрым словом". To Felix_ff: Если не трудно поясните свои мысли по поводу съезда логики с п2 Почему п4 не выполним? Ведь таблица inserted хоть и виртуальная, но таблица? Поможет ли мне переменная @@RowCount при движении по таблице inserted? Если как я первоначально в первом посте предполагал, что мне надо из триггера самому обновлять целевую таблицу, то как действительно быть с уникальным значением? Считывать последний из таблицы и присваивать новое значение новой записи? Одно прояснилось - другое замутилось :( ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 10:34 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
авторВ теле триггера пишу нечто похожее @переменная1 = SELECT Поле2 from inserted Представьте себе, что произойдет, если в таблице inserted будет больше одной строки. Какое значение в этом случае будет у @переменная1 ? ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 10:39 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh Почему выбран триггер INSTEAD OF? Все очень просто - поле фамилия (или номер документа) не может содержать пробелов как таковых. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 10:59 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
To Felix_ff: Если не трудно поясните свои мысли по поводу съезда логики с п2 Почему п4 не выполним? Ведь таблица inserted хоть и виртуальная, но таблица? Поможет ли мне переменная @@RowCount при движении по таблице inserted? Если как я первоначально в первом посте предполагал, что мне надо из триггера самому обновлять целевую таблицу, то как действительно быть с уникальным значением? Считывать последний из таблицы и присваивать новое значение новой записи? Мне тоже интересно, возможно ли такое? :) Всегда считал, что inserted и deleted можно только читать, но не изменять в документации написано Инструкции триггеров DML используют две особые таблицы: deleted и inserted. SQL Server автоматически создает эти таблицы и управляет ими. Эти временные таблицы, находящиеся в оперативной памяти, используются для проверки результатов изменений данных и для установки условий срабатывания триггеров DML. Нельзя в этих таблицах изменять данные напрямую или выполнять над ними операции языка описания данных DDL, например инструкцию CREATE INDEX. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 11:51 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
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.
возьмет по сути рандомное значение (обычно последнее в плане сканирующего оператора, но это поведение может в любой момент поменяться) если хотите париться с получением identity в триггере instead of можете почитать про финт ушами с merge + output внутри триггера но это если честно извращение. invm дал Вам вполне дельную рекомендацию что результат которого вы добиваетесь вполне достижым без использования триггеров. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 12:23 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh, ETL задачи лучше решать средствами Integration services, там и пробелы можно выкинуть, и форматировать ФИО и еще много чего. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 15:02 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
Добрый вечер, джентельмены! Похоже, что некоторые читают только последние сообщения, не прочив суть вопроса. To invm: Имеется таблица со структурой: РК int Фамилия nvarchar(max) На поле фамилия стоит CHECK [а-я-] Про какое вычисляемое поле Вы говорите? Как поможет представление (view) исправить проблему с пробелами, если сработает CHECK и запись будет отброшена? Я не зря спросил про @@RowCount (если верить описанию, то эта переменная содержит кол-во строк последней операции, в данном случае, кол-во вставленных строк в таблице ) To gotsql: Вы путаете DDL и DML (первое управляет структурой таблицы, например создание индексов, второе управляет данными insert, update, delete). Я не изменяю структуру таблицы, я меняю содержимое строки таблицы... Если у уважаемого сообщества есть более разумные предложения - раза 2 в неделю буду читать топик. Сейчас в отпуске, на даче... Буду пытаться штудировать буржуйские источники информации... По результатам, естественно отпишусь... ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 15:03 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh, Код: sql 1. 2. 3. 4. 5. 6. 7.
Код: sql 1. 2. 3. 4. 5. 6. 7.
далее используете view вместо таблицы если у вас эта таблица не используется прямо сразу в режиме онлайна после балк лоада, может лучше разбить процесс загрузку на несколько этапов? загружаете данные с stage-таблицу, модифицируете, переливаете в боевую таблицу. как альтернатива используйте SSIS для заливки данных оно как раз как ETL решение прекрасно подходит. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 15:16 |
|
Про триггеры INSTEAD OF вопросы
|
|||
---|---|---|---|
#18+
edward_sh РК int Фамилия nvarchar(max) На поле фамилия стоит CHECK [а-я-] Про какое вычисляемое поле Вы говорите? Код: sql 1. 2. 3. 4. 5. 6.
... |
|||
:
Нравится:
Не нравится:
|
|||
13.07.2020, 15:42 |
|
|
start [/forum/topic.php?fid=46&fpage=54&tid=1685884]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
38ms |
get topic data: |
12ms |
get forum data: |
2ms |
get page messages: |
53ms |
get tp. blocked users: |
2ms |
others: | 277ms |
total: | 415ms |
0 / 0 |