SQLShack

Ez a cikk az SQL Serverben lévő triggerek letiltásának különböző módjaival foglalkozik, hogy azok ne zavarjanak bizonyos műveleteket, például a tömeges beszúrásokat.

Probléma

Volt egy olyan helyzet, amikor adatokat kellett betöltenünk az egyik adatbázisunk tábláiba. Ezekben a táblákban létrehoztunk néhány trigger-t a beszúráshoz, frissítéshez és törléshez, és ezek a triggerek “NOT FOR REPLICATION”-ként vannak beállítva. Az adatok táblákba való betöltése közben nem szeretnénk, ha ezek a triggerek kioldódnának. Arra gondoltunk, hogy letiltjuk a triggereket a táblákon, de ez letiltja őket más felhasználói tranzakciók számára is. Azt akarjuk, hogy csak az én munkamenetemben ne legyenek kilőve, ahonnan az adatbetöltési szkriptet hajtom végre. Ebben a cikkben lássuk, hogyan lehet letiltani a triggereket az SQL Serverben egy bizonyos.

megoldás

Először meg kell értenünk a “NOT FOR REPLICATION” fogalmát az SQL Serverben.

A NOT FOR REPLICATION az SQL Serverben a triggerek létrehozása során használható. Ez azt jelzi, hogy ezek a triggerek nem lépnek működésbe, amikor a replikációs ügynök adatmódosításokat (INSERT / UPDATE / DELETE) végez a táblán.

Nem csak az SQL Serverben lévő triggereknél, hanem idegen kulcsok, azonossági oszlopok és ellenőrzési korlátozások létrehozásakor is használható ez a súgó.

Az idegen kulcsok esetében az idegen kulcs ellenőrzése csak akkor történik meg, amikor a felhasználó adatokat módosít a táblán, és az idegen kulcsok érvényesítésére nem kerül sor, amikor a replikációs ügynök ezeket a módosításokat szinkronizálja a másik végpontra (vagy az előfizetőre, vagy az előfizetőre és a kiadóra is, a konfigurált replikáció típusától függően)

Az azonosító oszlopok esetében a replikációs ügynök adatainak a táblába való beszúrásakor nem generál új azonosító értéket, hanem az eredeti, a forrásnál generált azonosító értéket használja.

Mivel az SQL Serverben a triggerek “NOT FOR REPLICATION” jelzéssel lettek létrehozva ezekre a táblákra, ha normál felhasználóként adatot szúrunk be a táblába, ezek a triggerek működésbe lépnek. Ezek a ravaszok nem lettek kioldva, amikor a replikációs ügynök beilleszt, töröl és frissít adatokat a táblákban. Tehát úgy teszek, mintha replikációs ügynökként végezném a munkámat. (Vagyis a triggerek minden felhasználói munkamenetre ki lettek lőve, és nem lőttek ki az adott munkamenetre, amelybe replikációs ügynökként jelentkeztem be.)

Ennek szemléltetésére létrehozok két “Emp” és “EmpJoining” mintatáblát és egy trigger-t az “Emp” táblán, amely akkor lő ki, amikor egy új sor kerül beillesztésre az “Emp” táblába.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

CREATE TABLE Emp ( Empid int , name varchar (50) )
GO
CREATE TABLE EmpJoining ( Empid int, JD datetime)
GO
CREATE TRIGGER TR_INSEMPDETAILS ON Emp
FOR INSERT
NOT FOR REPLICATION
AS
BEGIN
SET NOCOUNT ON
INSERT INTO EmpJoining
SELECT Empid , GETDATE() FROM inserted
END
GO

Most például megvan az alkalmazott azonosítója, neve és csatlakozási dátuma más rendszerben, amit a fenti meglévő táblákba kell importálni. Ebben az esetben nem akarom, hogy a kiváltó logika kioldódjon, amikor az adatokat az Emp táblába illesztem be.

Alapvetően mindkét táblához van T-SQL beszúrási szkriptem, amely beilleszti az alkalmazott azonosítóját, nevét az “Emp” táblába és a csatlakozási dátumukat az “EmpJoining” táblába.

Jelentkezzünk be normál felhasználóként, és hajtsuk végre a T-SQL szkriptet az adatoknak a táblába való beszúrásához.

Login as normal user:

Open SQL Server management studio. Most jelentkezzünk be az SQL Serverre normál felhasználóként, és használjuk azt az adatbázist, ahol a táblát létrehoztuk. Az alábbi szkript segítségével szúrjon be adatokat az Emp táblába, és ellenőrizze, hogy a trigger elsült-e vagy sem.

