sql >> Databasteknik >  >> RDS >> Sqlserver

SQL Server Trigger:Förståelse och alternativ

SQL Server-utlösaren är en speciell typ av lagrade procedurer som exekveras automatiskt när en händelse inträffar i en specifik databasserver. SQL Server förser oss med två huvudtyper av triggers:DML Utlösare och DDL utlösare. DDL-triggarna kommer att aktiveras som svar på olika Data Definition Language-händelser (DDL), som exekvering av CREATE, ALTER, DROP, GRANT, DENY och REVOKE T-SQL-satser. DDL-utlösaren kan svara på DDL-åtgärderna genom att förhindra dessa ändringar från att påverka databasen, utföra en annan åtgärd som svar på dessa DDL-åtgärder eller registrera dessa ändringar som exekveras mot databasen.

SQL Server DML Trigger är en speciell typ av lagrade procedurer som är utformade för att utföra en sekvens av åtgärder på en databastabell, till vilken utlösaren är kopplad, när en Data Manipulation Language (DML) händelser, såsom INSERT, UPDATE eller DELETE åtgärd, inträffar för att ändra innehållet i databastabellerna eller vyerna, oavsett om tabellraderna påverkas eller inte. Triggarna skiljer sig från de lagrade procedurerna genom att triggarna utlöses automatiskt när en fördefinierad datamodifiering inträffar. DML-triggarna kan användas för att upprätthålla dataintegritet och genomdriva företagets affärsregler, på samma sätt som funktionalitet för tabellkontroll och främmande nycklar, genom att utföra granskningsprocesser och andra efter DML-åtgärder. Du kan använda DML-utlösare för att fråga andra tabeller och utföra komplexa T-SQL-frågor.

Om utlösaren aktiveras, en speciell typ av virtuella tabeller som kallas Infogad och Raderad tabeller kommer att användas för att behålla datavärdena före och efter ändringen. Utlösningssatsen kommer att fungera inom ramen för samma transaktion som utlöser den. Detta innebär att transaktionen inte kommer att genomföras helt förrän triggersatsen har slutförts framgångsrikt. Å andra sidan kommer transaktionen att återställas om triggersatsen misslyckas.

Det finns två typer av DML-utlösare:EFTER eller FÖR trigger och I STÄLLET FÖR utlösare. AFTER-utlösaren aktiveras och exekveras efter att ha utfört åtgärden INFOGA, UPPDATERA eller DELETE som aktiverar den framgångsrikt. Alla refererande kaskadåtgärder och begränsningskontroller bör också lyckas innan avtryckaren aktiveras. AFTER-utlösaren kan endast definieras på tabellnivå utan möjlighet att definiera den på vyer. Utlösaren INSTEAD OF används för att åsidosätta uttalandet för åtgärden som aktiverar utlösaren med det uttalande som tillhandahålls i utlösaren, för att rulla tillbaka det uttalandet efter att ha skapat ett fel när någon försöker utföra en åtgärd som bryter mot en specifik policy, till exempel uppdatering en kritisk finansiell kolumn eller att skriva ändringen i en revisionstabell innan ändringen utförs. Utlösaren INSTEAD OF låter dig INFOGA, UPPDATERA eller DELETE data från vyerna som refererar till data från flera tabeller, förutom möjligheten att avvisa en del av en batchfråga och köra en annan del av den batchen framgångsrikt. Utlösaren INSTEAD OF kan inte användas med de uppdateringsbara vyerna som har WITH CHECK OPTION och i tabellerna med en referensrelation som anger kaskadåtgärder vid DELETE eller UPDATE.

Efter att ha diskuterat triggers teoretiskt kommer vi att börja visa vad vi diskuterar praktiskt. I de kommande demos kommer vi att visa de olika situationer där vi kan dra nytta av SQL Server-triggarna.

EFTER... DML-utlösare

