simple programming part 2 section 8 cursors and triggers

59
Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Upload: madlyn-collins

Post on 26-Dec-2015

217 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Simple Programming Part 2

SECTION 8

CURSORS and TRIGGERS

Page 2: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Cursors

• Stands for:– “Current set of records”

– It allows you to take a subset of data and output the information in various ways.

•An extremely important programming construct .

Page 3: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CURSOR Commands:

1.The OPEN command– Opens the cursor for use

2.The FETCH command– Retrieves a specific row from a cursor

3.The CLOSE command– Closes an open cursor

4.The DEALLOCATE command– Removes the cursor

Page 4: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Cursor Declaration

• Declared in the following manner:

1. Declare variables to hold the output from the cursor.

2. Declare the cursor object.

3. Assign the query to the cursor.

4. Open the cursor and fetch the first row

5. Loop until there are no more results. In the loop print out the Customer Number and the Customer Last Name from the result set and fetch the net

6. Close the cursor.

7. Deallocate the cursor to free up any memory or open result sets.

Page 5: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

The CUSTOMER Table

Page 6: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

1. Declare variables to hold the output from the cursor.

DECLARE @CustomerNumber as numeric;

DECLARE @CustomerName as nvarchar(20);

2. Declare the cursor object.

DECLARE @customer_cursor as CURSOR;

3. Assign the query to the cursor.

SET @customer_cursor = CURSOR FOR

SELECT CustomerNUmber, CustomerName

FROM CUSTOMER;

4. Open the cursor and fetch the fiurst row

OPEN @customer_cursor;

FETCH NEXT FROM @customer_cursor INTO @CustomerNumber, @CustomerName;

5. Loop until there are no more results. In the loop print out the Customer Number and the Customer Last Name from the result set and fetch the net row

WHILE @@FETCH_STATUS = 0

BEGIN

PRINT cast(@CustomerNumber as VARCHAR (50)) + ' ' + @CustomerName;

FETCH NEXT FROM @customer_cursor INTO @CustomerNumber, @CustomerName;

END

6. Close the cursor.

CLOSE @customer_cursor;

7. Deallocate the cursor to free up any memory or open result sets.

DEALLOCATE @customer_cursor;

The following uses a CURSOR from the CUSTOMER table

Page 7: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

What is in the cursor?

@CustomerNumber @CustomerName

5155 George Black

5204 Stephanie Green

5255 Alice Van Dunn

5346 Bonnie Stewart

5389 Jake Solaris

5443 Jane Quicker

Page 8: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 9: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

DECLARE @Customer as nvarchar(30);

DECLARE @customer_cursor as CURSOR;

SET @customer_cursor = CURSOR FOR

SELECT CONCAT(CustomerNumber,’ - ‘, CustomerName)

FROM CUSTOMER;

OPEN @customer_cursor;

FETCH NEXT FROM @customer_cursor INTO @Customer

WHILE @@FETCH_STATUS = 0

BEGIN

PRINT @Customer

FETCH NEXT FROM @customer_cursor INTO @Customer

END

CLOSE @customer_cursor;

DEALLOCATE @customer_cursor;

The following uses CONCAT using a CURSOR for CUSTOMER

Page 10: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 11: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Notice the dash mark ‘ - ‘

Notice the dash mark ‘ - ‘

Page 12: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 13: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

The Chinese Zodiac Procedure using a cursor

The CHINESE_ZODIAC table will be the basis of the cursor, zodiac_cursor

Page 14: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CREATE PROCEDURE Chinese_Zodiac_Proc05 (@birthyear NUMERIC)--This procedure deals with birth years and the Chinese ZodiacASDECLARE@BD NUMERIC(5), @X NUMERIC(10,6), @Y NUMERIC(4), @Z NUMERIC(2),@Number NUMERIC = 0,@ZodiacSign nVARCHAR(10),@zodiac_cursor as CURSORSET @zodiac_cursor = CURSOR FORselect * from chinese_zodiacBEGINSET @BD = @birthyear--The following deals with BCE years. There is no year 0IF @birthyear = 0BEGINSET @birthyear = 1PRINT 'Year 0 is not a vaild year. It should be year 1.'ENDIF @BD <1SET @BD = @BD +1SET @X = @BD/12SET @Y = @BD/12--The following reduces @Y by 1 when SQL Server rounds up a number to the next highest number.IF @Y > @X SET @Y = @Y-1SET @Z = (@X - @Y)*12ENDOPEN @zodiac_cursorFETCH NEXT FROM @zodiac_cursor INTO @Number, @ZodiacSignWHILE @@FETCH_STATUS = 0 and @Z <> @NumberFETCH NEXT FROM @zodiac_cursor INTO @Number,@ZodiacSignPRINT CAST(@birthyear as nVARCHAR(20)) + ' ' + @ZodiacSignPRINT '*****'CLOSE @zodiac_cursorDEALLOCATE @zodiac_cursor