1
2
3
4
5

INSERT INTO Emp ( Empid , name ) values ( 1 , ‘Adam’ )
select * from Emp
select * from EmpJoining

láthatjuk, hogy a trigger elsült és beillesztette az adatokat az EmpJoining táblába.

Az alábbi szkript segítségével ellenőrizhetjük a munkamenet tulajdonságot.

1
select SESSIONPROPERTY ( ‘replication_agent’ )

nullát ad vissza, ha normál felhasználóként jelentkezünk be, és egyet, ha replication agentként jelentkezünk be.

Lépések a replikációs ügynökként való bejelentkezéshez:

Most jelentkezzünk be replikációs ügynökként és szkript segítségével illesszünk be adatokat.

Zárjuk be az SQL server management studio-t és nyissuk meg újra.

Adjuk meg a szervert, a bejelentkezést és a jelszót, amit használni szeretnénk. kattintsunk az opciók gombra. Tekintse meg az alábbi képet.

Navigáljon a további kapcsolati paraméterek fülre. A további kapcsolati paraméterek táblázatban írja be a REPLICATION=TRUE szövegmezőbe az alábbi képen látható módon.

Használhatja a kívánt bejelentkezési módszert, akár windows hitelesítés, akár SQL Server hitelesítés.

Ezzel replikációs ügynökként fog bejelentkezni, és minden DML művelet, amelyet a táblán végez, replikációs ügynökként fog végrehajtódni.

Most hajtsa végre az alábbi lekérdezést annak ellenőrzésére, hogy replikációs ügynökként van-e bejelentkezve vagy sem.

1
select SESSIONPROPERTY ( ‘replication_agent’ )

Vissza kell adnia 1.

Most szúrjon be néhány sort az alábbi szkript segítségével.

1
2
3
4

INSERT INTO Emp ( Empid , name ) values ( 2 , ‘Greg’ )
select * from Emp
select * from EmpJoining

Láthatjuk, hogy a trigger nem lépett működésbe, mivel replikációs ügynökként jelentkeztünk be, és a trigger “NOT FOR REPLCIATION” értékre van állítva.

Az adatok csak az Emp táblába kerülnek beillesztésre. Kérjük, tekintse meg az alábbi képet.

Itt ebben az esetben a trigger nincs letiltva és elérhető más felhasználói tranzakciók számára, amelyek INSERT esetén tüzelni fogják a triggert. A kiváltó csak a replikációs ügynökként végrehajtott tranzakció esetében nem lép működésbe.

Az alábbi lekérdezéssel ellenőrizheti, hogy a kiváltó “NEM REPLIKÁCIÓRA” van-e jelölve vagy sem.

1
SELECT name,is_not_for_replication FROM SYS.triggers

Az SQL Serverben más módon is letilthatók a triggerek egy munkamenetre vonatkozóan, a kód feltételekkel történő kezelésével.

Például használhatja a CONTEXT_INFO() funkciót a trigger kódban és visszaadhatja. A CONTEXT_INFO() használata nem igényel külön engedélyeket.

Ebben az esetben, ha a CONTEXT_INFO megegyezik a triggerben megadott értékkel, a trigger visszatér, és nem hajtja végre az alábbi kódot. Kérjük, tekintse meg az alábbi kódot.

1
2
3
4
5
6
7
8
9
10
11
12

CREATE TRIGGER TR_INSEMPDETAILS ON Emp
FOR INSERT
AS
BEGIN
SET NOCOUNT on
DECLARE @CONT_INFO VARBINARY(128)
SELECT @CONT_INFO = CONTEXT_INFO()
IF @CONT_INFO = 0x1256698456
RETURN
INSERT INTO EmpJoining
SELECT Empid , GETDATE() FROM inserted
END

Ebben az esetben a context_info értékét 0x1256698456-ra kell állítani, mielőtt az “Emp” táblába beszúrnánk az adatokat.

A következő rendszernézetek is tárolják a kontextusinformációkat, de ezek közvetlen lekérdezése SELECT és VIEW SERVER STATE jogosultságokat igényel.

  • sys.dm_exec_requests
  • sys.dm_exec_sessions
  • sys.sysprocesses

T-SQL INSERT script helyett tegyük fel, hogy az adatok .txt fájl vagy .csv fájl. Használhatjuk a BCP UTILITY vagy a BULK INSERT opciókat, hogy adatokat töltsünk be a táblákba a triggerek elsütése nélkül.