Antag att vi behöver spåra de DML-åtgärder som utförs på en specifik tabell och skriva dessa loggar i en historiktabell, där ID för den infogade, uppdaterade eller raderade posten och den åtgärd som utförs kommer att skrivas till historiktabellen. CREATE TABLE T-SQL-satserna nedan kan användas för att skapa både käll- och historiktabellerna:

CREATE TABLE TriggerDemo_Parent( ID INT IDENTITY (1,1) PRIMARY KEY, Emp_First_name VARCHAR (50), Emp_Last_name VARCHAR (50), Emp_Salary INT )GOCREATE TABLE TriggerDemo_History( ID INT 1 IDENTITY (1,KEY) IDENTITY (1 , UtfördAction VARCHAR (50), )GO

För att spåra INSERT-operationen kommer vi att skapa en DML-utlösare som kommer att aktiveras efter att ha utfört en INSERT-operation på den överordnade tabellen. Denna utlösare kommer att hämta det senast infogade ID-värdet till den överordnade tabellen från den virtuella infogade tabellen, som i CREATE TRIGGER T-SQL-satsen nedan:

SKAPA TRIGGER AfterInsertTriggerON TriggerDemo_ParentAFTER INSERTASINSERT INTO TriggerDemo_History VALUES ((VÄLJ TOP 1 insert.ID FROM inserted), 'Insert')GO

Spårning av DELETE-operationen kan uppnås genom att skapa en DML-utlösare som aktiveras efter att ha utfört DELETE-operationen på den överordnade tabellen. Återigen kommer utlösaren att hämta ID-värdet för den senast raderade posten från den överordnade tabellen från den virtuella borttagna tabellen, som i CREATE TRIGGER T-SQL-satsen nedan:

SKAPA TRIGGER AfterDeleteTriggerON TriggerDemo_ParentAFTER DELETEASINSERT I TriggerDemo_History VALUES ((VÄLJ TOP 1 deleted.ID FROM deleted), 'Delete')GO

Slutligen kommer vi också att spåra UPDATE-operationen genom att skapa en DML-utlösare som kommer att aktiveras efter att ha utfört en UPDATE-operation på den överordnade tabellen. Inom denna utlösare kommer vi att hämta det senast uppdaterade ID-värdet från den överordnade tabellen från den virtuellt infogade tabellen, med hänsyn till att UPDATE-processen utförs genom att radera posten och infoga en ny post med de uppdaterade värdena, som i CREATE TRIGGER T-SQL-sats nedan:

SKAPA TRIGGER EfterUPDATETriggerON TriggerDemo_ParentAFTER UPDATEASINSERT I TriggerDemo_History VALUES ((VÄLJ TOP 1 insatt.ID FRÅN infogat), 'UPPDATERA')GO

Tabellerna och triggarna är klara nu för vår testning. Om du försöker infoga en ny post i den överordnade tabellen med hjälp av INSERT INTO T-SQL-satsen nedan:

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

Genom att sedan kontrollera exekveringsplanen som genererades genom att exekvera föregående INSERT-sats, kommer du att se att två infogningsoperationer kommer att utföras, vilket påverkar två tabeller; den överordnade tabellen med de värden som anges i INSERT-satsen och historiktabellen på grund av att AFTER INSERT-utlösaren aktiveras, som visas i exekveringsplanen nedan:

Det är också tydligt när du kontrollerar data som infogats i både överordnade och historiktabeller med hjälp av SELECT-satserna nedan:

VÄLJ * FRÅN TriggerDemo_ParentGOSELECT * FRÅN TriggerDemo_History

Där värdena som anges i INSERT-satsen kommer att infogas i den överordnade tabellen, och infogningsloggen som innehåller ID:t för den infogade posten och den utförda operationen kommer att infogas i historiktabellen, som visas i resultatet nedan:

Om du nu försöker uppdatera en befintlig post i den överordnade tabellen med hjälp av UPDATE T-SQL-satsen nedan:

UPPDATERA TriggerDemo_Parent SET Emp_Salary=550 WHERE ID=1

Och kontrollera exekveringsplanen som genererades genom att exekvera föregående UPDATE-sats, du kommer att se att uppdateringsoperationen kommer att följas av en infogningsoperation som påverkar två olika tabeller; den överordnade tabellen kommer att uppdateras med det värde som anges i UPDATE-satsen och infogningen i historiktabellen på grund av att AFTER UPDATE-utlösaren aktiveras, som visas i exekveringsplanen nedan:

Kontrollera både överordnade och historiktabellposterna med hjälp av SELECT-satserna nedan:

VÄLJ * FRÅN TriggerDemo_ParentGOSELECT * FRÅN TriggerDemo_History

Du kommer att se att uppdateringssatsen kommer att modifiera Emp_Salary-värdet i den överordnade tabellen med värdet som anges i UPDATE-satsen, och uppdateringsloggen som innehåller ID för den uppdaterade posten och den utförda operationen kommer att infogas i historiktabellen, som visas i resultatet nedan:

I det sista scenariot av AFTER DML-utlösaren kommer vi att spåra raderingen av en befintlig post från den överordnade tabellen med hjälp av DELETE T-SQL-satsen nedan:

RADERA FRÅN TriggerDemo_Parent WHERE ID=1

Kontrollera sedan exekveringsplanen som genererades genom att exekvera föregående DELETE-sats, du kommer att se att DELETE-operationen kommer att följas av insert-operationen, som påverkar två olika tabeller; den överordnade tabellen från vilken posten med det angivna ID:t i WHERE-satsen i DELETE-satsen kommer att raderas och infogningen i historiktabellen på grund av att AFTER DELETE-utlösaren aktiveras, som visas i exekveringsplanen nedan:

Om du kontrollerar både överordnade och historiktabellposterna med hjälp av SELECT-satserna nedan:

VÄLJ * FRÅN TriggerDemo_ParentGOSELECT * FRÅN TriggerDemo_History

Du kommer att se att posten med ID-värdet lika med 1 raderades från den överordnade tabellen som finns i DELETE-satsen, och deleteloggen som innehåller ID:t för den raderade posten och den utförda operationen kommer att infogas i historiktabellen , som visas i resultatet nedan:

I STÄLLET FÖR... DML-utlösare

Den andra typen av DML-utlösare är Istället för DML-utlösare. Som nämnts tidigare kommer INSTEAD OF-utlösaren att åsidosätta uttalandet av åtgärden som aktiverar utlösaren med uttalandet som tillhandahålls i utlösaren. Antag att vi behöver logga DML-åtgärderna som användare försöker utföra på en specifik tabell, utan att tillåta dem att utföra den åtgärden. CREATE TABLE T-SQL-satserna nedan kan användas för att skapa både källtabellen och alternativa 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 )GOCREATE TABLE TriggerDemo_InsteadParent( ID INT INT ID, PRItMA INT) , UtfördAction VARCHAR (50), )GO

