SQL Update Trigger
8 отговора
245 прегледа
SQL Update Trigger
Като пиша Update Trigger за MS SQL (MSDE) по какво разбирам коя е старата стойност на обновявано поле, както и каква е новата, която му се присъединява? И още - в таблиците inserted i deleted moje li da ima po poveche ot edin zapis?
Re: SQL Update Trigger
Старата стойност е в делетед, новата стойност е в инсертед.
>>в таблиците inserted i deleted moje li da ima po poveche ot edin zapis?
може.
>>в таблиците inserted i deleted moje li da ima po poveche ot edin zapis?
може.
Re: SQL Update Trigger
Не разбрах. Как така, когато правиш UPDATE тригер старата стойност ти е в DELETED???
I think its kinda funny I think its kinda sad the dreams in which Im dying are the best Iv ever had
I think its kinda funny I think its kinda sad the dreams in which Im dying are the best Iv ever had
пример с коментар
Праиме си две таблици за простота с еднаква структура. Праиме ги в темпдб та да не развалиме нещо без да искаме. xsql е корн шел враппер на isql - да не се абиме да въвеждаме пасуърди всеки път.
Примера е на сайбейз, ама на мс сял сержер е същото (не говорим за "инстеад" тригерите дето ги има само в мс сял сержер )
Таблицата а ще ни е оперативната таблица, а в таблицата h искаме да записваме всички промени който са направени в а. С малко повече код може да се записва не само промяната, но и датата, кой я е направил и т.н.
7719 xsql -d tempdb "create table a(a int)"
7720 xsql -d tempdb "create table h(a int)"
Тая работа ще стане с долния тригер. Както казах делетед съдържа записа преди промяната (а инсертед -- след)
7721 xsql -d tempdb "create trigger upd_trig on a for update as
insert into h select * from deleted"
Дай да въведеме един ред, та да има кво да променяме:
7722 xsql -d tempdb "insert into a (a) values 1"
е сопи единицата разбира се трябва да е в скоби:
7723 xsql -d tempdb "insert into a (a) values (1)"
А сега да смени единицата на 2
7724 xsql -d tempdb "update a set a=2 where a=1"
и да видим кво става в таблицата h:
7725 xsql -d tempd "select * from h"
е пак сори темпдБ а не темпд:
7726 xsql -d tempdb "select * from h"
Using 'sa' on server <името изтрито от съображения за сигърност>
Password:
a
-----------
1
Та така да обобщим тригера е голяма работа -- гарантира че квото си сложил в него ще се изпълнява както и да се упдейтва таблицата -- с твойта апликация, с апликацията, която ще напише някой дурак след две години на съвсем друг език, със сторед процедура или без и изобщо -- железно.
между другото таблиците инсертед и делетед се "създават" само за таблици с тригери и по същество са вю-та върху транзакционния лог.
Тр. логът както е известно е write-ahead, което означава че промените се записват първо там (гарантирано), а в самата база (data pages) kogato i ako serwera реши че няма кво друго да прави. Когато спреш сървера и го стартираш пак (или го стартираш след като машината е умряла по някакви причини), той праи recovery -- т.е. чете лога и нанася промените в the data pagеs.
Та като кажеш упдейт, сървера първо пише в лога старото състояние на страниците за да може да го възстанови ако неще се усере преди края на транзакцията -- например ако упдейта засяга 5 страници и на четвъртата процесът ти се дедлокне и сервера реши да го убие.
После записва в лога новото състояние на страниците, за да може да ти го възстанови ако нещо се усере след края на транзакцията (и за да може да направи рековери при стартуп).
Айде стига че стана утре, изписах си ръцете, а ти и една бира не предлагаш.