A BCP segédprogram használata

A BCP segédprogrammal tömeges adatokat tölthetünk be a táblába triggerek elsütése nélkül az SQL Serverben. Ez a módszer csak a táblába történő BESZERZÉS esetén működik, és nem lövi ki a “beszúráshoz” és a “beszúrás helyett” létrehozott triggereket.

Alapértelmezés szerint a BCP segédprogram nem lövi ki a triggereket az adatok táblákba való betöltésekor. A triggerek végrehajtásának kikényszerítéséhez a BCP-ben a -h “FIRE_TRIGGERS” parancsot kell használnunk, miközben adatokat töltünk be a táblába.

Az alábbiakban a példában használt mintatáblákat mutatjuk be.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

CREATE TABLE USERS
(ID int,
NAME varchar(50))
CREATE TABLE USERHIST
(USERID int,
CREATEDDATE datetime )
CREATE TRIGGER INS_USERS ON USERS
FOR INSERT
AS
BEGIN
INSERT INTO USERHIST
SELECT ID,GETDATE() FROM INSERTED
END

Kérjük, tekintse meg az alábbi példát az adatok “USERS” táblába való betöltésére szolgáló alapértelmezett BCP-re, amely nem fog triggereket indítani az SQL Serverben. Az eredeti kiszolgálót, az adatbázis nevét és a bejelentkezési adatokat elfedtem.

bcp .dbo.USERS in D:\bcp.txt -T -c -S “SERVERNAME” -Uusername -Ppassword

Kérjük, tekintse meg az alábbi példát a “FIRE_TRIGGERS” tippel ellátott BCP-re, amely adatokat tölt be a USERS táblába, ami kiváltja a triggereket.

bcp .dbo.USERS a D:\bcp.txt-ben -T -c -S “SERVERNAME” -Uusername -Ppassword -h “FIRE_TRIGGERS”

A BULK INSERT használata

Ez az opció is csak a táblában végzett INSERTEK esetén fog működni, és nem lövi ki a “for insert” és “instead of insert” létrehozott triggereket.

Alapértelmezés szerint a BULK INSERT nem lövi ki a triggereket az SQL Serverben. A “FIRE_TRIGGERS”

Van egy test.txt fájlom, amely az adatok “,” mint FIELDTERMINATOR.

Kérjük, tekintse meg az alábbi kódot az alapértelmezett BULK INSERT-hez, hogy adatokat töltsön be a USERS táblába, amely nem fog kiváltani triggereket az SQL Serverben.

1
2
3
4
5
6
7
8
9

BULK
INSERT USERS
FROM ‘D:\\test.txt’ –location with filename
WITH
(
FIELDTERMINATOR = ‘,’,
ROWTERMINATOR = ‘\n’
)
GO

Kérjük, tekintse meg az alábbi kódot a “FIRE_TRIGGERS” hivatkozással, amely a tesztből történő adatbetöltéskor az SQL Serverben triggereket indít.txt fájl.

1
2
3
4
5
6
7
8
9
10

BULK
INSERT USERS
FROM ‘D:\\test.txt’ –location with filename
WITH
(
FIELDTERMINATOR = ‘,’,
ROWTERMINATOR = ‘\n’,
FIRE_TRIGGERS
)
GO

Ebben a cikkben az alábbi esetekben tárgyaltuk a triggerek viselkedését az SQL Serverben.

  1. Bejelentkezés normál felhasználóként.
  2. Bejelentkezés replikációs ügynökként, és a ravasz nem replikációra van beállítva.
  3. CONTEXT_INFO függvény használata a ravaszkódban.
  4. BCP alapértelmezett használata és “FIRE_TRIGGER”
  5. BULK INSERT alapértelmezett használata és “FIRE_TRIGGER”

A 3., 4. és 5. pontok esetében nem számít, hogy “NOT FOR REPLICATION” típusú triggereket hozunk létre vagy sem.

  • Author
  • Recent Posts
SQL Server DBA, fejlesztő jó tapasztalattal SQL Server adminisztráció, fejlesztés, teljesítmény tuning, monitoring területén, magas rendelkezésre állás és katasztrófa utáni helyreállítási technológiák

Legújabb hozzászólások: Ranga Babu (az összes)
  • Geo Replication on Transparent Data Encryption (TDE) enabled Azure SQL databases – October 24, 2019
  • A Collate SQL parancs áttekintése – 2019. október 22.
  • Elveszett SA-jelszó helyreállítása – 2019. szeptember 20.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.