Efter att ha skapat de två tabellerna kommer vi att infoga en enda post i källtabellen för vår demo med hjälp av INSERT INTO-satsen nedan:

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

För denna demo kommer vi att skapa tre utlösare för att åsidosätta operationerna INSERT, UPDATE och DELETE. Den första utlösaren kommer att användas för att förhindra eventuella infogningsoperationer på den överordnade tabellen och loggen som ändras till den alternativa tabellen. Utlösaren skapas med CREATE TRIGGER T-SQL-satsen nedan:

SKAPA TRIGGER InsteadOfInsertTriggerON TriggerDemo_NewParentI STÄLLET FÖR INSERTASINSERT INTO TriggerDemo_InsteadParent VALUES ((VÄLJ TOPP 1 insatt.ID FRÅN infogat), 'Försöker infoga nytt ID')GO

Den andra utlösaren används för att förhindra uppdateringar på den överordnade tabellen och loggen som ändras till den alternativa tabellen. Denna utlösare skapas enligt nedan:

SKAPA TRIGGER InsteadOfUpdateTriggerON TriggerDemo_NewParentI STÄLLET FÖR UPDATEASINSERT INTO TriggerDemo_InsteadParent VALUES ((VÄLJ TOP 1 insatt.ID FRÅN infogat), 'Försöker uppdatera ett befintligt ID')GO

