piektdiena, 2011. gada 4. marts

DML trigera atslēgšana

Rakstā aprakstīts kā var aizliegt tabulas/skata DML trigera izpildi. Dots piemērs un skaidrojums, kāpēc tas ne vienmēr ir derīgs risinājums.

Tātad apskatīsim sekojošu piemēru (tabulas un trigera izveide):
Create Table dbo.TestTable
(
   TestTableID int Identity primary key,
   Skaitlis int,
   TrisBurti char(3),
   MainigsGarums NVarChar(20),
   GarsTeksts NVarChar(100),
   Deleted bit Default 0
)
go
Create Trigger tr_TestTable_Delete on dbo.TestTable
Instead Of Delete
As
    Set NoCount On
    Print 'Tiek dzēsti dati'
Tātad trigeris ziņojumu logā izvada tekstu 'Tiek dzēsti dati' tad, kad tiek dzēsti dati no tabulas. Datu dzēšanas gadījumā, trigeris nostrādā vienmēr. Ko darīt, ja mums vienā brīdī nepieciešams dzēst datus bez trigera izpildes? var izpildīt šādu komandu:
disable trigger tr_TestTable_Delete on dbo.TestTable
Go
-- Šeit Varam dzēst datus uz nebēdu, trigeris netiek izsaukts
Go
enable trigger tr_TestTable_Delete on dbo.TestTable
Skaisti! Tikai kamēr mēs darbojamies (mūsu darbību kods jāliek komentāru vietā), tikmēr trigeris nestrādās nevienam citam lietotājam. Respektīvi- visi, kas dzēsīs datus laika posmā no trigera aizliegšanas līdz atļaušanai, varēs apiet trigera izpildi.. Visbiežāk tas nav tas, ko mēs vēlamies..
Var izmantot transakciju:
Begin Tran
Go
disable trigger tr_TestTable_Delete on dbo.TestTable
Go
-- Šeit Varam dzēst datus uz nebēdu, trigeris netiek izsaukts
Go
enable trigger tr_TestTable_Delete on dbo.TestTable
Go
Commit
Šajā gadījumā ir mazliet labāk- trigeris tiek aizliegts tikai šīs transakcijas ietvaros, līdz ar to citi lietotāji nevarēs apiet trigera izpildi. Vienīgā problēma- trigera aizliegšana ir shēmas izmaiņas, tādēļ citiem lietotājiem būs aizliegtas pilnīgi visas darbības ar attiecīgo tabulu! Tātad- kamēr mūsu transakcija tiek izpildīta, tikmēr neviens neko ar tabulu nevar darīt..
Labais risinājums šai problēmai- ir veidot tādus trigerus, lai šāda trigeru "pagaidu" aizliegšana nebūtu vajadzīga. Jau daudz sliktāks risinājums varētu būt- Trigera aizliegšana vienas transakcijas ietvaros. Tomēr īsti labi tas neliekas. Un ja trigeris būtu uz skata, nevis tabulas, tad arī problēmu būtu vieglāk apiet (nu piemēram- kā aprakstīts Piemērs: Instead Of DML trigeris skatam). Ja datu bāze nav 24/7, tad droši vien problēmu nav.

Un pēc sevis satīram:
drop table dbo.TestTable

Nav komentāru:

Ierakstīt komentāru