Примера е на сайбейз, ама на мс сял сержер е същото (не говорим за "инстеад" тригерите дето ги има само в мс сял сержер )
Таблицата а ще ни е оперативната таблица, а в таблицата h искаме да записваме всички промени който са направени в а. С малко повече код може да се записва не само промяната, но и датата, кой я е направил и т.н.
7719 xsql -d tempdb "create table a(a int)"
7720 xsql -d tempdb "create table h(a int)"
Тая работа ще стане с долния тригер. Както казах делетед съдържа записа преди промяната (а инсертед -- след)
7721 xsql -d tempdb "create trigger upd_trig on a for update as
insert into h select * from deleted"
Дай да въведеме един ред, та да има кво да променяме:
7722 xsql -d tempdb "insert into a (a) values 1"
е сопи единицата разбира се трябва да е в скоби:
7723 xsql -d tempdb "insert into a (a) values (1)"
А сега да смени единицата на 2
7724 xsql -d tempdb "update a set a=2 where a=1"
и да видим кво става в таблицата h:
7725 xsql -d tempd "select * from h"
е пак сори темпдБ а не темпд:
7726 xsql -d tempdb "select * from h"
Using 'sa' on server <името изтрито от съображения за сигърност>
Password:
a
-----------
1
Та така да обобщим тригера е голяма работа -- гарантира че квото си сложил в него ще се изпълнява както и да се упдейтва таблицата -- с твойта апликация, с апликацията, която ще напише някой дурак след две години на съвсем друг език, със сторед процедура или без и изобщо -- железно.
между другото таблиците инсертед и делетед се "създават" само за таблици с тригери и по същество са вю-та върху транзакционния лог.
Тр. логът както е известно е write-ahead, което означава че промените се записват първо там (гарантирано), а в самата база (data pages) kogato i ako serwera реши че няма кво друго да прави. Когато спреш сървера и го стартираш пак (или го стартираш след като машината е умряла по някакви причини), той праи recovery -- т.е. чете лога и нанася промените в the data pagеs.
Та като кажеш упдейт, сървера първо пише в лога старото състояние на страниците за да може да го възстанови ако неще се усере преди края на транзакцията -- например ако упдейта засяга 5 страници и на четвъртата процесът ти се дедлокне и сервера реши да го убие.
После записва в лога новото състояние на страниците, за да може да ти го възстанови ако нещо се усере след края на транзакцията (и за да може да направи рековери при стартуп).
Айде стига че стана утре, изписах си ръцете, а ти и една бира не предлагаш.
Re: пример с коментар
Е те това:
7721 xsql -d tempdb "create trigger upd_trig on a for update as
insert into h select * from deleted"
не го знаех че го може. Мислех че има само updated таблица.
А иначе аз съм много фен на INSTEAD OF тригерите. Вярно че като са ги копнали от оракула МС са ги поокепазили малко, ама пак вършат много работа. В момента ги ползвам за приспособяване на около 50 000 реда код към нова (доста по-различна) структура на базата и съм страшно доволен от това че само 20-на вюта ще напиша.
Бира черпя, ама франко дейв & бъстърс в ориндж, ца.
I think its kinda funny I think its kinda sad the dreams in which Im dying are the best Iv ever had
7721 xsql -d tempdb "create trigger upd_trig on a for update as
insert into h select * from deleted"
не го знаех че го може. Мислех че има само updated таблица.
А иначе аз съм много фен на INSTEAD OF тригерите. Вярно че като са ги копнали от оракула МС са ги поокепазили малко, ама пак вършат много работа. В момента ги ползвам за приспособяване на около 50 000 реда код към нова (доста по-различна) структура на базата и съм страшно доволен от това че само 20-на вюта ще напиша.
Бира черпя, ама франко дейв & бъстърс в ориндж, ца.
I think its kinda funny I think its kinda sad the dreams in which Im dying are the best Iv ever had
Re: пример с коментар
Е радвам се че съм казал нещо интересно.
Между впрочем инстеад оф тригерите съм ги чувал само с едно ухо, така че ако ти попадне линк дето обяснява какво е това и има ли почва у нас -- постни го.
На тоя етап не ме интересуват сложнотии -- само идеята.
Айде, па ако не в Оринж ЦА, то поне в НЪЦ (NYC) може да пием бирата.
Между впрочем инстеад оф тригерите съм ги чувал само с едно ухо, така че ако ти попадне линк дето обяснява какво е това и има ли почва у нас -- постни го.
На тоя етап не ме интересуват сложнотии -- само идеята.
Айде, па ако не в Оринж ЦА, то поне в НЪЦ (NYC) може да пием бирата.
По-типичен пример
Тригера по долу е по-типичен и илюстрира употребата за поддържане на реф. интегрити на бд.
create trigger <име на триг>
on <име на таблица>
for delete
as
begin
/* FIND HOW MANY ROWS WHERE MODIFIED */
/* отлична идея -- ако операцията не прави нищо, що да се */
/* абиме да бършим безсмислена работа */
if ( @@rowcount = 0 )
return
/* CHECK EXISTENCE IN <табл-родител> */
if exists (select *
from <табл-родител> UGCN, deleted DELE
where UGCN.f_ugrp_id_code = DELE.f_ugrp_id_code
and UGCN.f_pack_id_code = DELE.f_pack_id_code)
begin
raiserror 20002 "тая нема да я бъде"
/* транзакцията която се ролбеква е оригиналната операция */
rollback transaction
return
end
end
go
create trigger <име на триг>
on <име на таблица>
for delete
as
begin
/* FIND HOW MANY ROWS WHERE MODIFIED */
/* отлична идея -- ако операцията не прави нищо, що да се */
/* абиме да бършим безсмислена работа */
if ( @@rowcount = 0 )
return
/* CHECK EXISTENCE IN <табл-родител> */
if exists (select *
from <табл-родител> UGCN, deleted DELE
where UGCN.f_ugrp_id_code = DELE.f_ugrp_id_code
and UGCN.f_pack_id_code = DELE.f_pack_id_code)
begin
raiserror 20002 "тая нема да я бъде"
/* транзакцията която се ролбеква е оригиналната операция */
rollback transaction
return
end
end
go
Re: пример с коментар
[линк]
Ами ако ми се случи да намина ще се обадя. Мисля да се отбия до нъц, че не съм бил още.
I think its kinda funny I think its kinda sad the dreams in which Im dying are the best Iv ever had
Ами ако ми се случи да намина ще се обадя. Мисля да се отбия до нъц, че не съм бил още.
I think its kinda funny I think its kinda sad the dreams in which Im dying are the best Iv ever had
Re: По-типичен пример
Забележка - Този тригер НЕ гарантира реф. интегрити на базата. По принцип е много трудно да постигнеш абсолютен интегритет без декларативни констрейнти. Доколкото разбирам, идеята на този тригер е да не можеш да изтриеш от таблицата запис, ако в родителската таблица има съответен запис. Обаче, в момента в който един user прави тази проверка в тригера и тя е успешна, т.е. няма запис в <табл-родител>, друг е инсертнал съответен запис в <табл-родител>, който първият не вижда, защото вторият още не е commit-нал. Първият доволно си commit-ва, след малко и вторият също и какво получаваме - боклучави данни.
Мисълта ми е, че при всички положения трябва да се направят всички усилия да се ползват декларативните средства са осигуряване на интегритет, които дадената база ни предоставя, и чак след това да се търсят някакви решения, които във всички случаи имат някакви сериозни недостатаци.
Мисълта ми е, че при всички положения трябва да се направят всички усилия да се ползват декларативните средства са осигуряване на интегритет, които дадената база ни предоставя, и чак след това да се търсят някакви решения, които във всички случаи имат някакви сериозни недостатаци.