Den sista utlösaren kommer att användas för att förhindra borttagning av den överordnade tabellen och loggen som ändras till den alternativa tabellen. Denna utlösare skapas enligt följande:

SKAPA TRIGGER InsteadOfDeleteTriggerON TriggerDemo_NewParentI STÄLLET FÖR DELETEASINSERT INTO TriggerDemo_InsteadParent VALUES ((VÄLJ TOP 1 insatt.ID FRÅN infogat), 'Försöker ta bort ett befintligt ID')GO

De två borden och de tre triggarna är klara nu. Om du försöker infoga ett nytt värde i den överordnade tabellen med hjälp av INSERT INTO T-SQL-satsen nedan:

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

Kontrollera sedan både den överordnade och de alternativa tabellposterna med hjälp av SELECT-satserna nedan:

VÄLJ * FRÅN TriggerDemo_NewParentGOSELECT * FRÅN TriggerDemo_InsteadParent

På grund av det faktum att vi har utlösaren INSTEAD OF INSERT i den överordnade tabellen, kommer du att se från resultatet att ingen ny post infogas i den överordnade tabellen, och en logg för infogningsoperationen infogas i den alternativa tabellen, som visas i resultatet nedan:

Försöker uppdatera en befintlig post i den överordnade tabellen med hjälp av UPDATE T-SQL-satsen nedan:

UPPDATERA TriggerDemo_NewParent SET Emp_Salary=550 WHERE ID=1

Kontrollera sedan både de överordnade och de alternativa tabellposterna med hjälp av SELECT-satserna nedan:

VÄLJ * FRÅN TriggerDemo_NewParentGOSELECT * FRÅN TriggerDemo_InsteadParent

Du kommer att se från resultatet att Emp_Salary-värdet för posten med ID-värdet lika med 1 från den överordnade tabellen inte kommer att ändras, och loggen för uppdateringsoperationen infogas i den alternativa tabellen på grund av att den har utlösaren INSTEAD OF UPDATE i den överordnade tabellen, som visas i resultatet nedan:

Slutligen, om vi försöker ta bort en befintlig post från den överordnade tabellen med hjälp av DELETE T-SQL-satsen nedan:

RADERA FRÅN TriggerDemo_NewParent WHERE ID=1

Och kontrollera både de överordnade och de alternativa tabellposterna med hjälp av SELECT-satserna nedan:

VÄLJ * FRÅN TriggerDemo_NewParentGOSELECT * FRÅN TriggerDemo_InsteadParent

Det kommer att framgå av resultatet att posten med ID-värdet lika med 1 från den överordnade tabellen inte kommer att raderas, och loggen för borttagningsoperationen infogas i den alternativa tabellen på grund av att INSTEAD OF DELETE-utlösaren finns i den överordnade tabell, som visas i resultatet nedan:

EFTER... DML-utlösare med meddelanden

AFTER-utlösaren kan också användas för att visa ett varningsmeddelande för en användare. I det här fallet kommer frågan att vara ett informationsmeddelande som inte hindrar exekvering av satsen som utlöser den. Låt oss släppa den tidigare skapade INSTEAD OF UPDATE-utlösaren och ersätta den med en annan EFTER UPDATE-utlösare som kommer att ge upp ett varningsfel efter att ha utfört någon uppdateringsoperation med DROP/CREATE TRIGGER T-SQL-satserna nedan:

DROP TRIGGER InsteadOfUpdateTriggerCREATE TRIGGER ReminderTrigger PÅ TriggerDemo_NewParent EFTER UPPDATERING SOM RAISERROR ('En uppdatering utförs på tabellen TriggerDemo_NewParent', 16, 10); GÅ 

