use ReportBuilderTraining --- --- rights a stored procedure designed to be run nightly that updates each student's current GPA --- based on data in the StudentHistory table --- --- experminent with creating/alterings stored procedures, try/catch error handling and transactions --- --- In truth, the entire updated could be written in one statement, but we handle the task less effeciently here --- to demonstrate the concepts. --- -- add a CurrentGPA field to the Student table, if is doesn't already exist if not exists (select * from information_schema.columns where TABLE_SCHEMA='dbo' and TABLE_NAME='Student' and COLUMN_NAME='CurrentGPA') alter table dbo.Student add CurrentGPA numeric(4,2) null go --- --- Create the procedure --- CREATE PROCEDURE dbo.sp_UpdateCurrentGPA AS BEGIN -- -- get most recent GPA for each student and write to temp table -- -- note that we don't need to worry about #temp already existing -- select StudentId ,CumulativeGPA ,row_number() over (partition by StudentId order by TermID desc) row into #temp from dbo.StudentHistory where CumulativeGPA is not NULL delete from #temp where row!=1 BEGIN TRANSACTION BEGIN TRY update dbo.Student set CurrentGPA = NULL update dbo.Student set CurrentGPA=t.CumulativeGPA from dbo.Student s join #temp t on s.StudentId=t.StudentId COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION END CATCH END GO select * from dbo.Student go exec dbo.sp_UpdateCurrentGPA go select * from dbo.Student go --- --- Now, edit stored procedure to intentionally cause and error, and see error handling work --- ALTER PROCEDURE dbo.sp_UpdateCurrentGPA AS BEGIN -- -- get most recent GPA for each student -- select StudentId ,CumulativeGPA ,row_number() over (partition by StudentId order by TermID desc) row into #temp from dbo.StudentHistory where CumulativeGPA is not NULL delete from #temp where row!=1 BEGIN TRANSACTION BEGIN TRY update dbo.Student set CurrentGPA = NULL update dbo.Student set CurrentGPA = 1./0 update dbo.Student set CurrentGPA=t.CumulativeGPA from dbo.Student s join #temp t on s.StudentId=t.StudentId COMMIT TRANSACTION END TRY BEGIN CATCH print ERROR_MESSAGE() -- -- should really test transaction state here with xact_state() -- and should also worry about "nested" transactions (hint: they are not nested at -- all, a rollback rolls back all the way to the first "begin transaction") -- -- See https://docs.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql -- ROLLBACK TRANSACTION END CATCH END GO exec dbo.sp_UpdateCurrentGPA go select * from dbo.Student go