Page 15: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 16: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 17: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

WHERE CURRENT OF

• Syntax:

WHERE CURRENT OF cursor_name;

Page 18: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Want to change Customer Number 5155 to 5156

Page 19: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 20: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 21: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

WHERE CURRENT OF:

When you use SQL you can update the current row by using an UPDATE statement that includes a WHERE CURRENT OF clause.

Changes made with this clause affect only the row on which the cursor is positioned.

When a cursor is based on a join, only the table_name specified in the UPDATE statement is modified.

Other tables participating in the cursor are not affected.

Page 22: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

• The previous example only changed on line of the table

– Where CustomerNumber = 5155

• To change multiple rows we need to loop through the table and change each row, one at a time.

• Need to use @@FETCH_STATUS

– Returns the status of the last cursor FETCH statement issued against any cursor currently opened

– Also use a loop with BEGIN …FETCH….END

• WHILE @@FETCH_STATUS = 0

– This means that while the fetch statement is successful

– Then do the next line in the procedure

Return Value Description

0 The FETCH statement was successful.

-1 The FETCH statement failed or the row was beyond the result set.

-2 The row fetched is missing.

Page 23: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Change multiple rows:

Page 24: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 25: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 26: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

MORE COMPLEX PROCEDURE

CREATE TABLE AlphaLtd_product(ProductName nVARCHAR(25) PRIMARY KEY,ProductPrice NUMERIC(4,2),QuantityOnHand NUMERIC(5,0),LastStockDate DATETIME2)

INSERT INTO AlphaLtd_product VALUES('Small Widget',99,1,'2014-01-15');INSERT INTO AlphaLtd_product VALUES('Medium Wodget',75,1000,'2013-01-15');INSERT INTO AlphaLtd_product VALUES('Chrome Phoobar',50,100,'2014-01-15');INSERT INTO AlphaLtd_product VALUES('Round Chrome Snaphoo',25,10000, null);INSERT INTO AlphaLtd_product VALUES('Extra Huge Mega Phoobar +',9.95,1234,'2015-01-15');INSERT INTO AlphaLtd_product VALUES('Square Zinculator',45,1,'2013-12-31');INSERT INTO AlphaLtd_product VALUES('Anodized Framifier',49,5, NULL);INSERT INTO AlphaLtd_product VALUES('Red Snaphoo',1.95,10,'2012-12-31');INSERT INTO AlphaLtd_product VALUES('Blue Snaphoo',1.95,10,'2012-12-30');

CREATE TABLE AlphaLtd_purchase(ProductName nVARCHAR(25),Salesperson nVARCHAR(3),PurchaseDate DATETIME2,Quantity NUMERIC(4,2))

INSERT INTO AlphaLtd_purchase VALUES('Small Widget','CA','2014-07-14',1);

INSERT INTO AlphaLtd_purchase VALUES('Medium Wodget','BB','2014-07-14',75);

INSERT INTO AlphaLtd_purchase VALUES('Chrome Phoobar','GA','2014-07-14',2);

INSERT INTO AlphaLtd_purchase VALUES('Small Widget','GA','2014-07-15',8);

INSERT INTO AlphaLtd_purchase VALUES('Medium Wodget','LB','2014-07-15',20);

INSERT INTO AlphaLtd_purchase VALUES('Round Chrome Snaphoo','CA','2014-07-16',5);

INSERT INTO AlphaLtd_purchase VALUES('Small Widget','CA','2014-07-17',1);

THE CURSOR

SELECT pur.Salesperson, pur.Quantity, prod.ProductPriceFROM AlphaLtd_purchase pur, AlphaLtd_product prodWHERE pur.ProductName = prod.ProductNameORDER BY Salesperson

Page 27: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 28: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Note the comment lines. They help to follow the logic.

Page 29: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

• The SELECT statement

• The FETCH commands

• The IF statements

Page 30: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Notice the carriage returns and indents

Page 31: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Cursor in CursorThe problem:What are the courses, and the student number and names of the students who took courses in semester 1 of 2008? The solution should look like the following.

Page 32: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

The tables – used in SQL section

