powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Сравнение СУБД [игнор отключен] [закрыт для гостей] / Триггеры
25 сообщений из 28, страница 1 из 2
Триггеры
    #32134656
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предлагаю обменяться мнениями относительно поддержки триггеров в разных СУБД.
SQL Server - instead-of и after. Вспыхивают на операцию, а не на отдельную запись. After - вешаются только на таблицы, может быть много на каждую операцию, есть возможность задать, кто будет стрелять первым, кто последним. Instead-of - вешаются на таблицы и представления, по одному на каждую операцию, традиционно используются для задания ссылочной целостности, более сложной нежели декларативная, и для создания обновляемых вьюх, классически не являющихся таковыми.
Before-триггеров нет. (Буду признателен за примеры их полезности).
...
Рейтинг: 0 / 0
Триггеры
    #32134702
DimaR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня знаний не так моно но попробую вкратце расказать про Oracle

Есть тригеры:
BEFORE, AFTER, INSTEAD OF
dml_event: Это операции с данными: DELETE INSERT UPDATE
может быть для каждой строки или для оператора.

ddl_event: Это операции над структурой базы типа ALTER, RENAME, GRANT ...иеще много, т.е. изменение структуры таблиц, привелегии ит.д
млжет быть на схему конкретного пользователя или базу.

database_event: это коннект-дисконнект пользователя, запуск-останов базы, ошибка сервера.

в качестве тела тригера используеться pl/sql блок,
ну и дополнительно (это не только в тригере) возиожность выполнения автономной транзакции, т.е. независимой от транзакции пользователя.
Если чего не так, или не дописал поправте.
...
Рейтинг: 0 / 0
Триггеры
    #32134720
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Триггеров на DDL и сист.события типа connect/disconnect в SQL Server нет. По слухам, обещают в след.версии. Согласен, что это удобно.
...
Рейтинг: 0 / 0
Триггеры
    #32134758
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
"Before-триггеров нет. (Буду признателен за примеры их полезности)."
У нас есть поле которое генерится автоматически, но пользователь может исходя из каких-то своих соображений ввести свое значение, так вот в Before тригере я проверяю, если это поле null, то я генерю сам, иначе использую значение пользавателя.
Например это используется при генерации латинского написания русского имени.
...
Рейтинг: 0 / 0
Триггеры
    #32134769
Roman Ignatiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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

Удобно - автоинкремент, но отрабатывает только если клиент не задал значения поля.
...
Рейтинг: 0 / 0
Триггеры
    #32134791
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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)
...
Рейтинг: 0 / 0
Триггеры
    #32134805
AI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Дед Маздай.

Потому что как-то неаккуратненько так делать...

Немного уточню по оракулу. instead of триггеры вешаются только на вьюшки. И в теле триггера можно вызывать процедуры PL/SQL & java.
...
Рейтинг: 0 / 0
Триггеры
    #32134811
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2Дед Маздай
Я привел лишь пример.
1.Как минимум потому что твой вариант длинее.(Зачем делать инсерт, а потом апдейт,если все можно сделать в одном инсерте???)
2.Если нужно будет вставлять много записей, то твой вариант будет работать очень медленно.
Все можно сделать, как правило, несколькими методами. Можно вообще не использавать тригеры.
...
Рейтинг: 0 / 0
Триггеры
    #32134841
Crip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Если нужно будет вставлять много записей, то твой вариант будет работать очень медленно.

Да ну ... Насколько я понимаю на id весит кластерный индекс...Все пройдет быстро
...
Рейтинг: 0 / 0
Триггеры
    #32134845
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А кстати, что у любой таблицы должен быть primary key???
А если его нет?
...
Рейтинг: 0 / 0
Триггеры
    #32134855
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Al
Почему неаккуратненько?

2nick
Если нужно вставлять много записей (insert ... select), то мне кажется, мой вариант будет быстрее, потому что он срабатывает сразу для всех вставляемых записей, а не идет по каждой, как курсор.

На самом деле Вы и Roman Ignatiev навели меня на пример, когда, по-видимому, без before-триггера не обойтись. Я имею в виду не саму генерацию автоинкремента, которая решается с помощью identity (SQL Server) или sequence (Oracle), а вставку null в поле not null. Instead-of триггер (по крайней мере в SQL Server) срабатывает раньше любых констрейнтов, кроме not null и identity.
...
Рейтинг: 0 / 0
Триггеры
    #32134874
