Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Предлагаю обменяться мнениями относительно поддержки триггеров в разных СУБД. SQL Server - instead-of и after. Вспыхивают на операцию, а не на отдельную запись. After - вешаются только на таблицы, может быть много на каждую операцию, есть возможность задать, кто будет стрелять первым, кто последним. Instead-of - вешаются на таблицы и представления, по одному на каждую операцию, традиционно используются для задания ссылочной целостности, более сложной нежели декларативная, и для создания обновляемых вьюх, классически не являющихся таковыми. Before-триггеров нет. (Буду признателен за примеры их полезности). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 13:23 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
У меня знаний не так моно но попробую вкратце расказать про Oracle Есть тригеры: BEFORE, AFTER, INSTEAD OF dml_event: Это операции с данными: DELETE INSERT UPDATE может быть для каждой строки или для оператора. ddl_event: Это операции над структурой базы типа ALTER, RENAME, GRANT ...иеще много, т.е. изменение структуры таблиц, привелегии ит.д млжет быть на схему конкретного пользователя или базу. database_event: это коннект-дисконнект пользователя, запуск-останов базы, ошибка сервера. в качестве тела тригера используеться pl/sql блок, ну и дополнительно (это не только в тригере) возиожность выполнения автономной транзакции, т.е. независимой от транзакции пользователя. Если чего не так, или не дописал поправте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 13:58 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Триггеров на DDL и сист.события типа connect/disconnect в SQL Server нет. По слухам, обещают в след.версии. Согласен, что это удобно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 14:13 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
"Before-триггеров нет. (Буду признателен за примеры их полезности)." У нас есть поле которое генерится автоматически, но пользователь может исходя из каких-то своих соображений ввести свое значение, так вот в Before тригере я проверяю, если это поле null, то я генерю сам, иначе использую значение пользавателя. Например это используется при генерации латинского написания русского имени. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 14:43 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
IB/FB Есть триггеры before и after действия. Подключаются на таблицы и view, правда, view я не пользуюсь, поэтому ничего о них сказать особого не могу. Триггеров на системные события как таковых нет, но при желании всегда можно сделать их на системные таблицы - по крайней мере на DDL отрабатывать будут. Честно говоря, не знаю, для чего это нужно. Триггер отрабатывает для каждой записи, можно установить порядок их выполнения. Естественно, возможно несколько триггеров на одно действие, лишь бы имена различались. По поводу применения триггеров before - у меня такие же непонятки насчет применения instead-of. А в before обычно выполняют следующие действия: 1. Заполнение дополнительных полей данными, например, автоинкремент или преобразование значения поля в верхний регистр и тд. Вычислимые поля хотя и есть, но не индексируются, поэтому часто удобно просто создать служебное поле, заполнить его значением другого в верхнем регистре - и готов case insensitive поиск по индексу. 2. Дополнительная проверка ссылочной целостности - foreign key и check отрабатывает между триггерами before & after, но выдает не слишком читабельные сообщения, поэтому удобно проверить в before и выдать исключение вида "А вот так делать нельзя" - в случае исключения дальше не идет и транзакция откатывается Насчет остального - в триггере before запись в таблице еще не изменена (не вставлена/не удалена), в after - уже сделано. В триггере доступны префиксы OLD & NEW - там, где имеют смысл, соответственно, старое и новое значение поля. Присвоение значения переменным NEW.<FieldName> и тд не вызывает, естественно, новой отработки триггера. Имхо, наиболее часто встречается триггер вида create trigger .... before insert as begin if (NEW.MyField is NULL) then NEW.MyField = Gen_ID(MyGenerator,1); end Удобно - автоинкремент, но отрабатывает только если клиент не задал значения поля. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 14:53 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
2nick Почему эту проверку нельзя сделать при помощи after-триггера? if exists(select 1 from information_schema.tables where table_name = 't' and table_type = 'BASE TABLE') drop table t create table t (id int identity primary key, fld nvarchar(10)) if objectproperty(object_id('tr1'), 'ExecIsAfterTrigger') = 1 drop trigger tr1 go create trigger tr1 on t after insert as update t set fld = 'Пусто' from t inner join inserted i on t.id = i.id where i.fld is null go insert t (fld) values (null) select * from t id fld ----------- ---------- 1 Пусто (1 row(s) affected) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 15:08 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
2 Дед Маздай. Потому что как-то неаккуратненько так делать... Немного уточню по оракулу. instead of триггеры вешаются только на вьюшки. И в теле триггера можно вызывать процедуры PL/SQL & java. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 15:17 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
2Дед Маздай Я привел лишь пример. 1.Как минимум потому что твой вариант длинее.(Зачем делать инсерт, а потом апдейт,если все можно сделать в одном инсерте???) 2.Если нужно будет вставлять много записей, то твой вариант будет работать очень медленно. Все можно сделать, как правило, несколькими методами. Можно вообще не использавать тригеры. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 15:21 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
>Если нужно будет вставлять много записей, то твой вариант будет работать очень медленно. Да ну ... Насколько я понимаю на id весит кластерный индекс...Все пройдет быстро ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 15:43 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
А кстати, что у любой таблицы должен быть primary key??? А если его нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 15:46 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
2Al Почему неаккуратненько? 2nick Если нужно вставлять много записей (insert ... select), то мне кажется, мой вариант будет быстрее, потому что он срабатывает сразу для всех вставляемых записей, а не идет по каждой, как курсор. На самом деле Вы и Roman Ignatiev навели меня на пример, когда, по-видимому, без before-триггера не обойтись. Я имею в виду не саму генерацию автоинкремента, которая решается с помощью identity (SQL Server) или sequence (Oracle), а вставку null в поле not null. Instead-of триггер (по крайней мере в SQL Server) срабатывает раньше любых констрейнтов, кроме not null и identity. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 15:56 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Насчет вставки NULL в поле not NULL - немного не понял... Имеется в виду проверка - если значение NULL, то присвоить что-то? Дело в том, что если поле not NULL и содержит NULL - в IB это никак не пройдет - проверка сработает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 16:08 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Да, для генерации ключей или что-то вроде своего инкрементного поля это было-бы полезно. А в ИБ текст типа create trigger .... before insert as begin if (NEW.MyField is NULL) then NEW.MyField = Gen_ID(MyGenerator,1); end получается, не будет работать, если MyField - ПК? А можно спросить знатоков - в Oracle можно работать со всеми изменёнными записями, т.е. есть-ли там таблицы типа inserted/deleted? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 16:40 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
2Roman Ignatiev Да, я имел в виду, что проверка not null срабатывает раньше instead-of триггера. Т.е. если create table t (id int identity primary key, fld char(3) not null) create trigger tr1 on t instead of insert as insert t (fld) select coalesce(fld, 'Пусто') from inserted то insert t (fld) values (null) не пройдет. Для всех остальных констрейнтов instead-of триггер срабатывает раньше. Напр. create table t (id int identity primary key, fld varchar(3) check (fld like '[0-9][0-9][0-9]')) create trigger tr1 on t instead of insert as insert t (fld) select case when fld like '[0-9][0-9][0-9]' then fld else '000' end from inserted insert t (fld) values (1) - вмешивается триггер, вставляет '000'. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 16:49 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Бррр... Понял - вставляешь Null и хочешь, чтобы в триггере подставилось значение по-умолчанию. Да, типичная задача для before. 2alexeyvg Будет он работать, проверка на not null в IB идет после before триггера (вообще все check, not null, foreign key и тд идут после), так что так и подставляется, и не важно, первичный ключ или нет. И, кстати, наконец-то я понял как применять instead of - ручками вставляешь в таблицы. Удобно, когда, например, view не обновляемое. В IB нет такого :-( В before просто ставишь/уточняешь/проверяешь значения полей, потом запись вставляется в таблицу, делается проверка целостности и отрабатывают триггеры на after, в которых значения полей уже не поменяешь (ошибку, кстати, тоже не дает, просто игнорирует присвоение NEW). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:09 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
>"Понял - вставляешь Null и хочешь, чтобы в триггере подставилось значение по-умолчанию" Есть ли в IB возможность сделать default на поле декларативно, без before? То же для автоинкремента? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:28 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Default - конечно можно, стандарт А вот identity - такого нет, есть генераторы. И, на мой взгляд, это на порядок удобнее, чем identity. Приведу пример: На клиенте - связка master-detail, что довольно типично, причем связь по полю с identity. Пользователь вставляет запись в мастера, и хочет вставить записи в detail... А чтобы получить значение поля связи, я должен послать запись на сервер и перечитать запись (хотя бы это поле). - неудобно. С IB - просто, можно дать select Gen_ID(<Generator>,1) from rdb$database - в этой таблице всегда одна запись. Я предпочитаю честно создать процедуру create procedure MyTable_ID returns (ID integer) as begin ID = Gen_ID(MyTableGen,1); end для каждой таблицы с автоинкрементом, и присваивать значение полю на клиенте. В соединении с упомянутым триггером работает великолепно. Ну и плюс - генераторы можно применять не только для автоинкремента :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:41 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Вдогонку: если в IB можно вешать before на view, то почему не сделать классически необновляемый view обновляемым при помощи before так же, как в SQL Srv это делается при помощи instead of? create table t (id int primary key, fld float) create view v as select id, fld * 10 as x from t insert v(id, x) values (1, 5) --Update or insert of view or function 'v' failed because it contains a derived or constant field. create trigger tr1 on v instead of insert as insert t (id, fld) select id, x/10 from inserted insert v(id, x) values (1, 5) select * from t id fld ----------- ----------------------------------------------------- 1 0.5 (1 row(s) affected) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:44 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
вообще-тоя триггер before в DB2 использавал примерно след. образом CREATE TRIGGER MyTrig1 NO CASCADE BEFORE INSERT ON MyTable FOR ESCH ROW (может быть FOR EACH STATEMENT) REFERENCING NEW AS N MODE DB2SQL BEGIN ATOMIC SET N.MyField1=(SELECT *офигительный запрос*); SET N.MyField2=( ); END или CREATE TRIGGER MyTrig2 NO CASCADE BEFORE INSERT ON MyTable FOR ESCH ROW (может быть FOR EACH STATEMENT) REFERENCING NEW AS N MODE DB2SQL WHEN (Какое-то условие с селектами и всякими проверками) SIGNAL SQLSTATE '7500X' ('текст ошибки') Т.е. можно задать несколько триггеров на одну таблицу Триггеры выполняются в порядке создания. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:47 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Не пробовал... Но дело в том, что после выполнения before будет попытка вставить запись во view, а оно не обновляемое. Избежать этого можно только дав Exception в триггере, а это откатит всю транзакцию :-)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:48 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
2Дед Маздай "Если нужно вставлять много записей (insert ... select), то мне кажется, мой вариант будет быстрее, потому что он срабатывает сразу для всех вставляемых записей, а не идет по каждой, как курсор. " Не будет. Потому что никакого курсора нет, так так используется строчный тригер. И как ты собираешься использовать свой тригер для моей задачи("срабатывает сразу для всех вставляемых записей")??? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 17:57 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Строчный триггер = идет позаписьно. Чем это отличается от курсора? В Oracle есть возможность выбирать for statement / for row, как нам это демонстрировал gardenman в случае DB2? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 18:09 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Я не совсем понял как там у DB. Просто в Oracle перед тем как вставить данные в строку выполняется тригер before for each row и все тело тригера выглядит так if :new.latname is null then :new.latname:=fun(:new.rusname); end if; никакого курсора нет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 18:16 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Вообще по поводу триггеров Before и After: тут все удобство/неудобство зависит только от привычки. Работал я раньше на InterBase - использовал Before. Потом переход на MS SQL тоже был тяжел в этом отношении - как так без Before. Но ничего, привык. Теперь уж и не хочется ничего менять Before. И нет проблем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 18:30 |
|
||
|
Триггеры
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 1. 2. А лучше всего (при желании) прежде чем писать что-то, самому проверить. Триггеры на системные таблицы в SQL Server сделать НЕВОЗМОЖНО. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2003, 18:41 |
|
||
|
|

start [/forum/topic.php?fid=35&msg=32135051&tid=1554371]: |
0ms |
get settings: |
7ms |
get forum list: |
12ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
28ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
38ms |
get tp. blocked users: |
1ms |
| others: | 223ms |
| total: | 322ms |

| 0 / 0 |