CREATE TABLE U_COURSES(CourseNum NUMERIC(4),CourseName nVARCHAR(8),CourseDesc nVARCHAR(40),CONSTRAINT CourseNum_pk PRIMARY KEY (CourseNum));

CREATE TABLE U_SECTIONS(SectionId NUMERIC(5),CourseNum NUMERIC(4)CONSTRAINT CourseNum_fk REFERENCES U_COURSES,SectionNum NUMERIC(2),SemesterNum NUMERIC(6)CONSTRAINT SemesterNum_fk REFERENCES U_SEMESTER,FacNum NUMERIC(5)CONSTRAINT FacNum_fk REFERENCES U_FACULTY,CourseSecDay nVARCHAR(5),CourseSecTime nVARCHAR(8),LocNum NUMERIC(2)CONSTRAINT LocNum2_fk REFERENCES U_CLASS_LOCATION,CONSTRAINT SectionId_pk PRIMARY KEY (SectionId));

INSERT INTO U_COURSES VALUES(1001, 'Actg1B10', 'Intro. to Accounting');INSERT INTO U_COURSES VALUES(1002, 'Fnce2G56', 'Intro. to Finance');INSERT INTO U_COURSES VALUES(1003, 'Actg2D17', 'Intermediate Accounting');INSERT INTO U_COURSES VALUES(1004, 'Actg4R43', 'Advanced Accounting');INSERT INTO U_COURSES VALUES(1005, 'Mktg2D24', 'Intro. to Marketing');