Roman Ignatiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насчет вставки NULL в поле not NULL - немного не понял...
Имеется в виду проверка - если значение NULL, то присвоить что-то?
Дело в том, что если поле not NULL и содержит NULL - в IB это никак не пройдет - проверка сработает.
...
Рейтинг: 0 / 0
Триггеры
    #32134916
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, для генерации ключей или что-то вроде своего инкрементного поля это было-бы полезно. А в ИБ текст типа
create trigger ....
before insert
as
begin
if (NEW.MyField is NULL) then
NEW.MyField = Gen_ID(MyGenerator,1);
end
получается, не будет работать, если MyField - ПК?

А можно спросить знатоков - в Oracle можно работать со всеми изменёнными записями, т.е. есть-ли там таблицы типа inserted/deleted?
...
Рейтинг: 0 / 0
Триггеры
    #32134931
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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'.
...
Рейтинг: 0 / 0
Триггеры
    #32134959
Roman Ignatiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бррр... Понял - вставляешь Null и хочешь, чтобы в триггере подставилось значение по-умолчанию.
Да, типичная задача для before.
2alexeyvg
Будет он работать, проверка на not null в IB идет после before триггера (вообще все check, not null, foreign key и тд идут после), так что так и подставляется, и не важно, первичный ключ или нет.
И, кстати, наконец-то я понял как применять instead of - ручками вставляешь в таблицы. Удобно, когда, например, view не обновляемое. В IB нет такого :-( В before просто ставишь/уточняешь/проверяешь значения полей, потом запись вставляется в таблицу, делается проверка целостности и отрабатывают триггеры на after, в которых значения полей уже не поменяешь (ошибку, кстати, тоже не дает, просто игнорирует присвоение NEW).
...
Рейтинг: 0 / 0
Триггеры
    #32134992
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>"Понял - вставляешь Null и хочешь, чтобы в триггере подставилось значение по-умолчанию"
Есть ли в IB возможность сделать default на поле декларативно, без before?
То же для автоинкремента?
...
Рейтинг: 0 / 0
Триггеры
    #32135007
Roman Ignatiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
для каждой таблицы с автоинкрементом, и присваивать значение полю на клиенте. В соединении с упомянутым триггером работает великолепно.
Ну и плюс - генераторы можно применять не только для автоинкремента :-)
...
Рейтинг: 0 / 0
Триггеры
    #32135012
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вдогонку: если в 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)
...
Рейтинг: 0 / 0
Триггеры
    #32135014
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вообще-тоя триггер 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' ('текст ошибки')

Т.е. можно задать несколько триггеров на одну таблицу
Триггеры выполняются в порядке создания.
...
Рейтинг: 0 / 0
Триггеры
    #32135016
Roman Ignatiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не пробовал... Но дело в том, что после выполнения before будет попытка вставить запись во view, а оно не обновляемое. Избежать этого можно только дав Exception в триггере, а это откатит всю транзакцию :-))
...
Рейтинг: 0 / 0
Триггеры
    #32135026
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2Дед Маздай
"Если нужно вставлять много записей (insert ... select), то мне кажется, мой вариант будет быстрее, потому что он срабатывает сразу для всех вставляемых записей, а не идет по каждой, как курсор. "
Не будет. Потому что никакого курсора нет, так так используется строчный тригер.
И как ты собираешься использовать свой тригер для моей задачи("срабатывает сразу для всех вставляемых записей")???
...
Рейтинг: 0 / 0
Триггеры
    #32135032
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Строчный триггер = идет позаписьно. Чем это отличается от курсора?
В Oracle есть возможность выбирать for statement / for row, как нам это демонстрировал gardenman в случае DB2?
...
Рейтинг: 0 / 0
Триггеры
    #32135038
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я не совсем понял как там у DB.
Просто в Oracle перед тем как вставить данные в строку выполняется тригер before for each row
и все тело тригера выглядит так
if :new.latname is null then
:new.latname:=fun(:new.rusname);
end if;
никакого курсора нет
...
Рейтинг: 0 / 0
Триггеры
    #32135051
Фотография tygra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще по поводу триггеров Before и After:
тут все удобство/неудобство зависит только от привычки.
Работал я раньше на InterBase - использовал Before.
Потом переход на MS SQL тоже был тяжел в этом отношении - как так без Before.
Но ничего, привык. Теперь уж и не хочется ничего менять Before. И нет проблем.
...
Рейтинг: 0 / 0
Триггеры
    #32135060
Alexander_Chepack
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
Триггеров на системные события как таковых нет, но при желании всегда 
можно сделать их на системные таблицы 


А лучше всего (при желании) прежде чем писать что-то, самому проверить.
Триггеры на системные таблицы в SQL Server сделать НЕВОЗМОЖНО.
...
Рейтинг: 0 / 0
25 сообщений из 28, страница 1 из 2
Форумы / Сравнение СУБД [игнор отключен] [закрыт для гостей] / Триггеры
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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