sql >> Database teknologi >  >> RDS >> Sqlserver

SQL Server Trigger:Forståelse og alternativer

SQL Server-triggeren er en speciel type lagrede procedurer, der automatisk udføres, når en hændelse opstår på en bestemt databaseserver. SQL Server giver os to hovedtyper af triggere:DML Triggere og DDL udløser. DDL-triggerne udløses som svar på forskellige Data Definition Language-hændelser (DDL), såsom at udføre CREATE, ALTER, DROP, GRANT, DENY og REVOKE T-SQL-sætninger. DDL-udløseren kan reagere på DDL-handlingerne ved at forhindre disse ændringer i at påvirke databasen, udføre en anden handling som svar på disse DDL-handlinger eller registrere disse ændringer, der udføres mod databasen.

SQL Server DML Trigger er en speciel type lagrede procedurer, der er designet til at udføre en sekvens af handlinger på en databasetabel, som triggeren er knyttet til, når en Data Manipulation Language (DML) hændelser, såsom INSERT, UPDATE eller DELETE handling, sker for at ændre indholdet af databasetabellerne eller visningerne, uanset om tabelrækkerne er påvirket eller ej. Triggerne adskiller sig fra de lagrede procedurer ved, at triggerne udløses automatisk, når der sker en foruddefineret dataændring. DML-triggerne kan bruges til at vedligeholde dataintegritet og håndhæve virksomhedens forretningsregler, på samme måde som funktionalitet for tabelkontrol og fremmednøgler, ved at udføre revisionsprocesser og andre post-DML-handlinger. Du kan bruge DML-triggerne til at forespørge andre tabeller og udføre komplekse T-SQL-forespørgsler.

Hvis udløseren udløses, kaldes en særlig type virtuelle tabeller Indsat og Slettet tabeller vil blive brugt til at opbevare dataværdierne før og efter ændringen. Udløsererklæringen vil fungere inden for rammerne af den samme transaktion, som udløser den udløser. Det betyder, at transaktionen ikke vil blive forpligtet fuldstændigt, før triggererklæringen er gennemført med succes. På den anden side vil transaktionen blive rullet tilbage, hvis triggersætningen mislykkes.

Der er to typer DML-udløsere:EFTER eller FOR trigger og I STEDET FOR udløser. AFTER-triggeren udløses og udføres efter at have udført handlingen INSERT, UPDATE eller DELETE, der aktiverer den. Alle referencekaskadehandlinger og begrænsningstjek bør også lykkes, før udløseren udløses. AFTER-udløseren kan kun defineres på tabelniveau uden mulighed for at definere den på visninger. INSTEAD OF-udløseren bruges til at tilsidesætte sætningen for den handling, der udløser triggeren, med den sætning, der er angivet i triggeren, ved at rulle denne erklæring tilbage efter at have rejst en fejl, når nogen forsøger at udføre en handling, der bryder en bestemt politik, såsom opdatering en kritisk finansiel kolonne eller at skrive ændringen ind i en revisionstabel, før ændringen udføres. I STEDET FOR-triggeren giver dig mulighed for at INDSÆTTE, OPDATERE eller SLETTE data fra de visninger, der refererer til data fra flere tabeller, foruden muligheden for at afvise en del af en batch-forespørgsel og udføre en anden del af den batch med succes. INSTEAD OF-udløseren kan ikke bruges med de opdaterbare visninger, der har WITH CHECK OPTION og i tabellerne med en referencerelation, der specificerer kaskadehandlinger på DELETE eller UPDATE.

Efter at have diskuteret triggerne teoretisk, vil vi begynde at vise, hvad vi diskuterer praktisk. I de kommende demoer vil vi vise de forskellige situationer, hvor vi kan drage fordele af SQL Server-triggerne.

EFTER... DML Trigger

Antag, at vi skal spore de DML-handlinger, der udføres på en specifik tabel, og skrive disse logs i en historiktabel, hvor ID'et for den indsatte, opdaterede eller slettede post og den handling, der udføres, vil blive skrevet til historiktabellen. CREATE TABLE T-SQL-sætningerne nedenfor kan bruges til at oprette både kilde- og historietabellerne:

CREATE TABLE TriggerDemo_Parent
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO

CREATE TABLE TriggerDemo_History
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ParentID INT,
   PerformedAction VARCHAR (50),
  )
GO

For at spore INSERT-operationen vil vi oprette en DML-trigger, der udløses efter at have udført en INSERT-handling på den overordnede tabel. Denne trigger vil hente den sidst indsatte ID-værdi til den overordnede tabel fra den virtuelle indsatte tabel, som i CREATE TRIGGER T-SQL-sætningen nedenfor:

CREATE TRIGGER AfterInsertTrigger
ON TriggerDemo_Parent
AFTER INSERT
AS
INSERT INTO TriggerDemo_History VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Insert')
GO

Sporing af DELETE-handlingen kan opnås ved at oprette en DML-trigger, der udløses efter at have udført DELETE-handlingen på den overordnede tabel. Igen vil triggeren hente ID-værdien af ​​den sidst slettede post fra den overordnede tabel fra den virtuelle slettede tabel, som i CREATE TRIGGER T-SQL-sætningen nedenfor:

CREATE TRIGGER AfterDeleteTrigger
ON TriggerDemo_Parent
AFTER DELETE
AS
INSERT INTO TriggerDemo_History VALUES ((SELECT TOP 1  deleted.ID FROM deleted), 'Delete')
GO

Til sidst vil vi også spore UPDATE-operationen ved at oprette en DML-trigger, der udløses efter at have udført en UPDATE-handling på den overordnede tabel. Inden for denne trigger vil vi hente den sidst opdaterede ID-værdi fra den overordnede tabel fra den virtuelle indsatte tabel, idet vi tager i betragtning, at UPDATE-processen udføres ved at slette posten og indsætte en ny post med de opdaterede værdier, som i CREATE TRIGGER T-SQL-sætning nedenfor:

CREATE TRIGGER AfterUPDATETrigger
ON TriggerDemo_Parent
AFTER UPDATE
AS
INSERT INTO TriggerDemo_History VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'UPDATE')
GO

Tabellerne og triggerne er nu klar til vores test. Hvis du forsøger at indsætte en ny post i den overordnede tabel ved hjælp af INSERT INTO T-SQL-sætningen nedenfor:

INSERT INTO TriggerDemo_Parent VALUES ('AAA','BBB',500)

Så ved at kontrollere den eksekveringsplan, der er genereret ved at udføre den forrige INSERT-sætning, vil du se, at to indsættelsesoperationer vil blive udført, hvilket påvirker to tabeller; den overordnede tabel med værdierne specificeret i INSERT-sætningen og historietabellen på grund af udløsning af AFTER INSERT-triggeren, som vist i udførelsesplanen nedenfor:

Det er også tydeligt, når du kontrollerer de data, der er indsat i både overordnede og historietabeller ved hjælp af SELECT-sætningerne nedenfor:

SELECT * FROM TriggerDemo_Parent
GO
SELECT * FROM TriggerDemo_History

Hvor værdierne angivet i INSERT-sætningen vil blive indsat i den overordnede tabel, og indsættelsesloggen, der indeholder ID'et for den indsatte post og den udførte operation, vil blive indsat i historietabellen, som vist i resultatet nedenfor:

Hvis du nu prøver at opdatere en eksisterende post i den overordnede tabel ved hjælp af UPDATE T-SQL-sætningen nedenfor:

UPDATE TriggerDemo_Parent SET Emp_Salary=550 WHERE ID=1

Og tjek den eksekveringsplan, der er genereret ved at udføre den forrige UPDATE-sætning. Du vil se, at opdateringsoperationen vil blive efterfulgt af en indsættelsesoperation, der påvirker to forskellige tabeller; den overordnede tabel vil blive opdateret med værdien angivet i UPDATE-sætningen og indsættelsesoperationen i historiktabellen på grund af udløsning af AFTER UPDATE-triggeren, som vist i udførelsesplanen nedenfor:

Kontrollerer både de overordnede og historiktabelposterne ved hjælp af SELECT-sætningerne nedenfor:

SELECT * FROM TriggerDemo_Parent
GO
SELECT * FROM TriggerDemo_History