INSERT INTO U_SECTIONS VALUES(10000,1001, 1, 200601, 3001, 'MWF', '10:00 AM', 35);INSERT INTO U_SECTIONS VALUES(10001,1001, 2, 200601, 3001, 'MWF', '3:00 PM', 35);INSERT INTO U_SECTIONS VALUES(10002,1002, 2, 200601, 3003, 'MTWRF', '11:00 AM', 55);INSERT INTO U_SECTIONS VALUES(10003,1003, 1,200702, 3004, 'MW', '9:00 AM', 45);INSERT INTO U_SECTIONS VALUES(10004,1003, 2, 200702, 3004, 'MW', '11:00 PM', 30);INSERT INTO U_SECTIONS VALUES(10005,1005, 1, 200702, 3006, 'T', '1:00 PM', 10);INSERT INTO U_SECTIONS VALUES(10006,1002, 1, 200703, 3002, 'W', '9:00 AM', 25);INSERT INTO U_SECTIONS VALUES(10007,1002, 2, 200703, 3002, 'R', '9:00 PM', 25);INSERT INTO U_SECTIONS VALUES(10008,1004, 1, 200703, 3005, 'MWF', '1:00 PM', 55);INSERT INTO U_SECTIONS VALUES(10009,1001, 1, 200701, 3001, 'MWF', '3:00 PM', 20);INSERT INTO U_SECTIONS VALUES(10010,1002, 1, 200701, 3006, 'MW', '3:00 PM', 40);INSERT INTO U_SECTIONS VALUES(10011,1002, 2, 200701, 3006, 'MW', '5:00 PM', 40);INSERT INTO U_SECTIONS VALUES(10012,1003, 1, 200801, 3003, 'W', '8:00 AM', 30);INSERT INTO U_SECTIONS VALUES(10013,1003, 2, 200801, 3003, 'W', '11:00 AM', 40);INSERT INTO U_SECTIONS VALUES(10014,1004, 1, 200801, 3005, 'MTWRF, '5:00 PM', 20);

Page 33: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

The tables - continuedCREATE TABLE U_STUDENT(StuNum NUMERIC(7),StuLast nVARCHAR(20),StuFirst nVARCHAR(10),StuAddress nVARCHAR(40),StuCity nVARCHAR(20),StuProv nVARCHAR(3),StuPostCode nVARCHAR(6),StuYear nVARCHAR(2),CONSTRAINT StuNum_pk PRIMARY KEY (StuNum));

INSERT INTO U_STUDENT VALUES(2074567, 'Randolph', 'Jennifer', '156 Wendover Drive', 'Toronto', 'ONT', 'M3A1H6', 'SO');INSERT INTO U_STUDENT VALUES(2057612, 'Jameson', 'Philip', '812 Augustus Blvd.', 'Hamilton', 'ONT', 'L9B3S2', 'SR');INSERT INTO U_STUDENT VALUES(2087194, 'Smithers', 'Paula', '7135 Yonge Street', 'Toronto', 'ONT', 'M6H2T4', 'FR');INSERT INTO U_STUDENT VALUES(2062109, 'Gordon', 'Emily', '812 Augustus Blvd.', 'St. Catharines', 'ONT', 'L2S7D3', 'JR');INSERT INTO U_STUDENT VALUES(2059152, 'Anderson', 'Cynthia', '89 Ball Road', 'Toronto', 'ONT', 'M1J8R4', 'SR');INSERT INTO U_STUDENT VALUES(2061032, 'VanDyk', 'William', '452 Overlord Place', 'St. Catharines', 'ONT', 'L2S2K7', 'JR');INSERT INTO U_STUDENT VALUES(2075947, 'Brotherson', 'Stephanie', '5134 Main Street', 'Hamilton', 'ONT', 'L8T6Y2', 'SO');INSERT INTO U_STUDENT VALUES(2080034, 'Collins', 'Amanda', '645 Powerline Road', 'St. Catharines', 'ONT', 'L2S4R2', 'FR');

CREATE TABLE U_ENROLLMENT(StuNum NUMERIC(7)CONSTRAINT StuNum_fk REFERENCES U_STUDENT,SectionId NUMERIC(5)CONSTRAINT CourseNum2_fk REFERENCES U_SECTIONS,Mark NUMERIC(2),Grade nVARCHAR(1),CONSTRAINT StuSection_pk PRIMARY KEY (StuNum, SectionId));

INSERT INTO U_ENROLLMENT VALUES(2074567, 10000, 80, 'A');INSERT INTO U_ENROLLMENT VALUES(2061032, 10001, 75, 'B');INSERT INTO U_ENROLLMENT VALUES(2075947, 10002, 85, 'A');INSERT INTO U_ENROLLMENT VALUES(2059152, 10003, 70, 'B');INSERT INTO U_ENROLLMENT VALUES(2057612, 10004, 90, 'A');INSERT INTO U_ENROLLMENT VALUES(2061032, 10004, 78, 'B');INSERT INTO U_ENROLLMENT VALUES(2075947, 10005, 68, 'C');INSERT INTO U_ENROLLMENT VALUES(2062109, 10005, 88, 'A');INSERT INTO U_ENROLLMENT VALUES(2057612, 10006, 75, 'B');INSERT INTO U_ENROLLMENT VALUES(2087194, 10007,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2080034, 10007,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2059152, 10008,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2061032, 10009,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2057612, 10010, 78, 'B');INSERT INTO U_ENROLLMENT VALUES(2074567, 10011, 85, 'A');INSERT INTO U_ENROLLMENT VALUES(2075947, 10012, 80, 'A');INSERT INTO U_ENROLLMENT VALUES(2061032, 10013,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2057612, 10013,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2075947, 10014,0,NULL);INSERT INTO U_ENROLLMENT VALUES(2057612, 10014,0,NULL);

Page 34: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

SELECT US.SectionId, UC.CourseName, US.SectionNumFROM U_COURSES UC, U_SECTIONS USWHERE UC.CourseNum = US.CourseNum AND US.SemesterNum = 200801ORDER BY US.SectionId, UC.CourseName, US.SectionNum;

The First Cursor

SELECT UE.SectionId, UE.StuNum, UST.StuFirst, UST.StuLastFROM U_ENROLLMENT UE, U_STUDENT UST, U_SECTIONS USWHERE UE.StuNum = UST.StuNumAND UE.SectionId = US.SectionId AND US.SemesterNum = 200801

The Second Cursor

Page 35: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CREATE PROCEDURE NewUniversity_procASDECLARE@x NUMERIC(5), @y nVARCHAR(8), @z NUMERIC(1),@a NUMERIC(5), @b NUMERIC(7), @c nVARCHAR(10), @d nVARCHAR(20);DECLARE @first_cur as CURSOR;SET @first_cur = CURSOR FOR

SELECT US.SectionId, UC.CourseName, US.SectionNumFROM U_COURSES UC, U_SECTIONS USWHERE UC.CourseNum = US.CourseNum AND US.SemesterNum = 200801ORDER BY US.SectionId, UC.CourseName, US.SectionNum;

OPEN @first_cur;FETCH NEXT FROM @first_cur INTO @x, @y, @z;WHILE @@FETCH_STATUS = 0 -- Outer cursor loopBEGINDECLARE @second_cur as CURSOR;SET @second_cur = CURSOR FORSELECT UE.SectionId, UE.StuNum, UST.StuFirst, UST.StuLastFROM U_ENROLLMENT UE, U_STUDENT UST, U_SECTIONS USWHERE UE.StuNum = UST.StuNumAND UE.SectionId = US.SectionId AND US.SemesterNum = 200801ORDER BY UE.SectionId, UE.StuNum;

-- Nested cursorOPEN @second_cur;FETCH NEXT FROM @second_cur into @a, @b, @c, @d;

PRINT @y + ' Section ' + CONVERT(nVARCHAR(20), @z)PRINT '***'WHILE @@FETCH_STATUS = 0 -- Inner cursor loop (nested cursor while)

BEGINIf @x = @aPRINT CONVERT(nVARCHAR(20), @b) + ' ' + @c + ' ' + @d;FETCH NEXT FROM @second_cur into @a, @b, @c, @d;END -- Inner cursor loop

PRINT '================================='FETCH NEXT FROM @first_cur INTO @x, @y, @z;CLOSE @second_cur;DEALLOCATE @second_cur;END -- Outer cursor loop

CLOSE @first_cur;DEALLOCATE @first_cur;

Page 36: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Notice that the second cursor is recreated each time you go through

the first cursor loop. This can sometimes not be very efficient.

Page 37: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Exception Handling

• Opportunity to issue meaningful error messages

• Exceptions

Page 38: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

System Messages

• DIVIDE BY ZERO

• Two ways of showing a user information about an error.

1. ERROR_NUMBER

2. ERROR_MESSAGE

Page 39: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 40: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

All we are doing here is forcing an error. The actual error does not make sense when it

comes to INSERTING values

Page 41: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Programmer-Defined Exceptions

• One can create their own conditions and names

• An example shown of how to define your own error messages

• Life: Valid only for this block

Page 42: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 43: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

TriggersA database trigger is procedural code

Automatically executes in response to certain events on a particular on a particular or view in a database.

The trigger is mostly used for maintaining the integrity of the information on the database.

Page 44: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Create Table master.dbo.audit_logins(LoginName nVARCHAR(50), -- holds the login nameLoginType nVARCHAR(50),-- holds the login typeLoginTime DATETIME2, -- holds the time of the loginClientHost nVARCHAR(50))-- holds the host from which the login request originated

Create the Logon trigger:

Create TRIGGER TR_audit_loginsON ALL SERVER WITH EXECUTE AS 'sa‘FOR LOGONASBEGIN

declare @LogonTriggerData xml --XML datatype, stores XML dataset @LogonTriggerData = eventdata();Insert into master..audit_loginsSelect @LogonTriggerData.value('(/EVENT_INSTANCE/LoginName)[1]', 'varchar(50)'),

@LogonTriggerData.value('(/EVENT_INSTANCE/LoginType)[1]', 'varchar(50)'), @LogonTriggerData.value('(/EVENT_INSTANCE/PostTime)[1]', 'datetime'), @LogonTriggerData.value('(/EVENT_INSTANCE/ClientHost)[1]', 'varchar(50)')END

An Example of a Login Trigger

Page 45: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Extensible Markup Language (XML) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable.

A markup language is a system for annotating a document in such a way that the syntax is distinguishable from the text.

The design goals of XML emphasize simplicity, generality and usability across the Internet.

<recipe>

<title>Bread and Butter</title><ingredientslist>

<ingredient>Bread</ingredient><ingredient>Butter</ingredient>

</ingredientlist>

<preparation>Put butter on a knife and spread on the bread.

</preparation>

</recipe>

Page 46: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

<EVENT_INSTANCE><EventType> event </EventType><PostTime> datetime </PostTime><SPID> spid </SPID><ClientHost> host </ClientHost><ServerName> name </ServerName><LoginName> login </LoginName><UserName> name </UserName><DatabaseName> name </DatabaseName><SchemaName> name </SchemaName><ObjectName> name </ObjectName><ObjectType> type </ObjectType><TSQLCommand> command </TSQLCommand>

</EVENT_INSTANCE>

What EVENT_INSTANCE contains the following data in XML format

SELECT HOST_NAME() AS HostName, SUSER_NAME() LoggedInUser

Page 47: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Simple Trigger Examples

Will work with the FACTORY_WORKER table, used previously, and a new table FACTORY_WORKER_BACKUP

Page 48: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

DML triggers execute when a user tries to modify data through a data manipulation language (DML) event such as INSERT, UPDATE, or DELETE statements on a table or view.

DML triggers can be used to:

1. enforce business rules2. enforce data integrity3. query other tables.

Can include complex Transact-SQL statements. The trigger and the statement that fires it are treated as a single transaction, which can be rolled back from within the trigger. If a severe error is detected (for example, insufficient disk space), the entire transaction automatically rolls back.

The most common table-oriented triggers:

1.INSERT, DELETE, and UPDATE

2.AFTER INSERT, AFTER DELETE, AFTER UPDATE

3.INSTEAD OF.

Page 49: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

Two special tables are used in trigger statements:

1.INSERTED:•The inserted table stores copies of the affected rows during INSERT and UPDATE statements.•During an insert or update transaction, new rows are added simultaneously to both the inserted table and the trigger table.•The rows in the inserted table are copies of the new rows in the trigger table.

2.DELETED:•The deleted table stores copies of the affected rows during DELETE and UPDATE statements. During the execution of a DELETE or UPDATE statement, rows are deleted from the trigger table and transferred to the deleted table.•The deleted table and the trigger table ordinarily have no rows in common.

Page 50: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CREATE TRIGGER trigAddFactoryWorkerON FACTORY_WORKERFOR INSERT ASDECLARE @FWNumber NUMERIC(4)SELECT @FWNumber= (SELECT FWNumber FROM INSERTED)PRINT 'FACTORY WORKER ' + CAST(@FWNumber as nVARCHAR(20)) + ' IS ADDED.'

CREATE TRIGGER trigAfterInsertFactoryWorkerON FACTORY_WORKERAFTER INSERTASBEGINSET NOCOUNT ON-- Stops the message indicating the number of rows affected by a Transact-SQL statement-- from being returned as part of the results.INSERT INTO FACTORY_WORKER_BACKUPSELECT * FROM INSERTEDPRINT 'The Factory Worker Backup Table has been UPDATED.'END

INSERT TRIGGER

AFTER INSERT TRIGGER

Page 51: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 52: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 53: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CREATE TRIGGER trigDeleteFactoryWorkerON FACTORY_WORKERFOR DELETEASDECLARE @FWNumber NUMERIC(4)SELECT @FWNumber = (SELECT FWNumber FROM DELETED)PRINT 'FACTORY WORKER ' + CAST(@FWNumber as nVARCHAR(20)) + ' IS DELETED.'

CREATE TRIGGER trigAfterDeleteFactoryWorkerON FACTORY_WORKERAFTER DELETEASBEGINSET NOCOUNT ONDELETE FROM FACTORY_WORKER_BACKUPWHERE FWNumber = (SELECT FWNumber FROM DELETED)PRINT 'The Factory Worker Backup Table has been UPDATED.'END

DELETE TRIGGER

AFTER DELETE TRIGGER

Page 54: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 55: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 56: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CREATE TRIGGER trigUpdateFactoryWorkerON FACTORY_WORKERFOR UPDATEASDECLARE @FWNumber NUMERIC(4)SELECT @FWNumber = (SELECT FWNumber FROM INSERTED)PRINT 'FACTORY WORKER ' + CAST(@FWNumber as nVARCHAR(20)) + ' IS UPDATED.'

CREATE TRIGGER trigAfterUpdateFactoryWorkerON FACTORY_WORKERAFTER UPDATEASBEGINDECLARE @FWNumber NUMERIC(4), @FWFirstName nVARCHAR(20), @FWLastName nVARCHAR(20)SET NOCOUNT ONSELECT @FWNumber = (SELECT FWNumber FROM INSERTED)SELECT @FWFirstName = (SELECT FWFirstName FROM INSERTED)SELECT @FWLastName = (SELECT FWLastName FROM INSERTED)UPDATE FACTORY_WORKER_BACKUPSET FWNumber = @FWNumber WHERE FWNumber = @FWNumberUPDATE FACTORY_WORKER_BACKUPSET FWFirstName = @FWFirstName WHERE FWNumber = @FWNumberUPDATE FACTORY_WORKER_BACKUPSET FWLastName = @FWLastName WHERE FWNumber = @FWNumberPRINT 'The Factory Woker Backup Table has been UPDATED.'END

UPDATE TRIGGER

AFTER UPDATE TRIGGER

Page 57: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 58: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS
Page 59: Simple Programming Part 2 SECTION 8 CURSORS and TRIGGERS

CREATE TRIGGER trigInsteadOfFactoryWorkerON FACTORY_WORKERINSTEAD OF UPDATEASBEGINSET NOCOUNT ON

IF UPDATE (FWNumber)RAISERROR ('You cannot change a Factory Worker Number!This transaction will not be entered.',10,1)

END

INSTEAD OF TRIGGER