ทริกเกอร์ฐานข้อมูล
ทริกเกอร์ฐานข้อมูลคือโค้ดขั้นตอนที่ดำเนินการโดยอัตโนมัติเพื่อตอบสนองต่อเหตุการณ์ เฉพาะ บนตารางหรือมุมมองในฐานข้อมูลทริกเกอร์มักใช้เพื่อรักษาความสมบูรณ์ ของข้อมูล ภายในฐานข้อมูล ตัวอย่างเช่น การแทรกบันทึกพนักงานใหม่สามารถสร้างรายการที่เกี่ยวข้องในตารางภาษี วันหยุด และเงินเดือนโดยอัตโนมัติ ในทำนองเดียวกัน ทริกเกอร์ช่วยให้สามารถบันทึกข้อมูลในอดีตได้ เช่น การติดตามค่าใช้จ่ายสำหรับเงินเดือนพนักงานเมื่อเวลาผ่านไป[ 1 ]
ทริกเกอร์ในระบบจัดการฐานข้อมูล (DBMS)
ด้านล่างนี้คือภาพรวมของวิธีการที่ ระบบจัดการ ฐานข้อมูล (DBMS) ทั่วไปหลายระบบ รองรับทริกเกอร์
ออราเคิล
นอกเหนือจาก ทริกเกอร์ ภาษาการจัดการข้อมูลมาตรฐาน (DML)ที่เรียกใช้ โค้ด PL/SQLเมื่อมีการแก้ไขข้อมูลแล้วOracleยังรองรับทริกเกอร์ที่ทำงานเมื่อมีการเปลี่ยนแปลงระดับสคีมาและเหตุการณ์ฐานข้อมูลทั่วทั้งระบบ ทั้งทริกเกอร์ภาษาการกำหนดข้อมูลระดับสคีมา(DDL)และทริกเกอร์เหตุการณ์ระบบได้รับการแนะนำพร้อมกันในOracle 8i [ 2 ] [ 3 ]
ทริกเกอร์ระดับสคีมา
BEFORE CREATEAFTER CREATEBEFORE ALTERAFTER ALTERBEFORE DROPAFTER DROP
การทำงานของทริกเกอร์ DML มาตรฐานของ Oracle นั้นถูกกำหนดโดยระดับความละเอียด (ความถี่ในการทำงานของทริกเกอร์) และการกรองเหตุการณ์ (การเปลี่ยนแปลงเฉพาะใดที่จะกระตุ้นการทำงาน):
โดยระดับความละเอียด
- ระดับแถว: ทริก เกอร์จะทำงานหนึ่งครั้งสำหรับแต่ละแถวที่ได้รับผลกระทบจาก คำสั่ง INSERT , UPDATEหรือDELETE (ที่กำหนดโดยใช้
FOR EACH ROWเงื่อนไข) หากคำสั่งแก้ไขห้าสิบแถว ทริกเกอร์จะทำงานห้าสิบครั้ง - ระดับคำสั่ง:ดำเนินการเพียงครั้งเดียวสำหรับ คำสั่ง SQL ทั้งหมด โดยไม่คำนึงถึงจำนวนแถวที่ถูกแก้ไข (พฤติกรรมเริ่มต้นหรือกำหนดโดยใช้
FOR EACH STATEMENT) จะทำงานแม้ว่าจะไม่มีแถวใดได้รับผลกระทบจากการดำเนินการก็ตาม
โดยการกรองเหตุการณ์
- ระดับตาราง:เปิดใช้งานกับการดำเนินการมาตรฐานใดๆ
INSERTที่UPDATEกำหนดDELETEเป้าหมายไปยังตารางทั้งหมด - ระดับคอลัมน์:ตัวกรองพิเศษที่ใช้กับ
UPDATEทริกเกอร์ ซึ่งจำกัดการทำงานให้ทำงานเฉพาะเมื่อมีการแก้ไขคอลัมน์ที่ระบุชื่อไว้เท่านั้น (กำหนดโดยใช้UPDATE OF column_nameไวยากรณ์)
ทริกเกอร์ระดับสคีมาและระดับระบบ
- ทริกเกอร์ระดับสคีมา (DDL):ทำงานเมื่อมีการเปลี่ยนแปลงอ็อบเจ็กต์สคีมาผ่านคำสั่งต่างๆ เช่น
AFTER,CREATE,BEFORE ALTER, หรือAFTER DROP. - ทริกเกอร์ระดับระบบ : ทำงานเพื่อตอบสนองต่อเหตุการณ์ฐานข้อมูลเชิงปฏิบัติการ รวมถึงการเข้าสู่ระบบของผู้ใช้ ผู้ใช้
LOGOFFฐานข้อมูลSTARTUPและฐานSHUTDOWNข้อมูล[ 4 ]
ไมโครซอฟต์ SQL Server
Microsoft SQL Server รองรับทริกเกอร์สำหรับคำสั่ง DML และ DDL รวมถึงทริกเกอร์พิเศษ "การเข้าสู่ระบบ" ด้วย
ขอบเขตของทริกเกอร์ DDL สามารถเป็นฐานข้อมูลเดียวCREATE TRIGGER...ON DATABASEหรืออินสแตนซ์ SQL Server ทั้งหมดก็ได้CREATE TRIGGER...ON ALL SERVERเมื่อกำหนดค่าสำหรับอินสแตนซ์ทั้งหมด ทริกเกอร์จะตรวจจับทั้งเหตุการณ์ระดับเซิร์ฟเวอร์และระดับฐานข้อมูลที่ดำเนินการภายในอินสแตนซ์นั้น
รายการเหตุการณ์การเรียกใช้งานทริกเกอร์ DDL ที่มีอยู่ทั้งหมดมีอยู่ในเอกสารอย่างเป็นทางการของ Microsoft [ 5 ]
ทริกเกอร์ DDL ใน SQL Server สามารถครอบคลุมฐานข้อมูลเดียวหรือทั้งอินสแตนซ์ได้ สำหรับการดำเนินการ DML จะใช้ตารางเสมือน insertedและdeletedในขณะที่ทริกเกอร์ทำงานในระดับคำสั่ง แต่สามารถใช้ตรรกะระดับแถวได้ผ่านเคอร์เซอร์
โพสต์เกรสซีอาร์
PostgreSQLเพิ่มการรองรับทริกเกอร์ในปี 1997 ต่อมาได้รวมทริกเกอร์เฉพาะคอลัมน์ในเวอร์ชัน 9.0 ซึ่งสอดคล้องกับมาตรฐานSQL:2003 อย่างสมบูรณ์ [ 6 ]ในขณะที่ทริกเกอร์ DML มาตรฐานจะผูกกับตารางเฉพาะ การแก้ไขสคีมาที่ไม่ใช่ DML เช่นCREATE TABLEจะถูกบันทึกทั่วโลกในระดับฐานข้อมูลโดยทริกเกอร์เหตุการณ์ ซึ่งเป็นคุณสมบัติที่แนะนำใน PostgreSQL 9.3 [ 7 ]
ไวยากรณ์ SQL พื้นฐานสำหรับการกำหนดทริกเกอร์ใน PostgreSQL มีโครงสร้างดังนี้:
สร้างทริกเกอร์name { ก่อน| หลัง} { เหตุการณ์[ หรือ... ] } บนtable_name [ สำหรับ[ แต่ละ] { แถว| คำสั่ง} ] เรียกใช้โปรซีเดอร์funcname ( อาร์กิวเมนต์)นกไฟ
Firebirdรองรับทริกเกอร์ระดับแถวหลายตัวต่อตารางสำหรับ การดำเนินการ INSERT, UPDATE, และDELETEรวมถึงการรวมกันของการกระทำเหล่านี้ ทริกเกอร์เหล่านี้จะทำงานก่อนหรือหลังการแก้ไขข้อมูล และทำงานเพิ่มเติมจากการเปลี่ยนแปลงตารางเริ่มต้น ผู้ใช้สามารถระบุลำดับการทำงานของทริกเกอร์หลายตัวที่สัมพันธ์กันได้โดยใช้POSITIONข้อความ ทริกเกอร์ยังสามารถกำหนดบนวิวเป็นINSTEAD OFทริกเกอร์ ซึ่งจะแทนที่ตรรกะของวิวที่สามารถอัปเดตได้เริ่มต้น ก่อนเวอร์ชัน 2.1 ทริกเกอร์บนวิวที่สามารถอัปเดตได้จะทำงานเพิ่มเติมจากตรรกะของเอนจินเริ่มต้น แทนที่จะแทนที่[ 8 ]
โดยค่าเริ่มต้น เอ็นจินฐานข้อมูลอนุญาตให้ทริกเกอร์ซ้อนกันและเรียกซ้ำได้ และจะไม่สร้างข้อยกเว้นตารางที่เปลี่ยนแปลงข้อมูล Firebird ใช้ ตัวแปรบริบท NEWและOLDเพื่อเข้าถึงสถานะของแถวในระหว่างการแก้ไขข้อมูล นอกจากนี้ยังให้แฟล็กบริบทแบบบูลีนINSERTING, UPDATING, และDELETINGแฟล็กเพื่อระบุเหตุการณ์ DML เฉพาะที่เริ่มต้นการทำงานของทริกเกอร์โดยใช้โปรแกรม
{ สร้าง| สร้างใหม่| สร้างหรือแก้ไข} ชื่อทริกเกอร์สำหรับ{ ชื่อตาราง| ชื่อวิว} [ ใช้งาน| ไม่ใช้งาน] { ก่อน| หลัง} { แทรก[ หรืออัปเดต] [ หรือลบ] | อัปเดต[ หรือแทรก] [ หรือลบ] | ลบ[ หรืออัปเดต] [ หรือแทรก] } [ ตำแหน่งn ] เริ่มต้น.... สิ้นสุดตั้งแต่เวอร์ชัน 2.1 เป็นต้นไป Firebird ได้เพิ่มการรองรับทริกเกอร์ระดับฐานข้อมูล ซึ่งจะทำงานเมื่อเกิดเหตุการณ์เฉพาะในเซสชันและธุรกรรม ตัวอย่างเช่น เหตุการณ์การเชื่อมต่อ ผ่านท ริกเกอร์ CONNECTและDISCONNECTและเหตุการณ์ธุรกรรม ผ่าน ทริกเกอร์ TRANSACTION START, TRANSACTION COMMIT, และ TRANSACTION ROLLBACKหากเกิดข้อยกเว้นระหว่างCONNECTทริกเกอร์ ลำดับการเชื่อมต่อจะถูกยกเลิก ในทำนองเดียวกัน ข้อยกเว้นที่เกิดขึ้นภายในทTRANSACTION COMMITริกเกอร์จะขัดขวางการดำเนินการธุรกรรมให้เสร็จสมบูรณ์ รวมถึงขั้นตอนการเตรียมการระหว่างการยืนยันแบบสองขั้นตอน
ทริกเกอร์ระดับฐานข้อมูลสามารถใช้เพื่อบังคับใช้ข้อจำกัดหลายตารางหรือเพื่อจำลองมุมมองที่สร้างขึ้นเมื่อเกิดข้อยกเว้นภายในTRANSACTION COMMITทริกเกอร์ การแก้ไขธุรกรรมที่ทำโดยทริกเกอร์ก่อนเกิดข้อผิดพลาดจะถูกยกเลิก และแอปพลิเคชันไคลเอ็นต์จะได้รับแจ้ง อย่างไรก็ตาม ธุรกรรมนั้นยังคงทำงานอยู่ราวกับว่าCOMMITการดำเนินการไม่เคยเริ่มต้น ทำให้แอปพลิเคชันสามารถทำการแก้ไขข้อมูลเพิ่มเติมและร้องขอลำดับการยืนยันได้[ 9 ]
รูปแบบไวยากรณ์ทั่วไปสำหรับการสร้างหรือแก้ไขทริกเกอร์ระดับฐานข้อมูลใน Firebird มีโครงสร้างดังต่อไปนี้:
{ สร้าง| สร้างใหม่| สร้างหรือแก้ไข} ชื่อทริกเกอร์[ ใช้งาน| ไม่ทำงาน] เมื่อ{ เชื่อมต่อ| ตัดการเชื่อม ต่อ | เริ่ม ธุรกรรม | ยืนยันธุรกรรม| ยกเลิกธุรกรรม} [ ตำแหน่งn ] เริ่มต้น..... สิ้นสุดMySQL/MariaDB
ทริกเกอร์ MySQL/MariaDB ซึ่งเปิดตัวในปี 2548 (เวอร์ชัน 5.0) รองรับเหตุการณ์ DML โดย MySQL 8.0 อนุญาตให้ใช้ทริกเกอร์ประเภทเดียวกันได้หลายตัว แม้ว่าทริกเกอร์ DDL จะไม่ได้รับการสนับสนุนก็ตาม[ 10 ]ไวยากรณ์ที่เข้ากันได้กับทั้งสองระบบใช้ , CREATE TRIGGER, DROP TRIGGERและ สำหรับการ ดำเนินFOR EACH ROWการระดับแถว โดยมีเนื้อหาเริ่มต้นด้วยSETหรือBEGIN[ 11 ]
IBM DB2 LUW
IBM Db2 สำหรับLinux , UnixและWindows (Db2 สำหรับ LUW) รองรับทริกเกอร์หลักสามประเภทที่จำแนกตามเวลาการเปิดใช้งาน ได้แก่BEFORE, AFTER, และINSTEAD OFเอนจินรองรับทั้งความละเอียดระดับแถวและระดับคำสั่ง หากมีการกำหนดทริกเกอร์หลายตัวสำหรับการดำเนินการเดียวกันบนตารางเดียว ลำดับการดำเนินการจะถูกกำหนดตามลำดับโดยประทับเวลาการสร้าง ตั้งแต่เวอร์ชัน 9.7 เป็นต้นไป Db2 ยังรองรับธุรกรรมอิสระ ทำให้ทริกเกอร์สามารถดำเนินการธุรกรรมอิสระที่สามารถยืนยันหรือยกเลิกได้โดยไม่ส่งผลกระทบต่อคำสั่งที่ทำให้เกิดทริกเกอร์[ 12 ]
ทBEFOREริกเกอร์ใช้เพื่อตรวจสอบความถูกต้องของข้อมูลที่เข้ามาและพิจารณาว่าควรอนุญาตให้มีการแก้ไขข้อมูลหรือไม่ หากเกิดข้อยกเว้นภายในBEFOREทริกเกอร์ การดำเนินการจะถูกยกเลิกและการเปลี่ยนแปลงในฐานข้อมูลจะถูกย้อนกลับ แม้ว่าBEFOREทริกเกอร์จะไม่สามารถดำเนินการคำสั่ง DML เพื่อแก้ไขตารางฐานข้อมูลโดยตรงได้ แต่ก็ไม่ได้เป็นแบบอ่านอย่างเดียวโดยสมบูรณ์ ทริกเกอร์สามารถแก้ไขสถานะข้อมูลที่เข้ามาได้โดยใช้โปรแกรม โดยการเปลี่ยนแปลงค่าเป้าหมายภายในตัวแปรการเปลี่ยนผ่านของแถวก่อนที่จะเขียนลงดิสก์[ 13 ]
ในทางกลับกันAFTERทริกเกอร์จะทำงานหลังจากที่การแก้ไขข้อมูลที่ร้องขอเสร็จสมบูรณ์ แตกต่างจากBEFOREทริกเกอร์ทั่วไปAFTERทริกเกอร์สามารถดำเนินการเขียนข้อมูลแบบ DML ต่อไปได้ในตารางฐานข้อมูลใดๆ รวมถึงตารางที่ใช้งานอยู่ซึ่งเป็นตัวเริ่มต้นการทำงานของทริกเกอร์ ทINSTEAD OFริกเกอร์ใช้กับวิวโดยเฉพาะเพื่อแทนที่ตรรกะการประมวลผลเริ่มต้นและทำให้วิวที่ไม่สามารถอัปเดตได้สามารถเขียนได้ ตรรกะเชิงกระบวนการภายในทริกเกอร์ของ Db2 มักเขียนโดยใช้ส่วนขยายภาษาเชิงกระบวนการSQL PL
ฐานข้อมูล SQLite
สร้างทริกเกอร์[ ชั่วคราว| ชั่วคราว] [ ถ้ายังไม่มีอยู่] [ ชื่อฐานข้อมูล.] ชื่อทริกเกอร์[ ก่อน| หลัง| แทนที่] { ลบ| แทรก| อัปเดต[ ของชื่อคอลัมน์[, ชื่อคอลัมน์]...] } บน{ ชื่อตาราง| ชื่อวิว} [ สำหรับแต่ละแถว] [ เมื่อเงื่อนไข] เริ่มต้น... สิ้นสุดSQLiteรองรับเฉพาะทริกเกอร์ระดับแถวเท่านั้น และไม่มีระบบรองรับทริกเกอร์ระดับคำสั่งโดยตรง
มุมมองที่สามารถอัปเดตได้ ซึ่งโดยปกติแล้วเอนจินจะไม่รองรับนั้น สามารถจำลองได้โดยการใช้INSTEAD OFทริกเกอร์กับโครงสร้างมุมมองเป้าหมาย
ฐานข้อมูล XML
ทริกเกอร์ถูกนำไปใช้ในระบบจัดการฐานข้อมูลที่ไม่ใช่เชิงสัมพันธ์ ตัวอย่างเช่น ฐานข้อมูล XML อย่าง Sednaรองรับทริกเกอร์ที่ใช้XQueryทริกเกอร์ใน Sedna ถูกออกแบบมาให้เลียนแบบพฤติกรรมเชิงโครงสร้างของทริกเกอร์มาตรฐานSQL:2003แต่ได้รับการปรับแต่งให้เหมาะสมกับรูปแบบการสืบค้นและอัปเดต XML โดยเฉพาะ รวมถึงXPath , XQueryและส่วนขยายการอัปเดต XML
ใน Sedna สามารถกำหนดทริกเกอร์ให้กับโหนดใดๆ ภายในเอกสาร XML ที่จัดเก็บอยู่ในฐานข้อมูลได้ เมื่อโหนดเป้าหมายเหล่านี้ได้รับการแก้ไข ทริกเกอร์จะเรียกใช้คำสั่ง XQuery หรือสคริปต์การอัปเดตที่เกี่ยวข้องโดยอัตโนมัติ ซึ่งกำหนดไว้ในส่วนเนื้อหาของทริกเกอร์ ตัวอย่างเช่น ทริกเกอร์ต่อไปนี้จะบล็อกการลบโหนดpersonหากยังมีรายการประมูลที่เปิดอยู่ซึ่งอ้างอิงถึงโปรไฟล์นั้นๆ:
สร้างทริกเกอร์"trigger3" ก่อนลบในdoc( "auction" )/ site // person สำหรับแต่ละโหนดทำซ้ำ{ ถ้ามีอยู่( $ WHERE // open_auction / bidder / personref / @person = $ OLD / @id )) แล้ว( ) มิฉะนั้น$ OLD ; }ทริกเกอร์ฐานข้อมูล MongoDB
ในMongoDB Atlas ทริกเกอร์ถูกนำมาใช้เป็นส่วนหนึ่งของสถาปัตยกรรมแบบไร้เซิร์ฟเวอร์และขับเคลื่อนด้วยเหตุการณ์ เพื่อดำเนินการตรรกะฝั่งเซิร์ฟเวอร์อัตโนมัติเมื่อมีการเปลี่ยนแปลงข้อมูล แตกต่างจากทริกเกอร์ฐานข้อมูลแบบดั้งเดิมซึ่งทำงานโดยตรงบนเซิร์ฟเวอร์ฐานข้อมูล ทริกเกอร์ฐานข้อมูลของ MongoDB Atlas ทำงานบนเลเยอร์การประมวลผลที่ปรับขนาดได้อย่างอิสระ โดยจะตรวจสอบการแก้ไขข้อมูลแบบเรียลไทม์ ( INSERT, UPDATE, REPLACE, หรือDELETE) โดยใช้Change Streams[ 14 ] เมื่อตรวจพบเหตุการณ์ ทริกเกอร์จะเรียกใช้ฟังก์ชัน Atlas แบบกำหนดเอง (เขียนด้วย JavaScript) โดยอัตโนมัติ หรือส่งเหตุการณ์ไปยังบริการภายนอก ฟังก์ชันนี้ใช้เป็นหลักในการบังคับใช้ความสอดคล้องของข้อมูลและความสมบูรณ์ของข้อมูล และเพื่อดำเนินการตรวจสอบโดยอัตโนมัติทั่วทั้งระบบนิเวศข้อมูล
ร้านค้าออนไลน์ที่ติดตามการจัดส่งพัสดุอาจใช้ทริกเกอร์ในฐานข้อมูลเพื่อแจ้งเตือนลูกค้าเมื่อใดก็ตามที่พัสดุของพวกเขาเปลี่ยนสถานที่ ทริกเกอร์จะตรวจสอบการเปลี่ยนแปลงข้อมูลภายในstore.ordersชุดข้อมูล ซึ่งคำสั่งซื้อที่ใช้งานอยู่แต่ละรายการจะถูกจัดเก็บเป็นเอกสารที่มีโครงสร้างดังตัวอย่างต่อไปนี้:
{ _id : Object Id( " 59cf1860a95168b8f685e378" ) , customerId : Object Id ( "59cf17e1a95168b8f685e377" ) , orderDate : ISODate ( " 2018-06-26T16 :20:42.313Z" ) , shipDate : ISODate ( "2018-06-27T08:20:23.311Z" ) , orderContents : [ { qty : 1 , name : " Earl Grey Tea Bags - 100ct " , price : NumberDecimal ( " 10.99 " ) } ] , shippingLocatio } n : [ { location : " Memphis " , time : ISODate ( " 2018-06-27T18 : 22:33.243Z" ) }, ] }สถาปัตยกรรมและการก่อสร้าง
ระดับความละเอียดและจังหวะเวลาในการดำเนินการ
เพื่อให้เข้าใจวิธีการทำงานของทริกเกอร์ในฐานข้อมูล จำเป็นต้องพิจารณาสองแนวคิดหลัก ได้แก่ระดับความละเอียด ของทริกเกอร์ (ระดับแถวเทียบกับระดับคำสั่ง) และเวลาในการดำเนินการ (ก่อนเทียบกับหลัง) การตั้งค่าเหล่านี้จะกำหนดว่าทริกเกอร์จะทำงานกี่ครั้งและโค้ดของทริกเกอร์จะทำงานเมื่อใด
ระดับแถวเทียบกับระดับคำสั่ง
ความแตกต่างหลักระหว่างทริกเกอร์ทั้งสองประเภทนี้อยู่ที่ความถี่ในการทำงานเมื่อมีการเปลี่ยนแปลงข้อมูล:
- ทริกเกอร์ระดับแถวจะทำงานหนึ่งครั้งสำหรับทุกแถวที่ได้รับผลกระทบจากคำสั่งฐานข้อมูล เช่น คำสั่ง
INSERT`print`UPDATE, `print` หรือDELETE`print` ตัวอย่างเช่น หากUPDATEคำสั่งเปลี่ยนแปลง 50 แถวในตาราง ทริกเกอร์ระดับแถวจะทำงาน 50 ครั้ง หากคำสั่งไม่ตรงกับแถวใด ๆ และไม่เปลี่ยนแปลงอะไรเลย ทริกเกอร์ระดับแถวจะไม่ทำงานเลย - ทริกเกอร์ระดับคำสั่งจะทำงานเพียงครั้งเดียวสำหรับคำสั่ง SQL ทั้งหมด โดยไม่คำนึงถึงจำนวนแถวที่เปลี่ยนแปลง แม้ว่าคำสั่งฐานข้อมูลจะไม่มีผลกระทบต่อแถวใด ๆ เลยก็ตาม ทริกเกอร์ระดับคำสั่งก็จะยังคงเรียกใช้โค้ดของมันหนึ่งครั้ง
ระดับความละเอียดของการเรียกใช้ทริกเกอร์จะแตกต่างกันไปตามเอนจิ้น โดยระบบอย่าง PostgreSQL ใช้FOR EACH ROWทริกเกอร์ระดับแถว ในขณะที่ Microsoft SQL Server ใช้ทริกเกอร์ระดับคำสั่งเป็นค่าเริ่มต้น และต้องจัดการแถวผ่านตารางเสมือน นักพัฒนาต้องหลีกเลี่ยงการเรียก ใช้ทริกเกอร์ ซ้ำซ้อน ซึ่งทริกเกอร์จะอัปเดตตารางแล้วเรียกใช้ตัวเองอีก ทำให้เกิดลูปไม่สิ้นสุดและอาจทำให้ฐานข้อมูลล่มได้
ก่อนและหลัง
ตัวเลือกด้านเวลา ซึ่งระบุโดยใช้ คำหลัก BEFOREและAFTERจะกำหนดว่าทริกเกอร์จะทำงานเมื่อใดเมื่อเทียบกับการแก้ไขข้อมูล:
BEFOREทริกเกอร์จะทำงานก่อนที่การเปลี่ยนแปลงข้อมูลจะถูกบันทึกอย่างถาวรลงในตาราง การใช้งานทBEFOREริกเกอร์ที่พบบ่อยคือการตรวจสอบความถูกต้องของข้อมูลขาเข้าหรือการตรวจสอบความปลอดภัย ตัวอย่างเช่นBEFOREทริกเกอร์สามารถตรวจสอบระเบียนที่เข้ามาและแก้ไขค่าที่ไม่ถูกต้องหรือหยุดการทำงานทั้งหมดก่อนที่จะเขียนข้อมูลใดๆ ลงดิสก์AFTERทริกเกอร์จะเรียกใช้โค้ดหลังจากที่การเปลี่ยนแปลงข้อมูลได้รับการเขียนลงในตารางอย่างปลอดภัยแล้ว โดยทั่วไปทริกเกอร์เหล่านี้จะใช้สำหรับงานประมวลผลภายหลัง เช่น การบันทึกข้อมูลประวัติหรือการสร้างบันทึกการตรวจสอบ ในขณะที่BEFOREทริกเกอร์เหมาะที่สุดสำหรับการตรวจสอบและทำความสะอาดข้อมูลที่เข้ามาAFTERทริกเกอร์เหมาะอย่างยิ่งสำหรับการคัดลอกการเปลี่ยนแปลงที่ได้รับการยืนยันไปยังตารางประวัติหรือตารางบันทึกแยกต่างหาก[ 15 ]
ตัวอย่างการใช้งาน (Oracle PL/SQL)
ตัวอย่างต่อไปนี้แสดงทริกเกอร์ระดับแถวของ Oracle PL/SQL ที่กำหนดค่าให้ทำงานหลังจากUPDATEดำเนินการกับตารางชื่อ `<table>` phone_bookทริกเกอร์นี้จะบันทึกการเปลี่ยนแปลงในอดีตโดยอัตโนมัติโดยการเขียนรายการบันทึกไปยังตารางติดตามแยกต่างหากชื่อ `<table>` phone_book_auditนอกจากนี้ยังใช้ลำดับฐานข้อมูลชื่อ `<table>` audit_id_sequenceเพื่อสร้างหมายเลข ID ที่ไม่ซ้ำกันสำหรับรายการบันทึกใหม่แต่ละรายการ:
สร้างหรือแทนที่ทริกเกอร์phone_book_audit หลังจากอัปเดตในตาราง phone_book สำหรับแต่ละแถวเริ่มต้นแทรกข้อมูลลงในphone_book_audit ( audit_id , audit_change , audit_l_name , audit_f_name , audit_old_phone_number , audit_new_phone_number , audit_date ) ด้วยค่า( audit_id_sequence . nextVal , 'Update' , : OLD . last_name , : OLD . first_name , : OLD . phone_number , : NEW . phone_number , SYSDATE ); สิ้นสุด;คำUPDATEสั่งที่ดำเนินการกับphone_bookตารางจะแก้ไขระเบียนที่มีนามสกุล "Jones":
อัปเดต สมุด โทรศัพท์ตั้งค่าหมายเลขโทรศัพท์เป็น'111-111-1111' โดยที่นามสกุลเท่ากับ'Jones' ;| รหัสตรวจสอบ | การตรวจสอบการเปลี่ยนแปลง | ชื่อการตรวจสอบ L_ | ชื่อการตรวจสอบ F | ตรวจสอบหมายเลขโทรศัพท์เก่า | ตรวจสอบหมายเลขโทรศัพท์ใหม่ | วันที่ตรวจสอบ |
|---|---|---|---|---|---|---|
| 1 | อัปเดต | โจนส์ | จอร์แดน | 098-765-4321 | 111-111-1111 | 02-พฤษภาคม-14 |
| 2 | อัปเดต | โจนส์ | เมแกน | 111-222-3456 | 111-111-1111 | 02-พฤษภาคม-14 |
ตาราง ผลลัพธ์phone_book_auditจะมีรายการที่แตกต่างกันสองรายการ เนื่องจากฐานข้อมูลต้นทางมีระเบียนสองรายการที่ตรงกับนามสกุล "Jones" เนื่องจากทริกเกอร์ระดับแถวจะทำงานหนึ่งครั้งสำหรับแต่ละแถวที่แก้ไข เอ็นจิ้นจึงเรียกใช้ตรรกะทริกเกอร์สองครั้งในระหว่างการดำเนินการคำสั่งอัปเดตเดียว[ 16 ]
หลังจากทริกเกอร์ระดับคำสั่ง
ในทางกลับกันAFTERทริกเกอร์ระดับคำสั่งจะทำงานเพียงครั้งเดียวต่อการดำเนินการคำสั่งเสร็จสิ้นแต่ละครั้ง โดยไม่คำนึงถึงจำนวนแถวทั้งหมดที่ถูกแก้ไขโดยคำสั่งนั้น ไวยากรณ์ของ Oracle ต่อไปนี้กำหนดทริกเกอร์ระดับคำสั่งที่บันทึกเหตุการณ์ธุรกรรมเดียวภายในphone_book_edit_historyตารางทุกครั้งที่UPDATEมีการดำเนินการเกิดขึ้นกับphone_bookตาราง:
สร้างหรือแทนที่ทริกเกอร์phone_book_history หลังจากอัปเดตในphone_book โดยเริ่ม ต้น ด้วยการแทรกข้อมูลลงในphone_book_edit_history ( audit_history_id , username , modification , edit_date ) ด้วยค่า( audit_history_id_sequence . nextVal , USER , 'Update' , SYSDATE ); สิ้นสุด; การดำเนินการตามคำสั่งเดียวกันUPDATEจะแยกความแตกต่างด้านพฤติกรรมของตัวกระตุ้นระดับคำสั่ง:
อัปเดต สมุด โทรศัพท์ตั้งค่าหมายเลขโทรศัพท์เป็น'111-111-1111' โดยที่นามสกุลเท่ากับ'Jones' ;| รหัสประวัติการตรวจสอบ | ชื่อผู้ใช้ | การแก้ไข | วันที่แก้ไข |
|---|---|---|---|
| 1 | บอนยอร์ | อัปเดต | 02-พฤษภาคม-14 |
บันทึกธุรกรรมระบุว่าทริกเกอร์ทำงานเพียงครั้งเดียวเท่านั้น แม้ว่าการแก้ไขข้อมูลจะส่งผลกระทบต่อข้อมูลสองรายการแยกกันก็ตาม
ก่อนทริกเกอร์ระดับแถวพร้อมการกรองแบบมีเงื่อนไข
ทBEFOREริกเกอร์ระดับแถวจะประเมินและเปลี่ยนแปลงค่าข้อมูลที่เข้ามา ก่อนที่การดำเนินการเขียนทางกายภาพจะเสร็จสมบูรณ์บนดิสก์ รูปแบบนี้แสดงให้เห็นถึงทริกเกอร์ที่ใช้WHENข้อจำกัดของข้อความเพื่อดักจับINSERTการกระทำ เมื่อเรคอร์ดมีสตริงนามสกุลที่มีความยาวเกิน 10 ตัวอักษร เอ็นจิ้นจะเรียกใช้SUBSTRฟังก์ชัน[ 17 ]เพื่อตัดค่าอินพุตให้เหลือเพียงอักขระตัวแรก: [ 18 ]
สร้างหรือแทนที่ทริกเกอร์phone_book_insert ก่อนแทรกข้อมูลลงในตารางphone_book สำหรับแต่ละแถวเมื่อความยาวของนามสกุลใหม่มากกว่า10 ให้เริ่มต้นที่: นามสกุลใหม่: = ลบนามสกุลใหม่ด้วยค่า0 และ1กลไกนี้จะสังเกตได้เมื่อพยายามแทรกข้อมูลที่ตรงตามเกณฑ์การกรอง:
INSERT INTO phone_book VALUES ( 6 , 'VeryVeryLongLastName' , 'Erin' , 'Minneapolis' , 'MN' , '989 University Drive' , '123-222-4456' , 55408 , TO_DATE ( '11/21/1991' , 'MM/DD/YYYY' ));| รหัสบุคคล | นามสกุล | ชื่อจริง | เมือง | ตัวย่อของรัฐ | ที่อยู่ | หมายเลขโทรศัพท์ | รหัสไปรษณีย์ | วันเกิด |
|---|---|---|---|---|---|---|---|---|
| 6 | วี | เอริน | มินนิอาโพลิส | MN | 989 ถนนยูนิเวอร์ซิตี้ไดรฟ์ | 123-222-4456 | 55408 | 21 พ.ย. 91 |
เอนจินจะยืนยันข้อมูลแถวที่มีตัวแปรนามสกุลที่ถูกตัดทอน เพื่อยืนยันว่าการแก้ไขเกิดขึ้นก่อนที่จะเขียนระเบียนลงในตาราง
ก่อนที่จะเกิดทริกเกอร์ระดับคำสั่งและการยกเว้น
การใช้งานBEFOREทริกเกอร์ระดับคำสั่งเป็นรูปแบบการออกแบบมาตรฐานสำหรับการบังคับใช้พารามิเตอร์ความปลอดภัยหรือข้อจำกัดกฎทางธุรกิจทั่วโลกในทรัพยากรฐานข้อมูล[ 19 ]คำจำกัดความต่อไปนี้จำกัดการเข้าถึงฐานข้อมูลบนตารางเป้าหมายภายใต้สคีมาเฉพาะ:
CREATE OR REPLACE TRIGGER hauschbc BEFORE INSERT ON SOMEUSER . phone_book BEGIN RAISE_APPLICATION_ERROR ( num => - 20050 , msg => 'ข้อความแสดงข้อผิดพลาดอยู่ที่นี่' ); END ;การพยายามแทรกข้อมูลไปยังทรัพยากรที่ได้รับการป้องกันจะทำให้เอนจินฐานข้อมูลยกเลิกกระบวนการและส่งข้อความแสดงข้อผิดพลาดกลับไปยังอินเทอร์เฟซแอปพลิเคชันไคลเอ็นต์ที่เรียกใช้งาน:
ข้อผิดพลาด SQL: ORA-20050: ข้อความแสดงข้อผิดพลาดอยู่ที่นี่
ข้อยกเว้นรันไทม์ที่กำหนดเองซึ่งเกิดขึ้นผ่านRAISE_APPLICATION_ERRORโปรโตคอลนั้นอยู่ภายใต้ช่วงตัวเลขที่จำกัด เพื่อหลีกเลี่ยงความขัดแย้งกับรหัสข้อผิดพลาดของระบบที่กำหนดไว้ล่วงหน้า นักพัฒนาแอปพลิเคชันต้องกำหนดตัวแปรนี้ภายในขอบเขตตัวเลขระหว่าง -20000 ถึง -20999
ลิงก์ภายนอก
- Microsoft SQL Server DROP TRIGGER
- ทริกเกอร์ฐานข้อมูล MySQL
- สร้างทริกเกอร์ในฐานข้อมูล MySQL
- คำสั่ง DB2 CREATE TRIGGER
- Oracle สร้างทริกเกอร์
- PostgreSQL สร้างทริกเกอร์
- ปัญหาการแก้ไขตารางใน Oracle เมื่อใช้คำสั่ง DELETE CASCADE
- ภาษาการสืบค้น SQLite: สร้างทริกเกอร์
- เอกสารของ Oracle เกี่ยวกับทริกเกอร์