Presentation on theme: "SOME COOL NMMI SQL TRIGGERS by Bryan Yates, New Mexico Military Institute in Roswell, NM"— Presentation transcript:
SOME COOL NMMI SQL TRIGGERS by Bryan Yates, New Mexico Military Institute in Roswell, NM My Info
In the beginning We migrated to ABT PowerCAMPUS in 2002 We realized ABT did a lot of things in triggers and we could also leverage this for a lot of business processes We decided that upgrades were too risky to create our own tables in Campus6, so we created a new Database called Institute. We initially didn’t know we could have multiple insert/update/delete triggers per table, so we initially called a stored procedure called from ABT’s trigger and re-inserted it after every upgrade We check to ensure we’re in the live database before pushing data to Institute, this could be improved if all tables were in the Campus6 database. Testing with db copies would be better.
Our first audit trigger -- Use the Specify Values for Template Parameters -- command (Ctrl-Shift-M) to fill in the parameter -- values below. -- use ALTER TABLE ADD create_date datetime NULL, create_time datetime NULL, create_user varchar(12) NULL, revision_date datetime NULL, revision_time datetime NULL, revision_user varchar(12) NULL go CREATE TRIGGER ti_audit_ ON FOR INSERT AS /* Audit Fields */ varchar(20) = from Inserted exec sp_Audit_Create ' ',' go CREATE TRIGGER tu_audit_ ON dbo. FOR UPDATE AS /* Audit fields */ varchar(20) = from Inserted exec sp_Audit_Revision ' ',' go
Lessons learned Only works on first item if bulk insert done Insert into tbl (id,name) values (1,’a’),(2,’b’) Inset into tbl (id,name) select top 2 id,name from tbl2 Templates are cool, sometimes Only usable on tables with a single primary key Should have used NMMI in the name of the trigger, and a description, like ti_TBL_NMMI_audit Eventually learned that you can make triggers for insert AND update in the same trigger
New database table, who did that? -- ============================================= -- Author: Gary Hill -- Create date: 6/6/ Description: Send an to programmers when a new database is created. -- ============================================= CREATE TRIGGER [trg_DDL_CreateDatabase] ON ALL SERVER FOR CREATE_DATABASE AS varchar(200) = 'DATABASE Created on ' + + ' by ' + SUSER_SNAME() = (SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)','nvarchar(max)')) EXEC = @subject GO
tu_residency_nmmi, room changes Simple enough, let’s track some room changes, but not just between semesters Originally used to help keep the phone number with the student Extended to keep the switch and port info stored in FAX field to know if student port was locked (loss of privilege). Abandoned by IT due to in room phones going away and edge smart switch management improvements Housing office still uses to review problem cases
tu_residency_nmmi if -- only the guts are shown AND AND (DB_NAME() = 'CAMPUS6') -- BAY 7/22/09 to allow room/troop/status updates to go straight into Housing AND DB_NAME() = 'CAMPUS6' AND <> or <> or <> ) IN (select PEOPLE_CODE_ID from institute.dbo.CMDT_Housing_INFO) update institute.dbo.CMDT_Housing_INFO set Room_Id where people_code_id
sp_room_change INSERT INTO Institute.dbo.Room_Changes (People_ID, Old_Room_ID, Old_Phone_Number, New_Room_ID, New_Phone_Number, Academic_Year, Academic_Term, Create_Date, Create_Time, Create_User, Create_Terminal, Revision_Date, Revision_Time, Revision_User, Revision_Terminal) @create_terminal) -- update campus address with new phone number and mail slot update CAMPUS6.dbo.AddressSchedule Set Address_Line_1 = 'NMMI Mail Slot from CAMPUS6.dbo.AddressSchedule where and Address_type = 'CAMP' and Status = 'A' update campus6.dbo.RESIDENCY set DORM_ROOM from campus6.dbo.RESIDENCY RES join semesterinfo SI on SI.academic_year = res.ACADEMIC_YEAR and si.academic_term = res.ACADEMIC_TERM and si.academic_session = res.ACADEMIC_SESSION and si.offset > 0 where res.PEOPLE_CODE_ID = 'P'
StudentFinancial This Campus6 table gets created on the roll and on certain events during in-processing We use the PaymentPlan field to define the “Financial Advisor” for each student. This is usually based on the first letter of their last name, but full or partial AGA scholarship recipients, and some other exceptions exist Business Office didn’t have rights to StudentFinancial table because Registrar wanted full control over Tuition_Plan and Tuition_Exemption.
StudentFinancial trigger CREATE trigger [dbo].[ti_studentfinancialNMMIfinAdv] on [dbo].[STUDENTFINANCIAL] for INSERT as /*********************************************************************** Description: Update non-AGA Financial Advisors using the PaymentPlan field Parameters: History: 1/30/2012 BAY created to help auto-maintain Financial Advisors ************************************************************************/ update studentfinancial set PAYMENT_PLAN = FA.PaymentPlanCode from studentfinancial SF join inserted INS on INS.people_code_id = SF.people_code_id and INS.academic_year = SF.academic_year and INS.academic_term = SF.academic_term and INS.academic_session = SF.academic_session join PEOPLE PEO on PEO.PEOPLE_CODE_ID = SF.PEOPLE_CODE_ID join Institute.dbo.BO_STMT_Financial_Advisor FA on charindex(LEFT(PEO.LAST_NAME,1),FA.FIRST_LETTER) > 0 where SF.ACADEMIC_SESSION = '01' and isnull(SF.TUITION_EXEMPTION,'') not in ('aga','aganon') and isnull(SF.PAYMENT_PLAN,'') = '' GO
StudentFinancial, Supporting data select * from Institute.dbo.BO_STMT_Financial_Advisor -- drives triggers, and pre/billing groupings select * from campus6.dbo.CODE_PAYMENTPLAN -- shows in PowerCAMPUS PaymentPlanCodeFIRST_LETTERAdvisorNameAdvisorPhoneusername 1FAABCMrs. Angelia Horton(575) angelia 2FAHIJKLMs. Shelly Wheeler(575) shelly 3FADEFGMs. Rebecca Quintero(575) quinter 4FAMNOMrs. Sarah Villarreal(575) sarah 5FAPQRSMrs. Linda Stansell(575) stansell 6FATUVWXYZCPT Ma Eva Heacox(575) ma_eva AGANULLCPT Amanda Garcia(575) garciaa CODE_VALUE_KEYCODE_VALUESHORT_DESCMEDIUM_DESCLONG_DESCSTATUS 1FA Mrs. Angelia HortonMrs. Angelia Horton at (575) A 2FA Ms. Shelly WheelerMs. Shelly Wheeler at (575) A 3FA Ms. Rebecca QuinteroMs. Rebecca Quintero at (575) A 4FA Mrs Sarah VillarrealMrs. Sarah Villarreal at (575) A 5FA Mrs. Linda StansellMrs. Linda Stansell at (575) A 6FA CPT Ma Eva HeacoxCPT Ma Eva Heacox at (575) A AGA CPT Amanda GarciaCPT Amanda Garcia at (575) A
StudentFinancial summary I think this trigger is so cool, because of 2 things The trigger joins directly to the Inserted table, meaning any bulk imports are handled without “looping” over them The first initial of the last name join is really slick
Absent 2 or more times in one day? CREATE TRIGGER [dbo].[ti_tranattendance_nmmi] ON [dbo].[TRANATTENDANCE] FOR INSERT AS nvarchar(1) nvarchar(9) nvarchar(10) nvarchar(4) nvarchar(10) nvarchar(10) nvarchar(15) nvarchar(4) nvarchar(4) datetime nvarchar(10) datetime datetime nvarchar(8) nvarchar(4) datetime datetime nvarchar(8) nvarchar(4) nvarchar(1) nvarchar(max) INT int = -- this will loop over multiple line inserts correctly <= 0 Return = 0 = (Select Min([TranAttendanceId]) From inserted Where [TranAttendanceId] Is Not Null BEGIN COMMENTS FROM inserted WHERE TranAttendanceId If (DB_NAME() = 'CAMPUS6' and in ('ABSENT','TARDY'))) -- move into lines someday? Begin EXEC institute.dbo.sp_absence -- Ok, what real people would more likely do goes here from next slide End = (Select Min( [TranAttendanceId] ) From inserted Where [TranAttendanceId] --Get Next Id END
institute.dbo.sp_absence Our sp_absence stored procedure actually checks multiple data sources (two off campus reports, and infirmary reports) to see if it can excuse the user, defer the decision (can’t make a decision before the end of class, if in the infirmary), or enter a “Stick” (our homegrown violation system). Deferred decisions are checked again hourly If not excused, they receive a Stick Then an insert trigger on our Stick table checks for the same student 2 and more times today, and sends Depends a lot on Faculty prompt Attendance reporting
Absent trigger, generalized for non-NMMI -- replace the “EXEC institute.dbo.sp_absence …” line in ti_tranattendance_nmmi with something like below, I did test this code -- variables varchar(4000) select -- define variables only if sum for the day = PEO.LAST_NAME + ', ' + PEO.first_name + ' ' + right(PEO.people_code_id,9) + ' ABSENT '+ cast(COUNT(*) as varchar) + ' times = ' CRR Link = + case when EMPA. _Address IS not null then replace(empA. _Address + ','') + ';' else '' end from TRANATTENDANCE TA join TRANATTENDANCE TA2 on TA.TranAttendanceId and TA2.People_Code_ID = TA.People_Code_ID and TA2.ATTENDANCE_DATE = TA.ATTENDANCE_DATE -- = limits per date report, not limited in WHERE to allow testing with any date join people PEO on PEO.PEOPLE_CODE_ID = TA.People_Code_ID JOIN Academic ACA on ACA.PEOPLE_CODE_ID = TA.PEOPLE_CODE_ID and ACA.ACADEMIC_YEAR = TA.ACADEMIC_YEAR and ACA.ACADEMIC_TERM = TA.ACADEMIC_TERM and ACA.ACADEMIC_SESSION = TA.ACADEMIC_SESSION left join institute.dbo.Employees EMPA -- view of active employees on EMPA.PEOPLE_ID = RIGHT(ACA.ADVISOR,9) -- or on 'P'+EMPA.PEOPLE_ID = ACA.ADVISOR -- which is better? where TA2.ATTENDANCE_STATUS in ('ABSENT') and TA.ATTENDANCE_STATUS in ('ABSENT') -- add Tardy if you want and CONVERT (date, GETDATE())= TA.ATTENDANCE_DATE -- limit to today, comment out for testing group by PEO.People_Code_ID,PEO.LAST_NAME,PEO.first_name,EMPA. _Address having COUNT(*) > 1 if is not null) -- if variables are not null, then send something off begin EXEC = = @importance = -- – switch around for testing end
Summary, Questions Please nit-pick my code, Should ANSI_NULLS ON and QUOTED_IDENTIFIER ON ? Ok, Better, Best practices Dependencies across databases “Base View” starting points for departments Download I’m staying on campus & love to talk geek Other valid geek topics include Raspberry Pi, and C# I am also finishing a campus migration from Exchange 2007 to Office 365, if you want to talk about that My Info