Du vil se, at opdateringssætningen vil ændre Emp_Salary-værdien i den overordnede tabel med den værdi, der er angivet i UPDATE-sætningen, og opdateringsloggen, der indeholder ID'et for den opdaterede post og den udførte handling, vil blive indsat i historiktabellen, som vist i resultatet nedenfor:

I det sidste scenarie med AFTER DML-udløseren sporer vi sletningen af ​​en eksisterende post fra den overordnede tabel ved hjælp af DELETE T-SQL-sætningen nedenfor:

DELETE FROM  TriggerDemo_Parent WHERE ID=1

Kontroller derefter den eksekveringsplan, der er genereret ved at udføre den forrige DELETE-sætning, du vil se, at DELETE-operationen vil blive efterfulgt af indsættelsesoperationen, der påvirker to forskellige tabeller; den overordnede tabel, hvorfra posten med det angivne ID i WHERE-sætningen i DELETE-sætningen vil blive slettet, og indsættelsesoperationen i historietabellen på grund af udløsning af AFTER DELETE-udløseren, som vist i udførelsesplanen nedenfor:

Hvis du tjekker både den overordnede og historiktabelposterne ved hjælp af SELECT-sætningerne nedenfor:

SELECT * FROM TriggerDemo_Parent
GO
SELECT * FROM TriggerDemo_History

Du vil se, at posten med ID-værdien lig med 1 blev slettet fra den overordnede tabel, der er angivet i DELETE-sætningen, og sletteloggen, der indeholder ID'et for den slettede post og den udførte handling, vil blive indsat i historietabellen , som vist i resultatet nedenfor:

I STEDET FOR... DML Trigger

Den anden type DML-triggere er I STEDET FOR DML-triggeren. Som tidligere nævnt vil INSTEAD OF-triggeren tilsidesætte erklæringen om den handling, der udløser triggeren, med erklæringen, der er angivet i triggeren. Antag, at vi skal logge de DML-handlinger, som brugere forsøger at udføre på en specifik tabel, uden at tillade dem at udføre denne handling. CREATE TABLE T-SQL-sætningerne nedenfor kan bruges til at oprette både kildetabellerne og alternative tabeller:

CREATE TABLE TriggerDemo_NewParent
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO


CREATE TABLE TriggerDemo_InsteadParent
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ParentID INT,
   PerformedAction VARCHAR (50),
  )
GO

Efter at have oprettet de to tabeller, vil vi indsætte en enkelt post i kildetabellen til vores demo ved hjælp af INSERT INTO-sætningen nedenfor:

INSERT INTO TriggerDemo_NewParent VALUES ('AA','BB', 500)

Til denne demo vil vi oprette tre triggere for at tilsidesætte INSERT, UPDATE og DELETE operationerne. Den første trigger vil blive brugt til at forhindre enhver indsættelseshandling på den overordnede tabel og loggen, der ændres til den alternative tabel. Triggeren oprettes ved hjælp af CREATE TRIGGER T-SQL-sætningen nedenfor:

CREATE TRIGGER InsteadOfInsertTrigger
ON TriggerDemo_NewParent
INSTEAD OF INSERT
AS
INSERT INTO TriggerDemo_InsteadParent VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Trying to Insert new ID')
GO

Den anden trigger bruges til at forhindre enhver opdateringshandling på den overordnede tabel og loggen, der ændres til den alternative tabel. Denne trigger oprettes som nedenfor:

CREATE TRIGGER InsteadOfUpdateTrigger
ON TriggerDemo_NewParent
INSTEAD OF UPDATE
AS
INSERT INTO TriggerDemo_InsteadParent VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Trying to Update an existing ID')
GO

Den sidste trigger vil blive brugt til at forhindre enhver sletningsoperation på den overordnede tabel og loggen, der ændres til den alternative tabel. Denne trigger oprettes som følger:

CREATE TRIGGER InsteadOfDeleteTrigger
ON TriggerDemo_NewParent
INSTEAD OF DELETE
AS
INSERT INTO TriggerDemo_InsteadParent VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Trying to Delete an existing ID')
GO