Om du försöker uppdatera Emp_Salary-värdet för den anställde med ID-värdet lika med 1 med UDPATE-satsen nedan:

UPPDATERA TriggerDemo_NewParent SET Emp_Salary=550 WHERE ID=1

Ett felmeddelande kommer att visas i Meddelanden fliken, som innehåller meddelandet i den skapade utlösaren, som visas nedan:

Kontrollera de överordnade tabelldata med hjälp av SELECT-satsen nedan:

VÄLJ * FRÅN TriggerDemo_NewParent

Du kommer att se från resultatet att Emp_Salary har uppdaterats framgångsrikt, som visas nedan:

Om du behöver utlösaren EFTER UPPDATERING för att stoppa uppdateringsoperationen efter att du har visat felmeddelandet, visas ROLLBACK uttalande kan läggas till utlösaren för att återställa uppdateringsoperationen som utlöste utlösaren, med påminnelse om att utlösaren och uttalandet som utlöser utlösaren kommer att köras i samma transaktion. Detta kan uppnås med ALTER TRIGGER T-SQL-satsen, se:

ALTER TRIGGER ReminderTrigger PÅ TriggerDemo_NewParent EFTER UPPDATERING SOM RAISERROR ('En uppdatering utförs på TriggerDemo_NewParent-tabellen', 16, 10); ROLLBACKGO 

Om du försöker uppdatera Emp_Salary-värdet för den anställde med ID lika med 1 med hjälp av UPDATE-satsen nedan:

UPPDATERA TriggerDemo_NewParent SET Emp_Salary=700 WHERE ID=1

Återigen kommer ett felmeddelande att visas i Meddelanden fliken, men den här gången kommer uppdateringsåtgärden att återställas helt, som visas i felmeddelandena nedan:

Kontrollera värdet från källtabellen med hjälp av SELECT-satsen nedan:

VÄLJ * FRÅN TriggerDemo_NewParent

Du kommer att se att Emp_Salary-värdet inte har ändrats, eftersom AFTER UPDATE-utlösaren rullade tillbaka den övergripande transaktionen efter att felmeddelandet visades, som visas i tabellresultatet nedan:

Utlösande nackdelar

Med alla de nämnda fördelarna med SQL Server-triggarna ökar triggarna databasens komplexitet. Om triggern är dåligt utformad eller överanvänd, kommer det att leda till stora prestandaproblem, såsom blockerade sessioner, på grund av att transaktionens livslängd förlängs under längre tid, extra overhead på systemet på grund av att den körs varje gång en INFOGA, UPPDATERING eller DELETE-åtgärden utförs eller det kan leda till problem med dataförlust. Dessutom är det inte lätt att se och spåra databasutlösare, särskilt om det inte finns någon dokumentation om det eftersom det är osynligt för utvecklare och applikationer.

Utlösa alternativ ... Framtvinga integritet

Om det visar sig att triggarna skadar prestandan för din SQL Server-instans måste du ersätta dem med andra lösningar. Till exempel, snarare än att använda utlösare för att upprätthålla entitetsintegriteten, bör den upprätthållas på den lägsta nivån genom att använda PRIMARY KEY och UNIQUE begränsningar. Detsamma tillämpas på domänintegriteten som bör upprätthållas genom CHECK-begränsningar, och referensintegriteten som bör upprätthållas genom FOREIGN KEY-begränsningarna. Du kan bara använda DML-utlösare om funktionerna som stöds av en specifik begränsning inte kan uppfylla dina applikationskrav.

Låt oss jämföra mellan att upprätthålla domänintegriteten med DML-utlösare och att använda CHECK-begränsningarna. Antag att vi bara måste tvinga in positiva värden i kolumnen Emp_Salary. Vi börjar med att skapa en enkel tabell med CREATE TABLE T-SQL-satsen nedan:

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

Definiera sedan AFTER INSERT DML-utlösaren som säkerställer att du infogar ett positivt värde i Emp_Salary-kolumnen genom att återställa transaktionen om en användare infogar ett negativt lönevärde, med hjälp av CREATE TRIGGER T-SQL-satsen nedan:

SKAPA TRIGGER TRGR_EmployeeSalary ON EmployeeSalaryTrigger EFTER INSERT ASDECLARE @EmpSal AS INTSET @EmpSal =(VÄLJ TOP 1 insatt.Emp_Salary FROM infogas)IF @EmpSal<0BEGIN negativ RAISERROR,sert1negativ RAISERROR,sert1100,sert1; ROLLBACKEND

För jämförelsesyften kommer vi att skapa en annan enkel tabell, med samma schema, och definiera en CHECK-begränsning i CREATE TABLE-satsen för att endast acceptera positiva värden i Emp_Salary-kolumnen, som visas nedan:

SKAPA TABELL 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

Om du försöker infoga posten nedan som innehåller negativt Emp_Salary-värde i den första tabellen som har en fördefinierad trigger, med hjälp av INSERT INTO-satsen nedan:

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

INSERT-satsen kommer att misslyckas och ger ett felmeddelande som visar att du inte kan infoga ett negativt värde i kolumnen Emp_Salary och återställa den totala transaktionen på grund av att den har en AFTER INSERT-utlösare, som visas i felmeddelandet nedan:

Dessutom, om du försöker infoga samma post som innehåller ett negativt Emp_Salary-värde i den andra tabellen som har en fördefinierad CHECK-begränsning med hjälp av INSERT INTO-satsen nedan:

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

INSERT-satsen kommer att misslyckas igen, vilket visar att du försöker infoga värdet som står i konflikt med CHECK-villkoret, som visas i felmeddelandet nedan:

Från de tidigare resultaten ser du att både trigger- och CHECK-begränsningsmetoderna uppnår målet genom att hindra dig från att sätta in negativa Emp_Salary-värden. Men vilken är bättre? Låt oss jämföra prestandan för de två metoderna genom att kontrollera exekveringsplanens vikt för var och en. Från de genererade exekveringsplanerna efter att ha kört de två frågorna kommer du att se att triggermetodens vikt är tre gånger vikten CHECK-begränsningsmetoden, som visas i jämförelsen av exekveringsplanen nedan:

För att jämföra körtiden som förbrukas av var och en, låt oss köra var och en 1000 gånger med hjälp av T-SQL-satserna nedan:

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

Du kommer att se att den första metoden som använder triggern kommer att ta ungefär 31ms exekveras helt, där den andra metoden som använder CHECK-begränsningen bara tar 17 ms , vilket är ungefär 0,5 tiden krävs i metoden som använder triggern. Detta beror på det faktum att utlösaren förlänger transaktionens livslängd och återställer frågan som aktiverar utlösaren efter att ha körts när en integritetsintrång hittas, vilket orsakar en prestandaförsämring på grund av återställningsprocessen. Fallet är annorlunda när du använder begränsningen CHECK, där begränsningen kommer att göra sitt jobb innan någon modifiering av data görs, vilket inte kräver någon återställning i händelse av överträdelse.

Utlösande alternativ ... revision

Som vi nämnde tidigare kan triggarna också användas för att granska och spåra ändringar som utförs på en specifik tabell. Om denna granskningsmetod orsakar en prestandaförsämring i din SQL Server-instans kan du enkelt ersätta den med OUTPUT klausul. OUTPUT-satsen returnerar information om varje rad som påverkas av operationen INSERT, UPDATE eller DELETE, i form av ett bekräftelsemeddelande eller ett värde som kan infogas i den historiska tabellen. OUTPUT-satsmetoden ger oss också mer kontroll över den exekverade koden, eftersom den kommer att läggas till i själva datainsättnings-, modifierings- eller raderingssatsen när du vill, i motsats till triggern som alltid kommer att exekveras.

Låt oss jämföra mellan att logga in datainsättningen och modifieringen i historiktabellen med DML-utlösare och att använda OUTPUT-satsen. Vi börjar med att skapa produktions- och historiktabellerna nedan med hjälp av CREATE TABLE T-SQL-satsen nedan:

CREATE TABLE TriggerDemo_Prod( ID INT IDENTITY (1,1) PRIMARY KEY, Emp_First_name VARCHAR (50), Emp_Last_name VARCHAR (50), Emp_Salary INT )GOCREATE TABLE TriggerDemo_ProdHistory (ID INT INT IDENTITY, PRIMA , ProdSalary INT, TS DATETIME, )GO

När båda tabellerna har skapats framgångsrikt kommer vi att skapa AFTER INSERT, UPDATE DML-utlösaren som kommer att skriva en post i historiktabellen om någon ny rad infogas i produktionstabellen eller en befintlig post modifieras med CREATE TRIGGER T-SQL-satsen nedan:

SKAPA TRIGGER ProdHistoryON TriggerDemo_ProdAFTER INSERT, UPDATEASINSERT INTO TriggerDemo_ProdHistory VALUES ((VÄLJ TOP 1 insatt.ID FRÅN infogat),(VÄLJ TOP 1 infogat.Emp_Salary FROM infogat) , GET() 

För att jämföra loggning av ändringarna med triggermetoden och OUTPUT-satsen måste vi skapa två nya enkla tabeller, produktions- och historiktabellerna, med samma schema som de två föregående tabellerna, men den här gången utan att definiera en trigger, med hjälp av CREATE TABLE T-SQL-satser nedan:

CREATE TABLE OutputDemo_Prod( ID INT IDENTITY (1,1) PRIMARY KEY, Emp_First_name VARCHAR (50), Emp_Last_name VARCHAR (50), Emp_Salary INT )GOCREATE TABLE OutputDemo_ProdHistory( ID INT IDENT,PRId , ProdSalary INT, TS DATETIME, ) GO

Nu är de fyra borden redo för testning. Vi kommer att infoga en post i den första produktionstabellen som har en trigger med hjälp av INSERT INTO T-SQL-satsen nedan:

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

Sedan kommer vi att infoga samma post i den andra produktionstabellen med hjälp av OUTPUT-satsen. Nedanstående INSERT INTO-sats kommer att fungera som två infogningssatser; den första kommer att infoga samma post i produktionstabellen och den andra infogningssatsen bredvid OUTPUT-satsen kommer att infoga insättningsloggen i historiktabellen:

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

När du kontrollerar data som infogats i de fyra produktions- och historiktabellerna kommer du att se att båda metoderna, trigger- och OUTPUT-metoderna, kommer att skriva samma logg i historiktabellen framgångsrikt och på samma sätt, som visas i resultatet nedan:

Från de genererade exekveringsplanerna efter exekvering av de två frågorna kommer du att se att triggermetodens vikt är ungefär (21%+36%) 57% av den totala vikten, där OUTPUT-metodens vikt är cirka 43 % , med en liten viktskillnad, som visas i jämförelsen av utförandeplanerna nedan:

Prestandaskillnaden är tydlig när man jämför exekveringstiden som förbrukas av varje metod, där loggning av ändringarna med triggermetoden kommer att ta (114+125) 239ms exekveras fullständigt, och metoden som använder OUTPUT-satsmetoden förbrukar endast 5ms , vilket är 2 % av tiden som används i triggermetoden, vilket tydligt framgår av tidsstatistiken nedan:

Det framgår nu av det tidigare resultatet att det är bättre att använda OUTPUT-metoden än att använda triggers för revision av ändringar.

Användbara länkar:

  • SKAPA TRIGGER (Transact-SQL) https://docs.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
  • DML-utlösare https://docs.microsoft.com/en-us/sql/relational-databases/triggers/dml-triggers
  • DDL-utlösare 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. Får endast månad och år från SQL DATE

  2. Ta reda på vilket kvartal en dejt tillhör i Oracle

  3. Ta bort dubbletter från Count()-resultat i SQLite

  4. Hur LTRIM()-funktionen fungerar i MySQL