De to borde og de tre triggere er klar nu. Hvis du forsøger at indsætte en ny værdi i den overordnede tabel ved hjælp af INSERT INTO T-SQL-sætningen nedenfor:

INSERT INTO TriggerDemo_NewParent VALUES ('CCC','DDD',500)

Kontroller derefter både de overordnede og de alternative tabelposter ved hjælp af SELECT-sætningerne nedenfor:

SELECT * FROM TriggerDemo_NewParent
GO
SELECT * FROM TriggerDemo_InsteadParent

På grund af det faktum, at vi har INSTEAD OF INSERT-triggeren i den overordnede tabel, vil du se på resultatet, at der ikke indsættes en ny post i den overordnede tabel, og en log for indsættelsesoperationen indsættes i den alternative tabel, som vist. i resultatet nedenfor:

Forsøger at opdatere en eksisterende post i den overordnede tabel ved hjælp af UPDATE T-SQL-sætningen nedenfor:

UPDATE TriggerDemo_NewParent SET Emp_Salary=550 WHERE ID=1

Kontroller derefter både de overordnede og de alternative tabelposter ved hjælp af SELECT-sætningerne nedenfor:

SELECT * FROM TriggerDemo_NewParent
GO
SELECT * FROM TriggerDemo_InsteadParent

Du vil se fra resultatet, at Emp_Salary-værdien for posten med ID-værdien lig med 1 fra den overordnede tabel ikke vil blive ændret, og loggen for opdateringsoperationen indsættes i den alternative tabel på grund af at have triggeren INSTEAD OF UPDATE i den overordnede tabel, som vist i resultatet nedenfor:

Endelig, hvis vi forsøger at slette en eksisterende post fra den overordnede tabel ved hjælp af DELETE T-SQL-sætningen nedenfor:

DELETE FROM  TriggerDemo_NewParent  WHERE ID=1

Og kontroller både de overordnede og de alternative tabelposter ved hjælp af SELECT-sætningerne nedenfor:

SELECT * FROM TriggerDemo_NewParent
GO
SELECT * FROM TriggerDemo_InsteadParent

Det vil fremgå af resultatet, at posten med ID-værdien lig med 1 fra den overordnede tabel ikke vil blive slettet, og loggen for sletningsoperationen indsættes i den alternative tabel på grund af at have ISTEAD FOR DELETE trigger i den overordnede tabel, som vist i resultatet nedenfor:

EFTER... DML-udløser med beskeder

AFTER-udløseren kan også bruges til at sende en advarselsmeddelelse til en bruger. I dette tilfælde vil forespørgslen være en informationsmeddelelse, der ikke forhindrer udførelse af den sætning, der udløser den udløser. Lad os droppe den tidligere oprettede INSTEAD OF UPDATE-trigger og erstatte den med en anden EFTER UPDATE-trigger, der vil give en advarselsfejl efter at have udført enhver opdateringshandling ved hjælp af DROP/CREATE TRIGGER T-SQL-sætningerne nedenfor:

DROP TRIGGER InsteadOfUpdateTrigger
CREATE TRIGGER ReminderTrigger  
ON TriggerDemo_NewParent  
AFTER  UPDATE   
AS RAISERROR ('An Update is performed on the TriggerDemo_NewParent table', 16, 10);  
GO  

Hvis du forsøger at opdatere Emp_Salary-værdien for medarbejderen med ID-værdien lig med 1 ved hjælp af UDPATE-sætningen nedenfor:

UPDATE TriggerDemo_NewParent SET Emp_Salary=550 WHERE ID=1

Der vises en fejlmeddelelse i Beskeder fanen, der indeholder meddelelsen i den oprettede trigger, som vist nedenfor:

Kontrol af de overordnede tabeldata ved hjælp af SELECT-sætningen nedenfor:

SELECT * FROM TriggerDemo_NewParent

Du vil se fra resultatet, at Emp_Salary er opdateret med succes, som vist nedenfor:

Hvis du har brug for AFTER UPDATE-udløseren for at stoppe opdateringshandlingen efter at have vist fejlmeddelelsen, vises ROLLBACK sætning kan føjes til triggeren for at rulle tilbage opdateringsoperationen, der udløste triggeren, idet man husker, at triggeren og den sætning, der udløser triggeren, vil blive udført i den samme transaktion. Dette kan opnås ved hjælp af ALTER TRIGGER T-SQL-sætningen, se:

ALTER TRIGGER ReminderTrigger  
ON TriggerDemo_NewParent  
AFTER  UPDATE   
AS RAISERROR ('An Update is performed on the TriggerDemo_NewParent table', 16, 10);  
ROLLBACK
GO  

Hvis du forsøger at opdatere medarbejderens Emp_Salary-værdi med ID, der er lig med 1 ved hjælp af UPDATE-erklæringen nedenfor:

UPDATE TriggerDemo_NewParent SET Emp_Salary=700 WHERE ID=1

Igen vil der blive vist en fejlmeddelelse i Beskeder fanen, men denne gang vil opdateringshandlingen blive rullet helt tilbage, som vist i fejlmeddelelserne nedenfor:

Kontrol af værdien fra kildetabellen ved hjælp af SELECT-sætningen nedenfor:

SELECT * FROM TriggerDemo_NewParent

Du vil se, at Emp_Salary-værdien ikke er ændret, da AFTER UPDATE-udløseren rullede den samlede transaktion tilbage efter at have rejst fejlmeddelelsen, som vist i tabelresultatet nedenfor:

Udløser ulemper

Med alle de nævnte fordele ved SQL Server-triggerne øger triggerne kompleksiteten af ​​databasen. Hvis triggeren er dårligt designet eller overbrugt, vil det føre til store præstationsproblemer, såsom blokerede sessioner, på grund af forlængelse af transaktionens levetid i længere tid, ekstra overhead på systemet på grund af at udføre den hver gang en INSERT, UPDATE eller SLET-handlingen udføres, eller det kan føre til problemer med datatab. Det er heller ikke nemt at se og spore databasetriggerne, især hvis der ikke er dokumentation om det, da det er usynligt for udviklere og applikationerne.

Trigger Alternativer … Håndhæv integritet

Hvis det viser sig, at triggerne skader ydeevnen af ​​din SQL Server-instans, skal du erstatte dem med andre løsninger. For eksempel, i stedet for at bruge triggerne til at håndhæve entitetsintegriteten, bør den håndhæves på det laveste niveau ved at bruge PRIMARY KEY og UNIQUE begrænsninger. Det samme gælder for domæneintegriteten, der skal håndhæves gennem CHECK-begrænsninger, og den referentielle integritet, der skal håndhæves gennem FOREIGN KEY-begrænsningerne. Du kan kun bruge DML-udløsere, hvis de funktioner, der understøttes af en specifik begrænsning, ikke kan opfylde dine applikationskrav.

Lad os sammenligne mellem håndhævelse af domæneintegriteten ved hjælp af DML-udløsere og brug af CHECK-begrænsningerne. Antag, at vi kun skal gennemtvinge indsættelse af positive værdier i kolonnen Emp_Salary. Vi starter med at lave en simpel tabel ved hjælp af CREATE TABLE T-SQL-sætningen nedenfor:

CREATE TABLE EmployeeSalaryTrigger
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO

Definer derefter AFTER INSERT DML-udløseren, der sikrer, at du indsætter en positiv værdi i kolonnen Emp_Salary ved at rulle transaktionen tilbage, hvis en bruger indsætter en negativ lønværdi, ved hjælp af CREATE TRIGGER T-SQL-sætningen nedenfor:

CREATE TRIGGER TRGR_EmployeeSalary ON EmployeeSalaryTrigger 
AFTER INSERT 
AS
DECLARE @EmpSal AS INT
SET @EmpSal = (SELECT TOP 1 inserted.Emp_Salary FROM inserted)
IF @EmpSal<0
BEGIN 
 RAISERROR  ('Cannot insert negative salary',16,10);
  ROLLBACK
END

Til sammenligningsformål vil vi oprette en anden simpel tabel med det samme skema og definere en CHECK-begrænsning i CREATE TABLE-sætningen til kun at acceptere positive værdier i Emp_Salary-kolonnen, som vist nedenfor:

CREATE TABLE EmployeeSalaryConstraint
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT CONSTRAINT EmpSal CHECK (Emp_Salary >=0)
  )
GO

Hvis du forsøger at indsætte nedenstående post, der indeholder negativ Emp_Salary-værdi, i den første tabel, der har en foruddefineret trigger, ved hjælp af INSERT INTO-sætningen nedenfor:

INSERT INTO EmployeeSalaryTrigger VALUES('Ali', 'Fadi',-4)
GO

INSERT-sætningen vil ikke vise en fejlmeddelelse, der viser, at du ikke kan indsætte en negativ værdi i Emp_Salary-kolonnen og rulle den samlede transaktion tilbage på grund af at have en AFTER INSERT-udløser, som vist i fejlmeddelelsen nedenfor:

Også, hvis du forsøger at indsætte den samme post, der indeholder en negativ Emp_Salary-værdi, i den anden tabel, der har en foruddefineret CHECK-begrænsning ved hjælp af INSERT INTO-sætningen nedenfor:

INSERT INTO EmployeeSalaryConstraint VALUES ('Ali', 'Fadi',-4)

INSERT-sætningen mislykkes igen, hvilket viser, at du forsøger at indsætte den værdi, der er i konflikt med CHECK-betingelsen, som vist i fejlmeddelelsen nedenfor:

Fra de tidligere resultater kan du se, at både trigger- og CHECK-begrænsningsmetoderne opnår målet ved at forhindre dig i at indsætte negative Emp_Salary-værdier. Men hvilken er bedre? Lad os sammenligne ydeevnen af ​​de to metoder ved at kontrollere udførelsesplanens vægt for hver enkelt. Fra de genererede eksekveringsplaner efter eksekvering af de to forespørgsler, vil du se, at triggermetodens vægt er tre gange CHECK-begrænsningsmetodens vægt, som vist i udførelsesplanens sammenligning nedenfor:

For at sammenligne den eksekveringstid, der forbruges af hver enkelt, lad os køre hver enkelt 1000 gange ved hjælp af T-SQL-sætningerne nedenfor:

INSERT INTO EmployeeSalaryTrigger VALUES('Ali', 'Fadi',-4)
GO 10000  
INSERT INTO EmployeeSalaryConstraint VALUES ('Ali', 'Fadi',-4)
GO 10000 

Du vil se, at den første metode, der bruger triggeren, vil tage omkring 31ms skal udføres fuldstændigt, hvor den anden metode, der bruger CHECK-begrænsningen, kun tager 17ms , hvilket er omkring 0,5 tiden påkrævet i metoden, der bruger triggeren. Dette skyldes, at triggeren forlænger transaktionens levetid og vil rulle tilbage forespørgslen, der udløser triggeren efter at have udført den, når der er fundet en integritetskrænkelse, hvilket forårsager en ydeevneforringelse på grund af rollback-processen. Sagen er anderledes, når du bruger CHECK-begrænsningen, hvor begrænsningen vil gøre sit arbejde, før der foretages ændringer i dataene, hvilket ikke kræver nogen rollback i tilfælde af overtrædelse.

Trigger-alternativer … Revision

Som vi nævnte tidligere, kan triggerne også bruges til at revidere og spore ændringerne udført på en specifik tabel. Hvis denne revisionsmetode forårsager en ydeevneforringelse i din SQL Server-instans, kan du nemt erstatte den med OUTPUT klausul. OUTPUT-sætningen returnerer information om hver række, der er påvirket af INSERT-, UPDATE- eller DELETE-operationen, i form af en bekræftelsesmeddelelse eller en værdi, der kan indsættes i den historiske tabel. OUTPUT-klausulmetoden giver os også mere kontrol over den udførte kode, da den vil blive tilføjet til selve dataindsættelses-, ændrings- eller sletningssætningen, når du vil, modsat triggeren, der altid vil blive udført.

Lad os sammenligne mellem at logge dataindsættelsen og ændringen i historietabellen ved hjælp af DML-udløsere og brug af OUTPUT-klausulen. Vi starter med at oprette nedenstående produktions- og historietabeller ved hjælp af CREATE TABLE T-SQL-sætningen nedenfor:

CREATE TABLE TriggerDemo_Prod
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO


CREATE TABLE TriggerDemo_ProdHistory
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ProdID INT,
   ProdSalary INT,
   TS DATETIME,
  )
GO

Når begge tabeller er oprettet med succes, vil vi oprette AFTER INSERT, UPDATE DML-triggeren, der vil skrive en post i historietabellen, hvis en ny række indsættes i produktionstabellen, eller en eksisterende post ændres ved hjælp af CREATE TRIGGER T-SQL-sætningen nedenfor:

CREATE TRIGGER ProdHistory
ON TriggerDemo_Prod
AFTER INSERT, UPDATE
AS
INSERT INTO TriggerDemo_ProdHistory  VALUES ( (SELECT TOP 1  inserted.ID FROM inserted),(SELECT TOP 1  inserted.Emp_Salary FROM inserted), GETDATE())
GO
GET()

For at sammenligne logning af ændringerne ved hjælp af triggermetoden og OUTPUT-klausulen, skal vi oprette to nye simple tabeller, produktions- og historietabellerne, med samme skema som de to foregående tabeller, men denne gang uden at definere en trigger, ved hjælp af OPRET TABLE T-SQL-sætninger nedenfor:

CREATE TABLE OutputDemo_Prod
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO


CREATE TABLE OutputDemo_ProdHistory
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ProdID INT,
   ProdSalary INT,
   TS DATETIME,
  )
  
GO

Nu er de fire borde klar til test. Vi indsætter én post i den første produktionstabel, der har en trigger ved hjælp af INSERT INTO T-SQL-sætningen nedenfor:

INSERT INTO TriggerDemo_Prod values('AA','BB', 750)
GO 

Derefter vil vi indsætte den samme post i den anden produktionstabel ved hjælp af OUTPUT-sætningen. Nedenstående INSERT INTO-sætning vil fungere som to indsæt-sætninger; den første vil indsætte den samme post i produktionstabellen, og den anden insert-sætning ved siden af ​​OUTPUT-sætningen vil indsætte indsættelsesloggen i historietabellen:

INSERT INTO OutputDemo_Prod  OUTPUT inserted.ID, inserted.Emp_Salary, GETDATE() 
INTO OutputDemo_ProdHistory	values('AA','BB', 750)
GO 

Ved at kontrollere de data, der er indsat i de fire produktions- og historiktabeller, vil du se, at begge metoder, trigger- og OUTPUT-metoderne, vil skrive den samme log ind i historiktabellen med succes og på samme måde, som vist i resultatet nedenfor:

Fra de genererede eksekveringsplaner efter eksekvering af de to forespørgsler, vil du se, at triggermetodens vægt er ca. (21%+36%) 57% af den samlede vægt, hvor OUTPUT-metodens vægt er omkring 43 % , med en lille vægtforskel, som vist i sammenligningen af ​​udførelsesplaner nedenfor:

Ydeevneforskellen er tydelig, når man sammenligner den eksekveringstid, der forbruges af hver metode, hvor logning af ændringerne ved hjælp af triggermetoden vil forbruge (114+125) 239ms skal udføres fuldstændigt, og metoden, der bruger OUTPUT-sætningsmetoden, bruger kun 5ms , hvilket er 2 % af tiden brugt i triggermetoden, som det tydeligt fremgår af tidsstatistikken nedenfor:

Det er tydeligt nu fra det tidligere resultat, at det er bedre at bruge OUTPUT-metoden end at bruge triggere til revision af ændringer.

Nyttige links:

  • OPRET TRIGGER (Transact-SQL) https://docs.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
  • DML-udløsere https://docs.microsoft.com/en-us/sql/relational-databases/triggers/dml-triggers
  • DDL-udløsere https://docs.microsoft.com/en-us/sql/relational-databases/triggers/ddl-triggers
  • OUTPUT-klausul (Transact-SQL) https://docs.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql

  1. Søgning efter tekst i Oracle Stored Procedures

  2. Forståelse af SQL Server Always Encrypted

  3. Vedhæftede filer i Oracle Applications R12

  4. Multiple indsæt SQL oracle