SQL Server: วิธีการปิดการใช้งานทริกเกอร์สำหรับการปรับปรุงสำหรับเซสชั่นปัจจุบันของคุณเท่านั้น?


15

ฉันกำลังทำงานกับ SQL Server 2008 R2

ผมมีตารางผลประโยชน์ที่มีหลัง INSERT, UPDATE ทริกเกอร์ชื่อtiu_benefit

ฉันต้องการเขียนคำสั่ง UPDATE สำหรับตารางนี้เพื่ออัปเดต 1 แถว แต่ฉันไม่ต้องการให้ทริกเกอร์เริ่มทำงาน ฉันรู้ว่าฉันสามารถปิดการใช้งานทริกเกอร์ก่อน UPDATE แล้วเปิดใช้ทริกเกอร์หลัง UPDATE:

DISABLE TRIGGER tiu_benefit ON benefit;  
GO  
UPDATE benefit SET editor = 'srh' where benefit_id = 9876
GO
ENABLE TRIGGER tiu_benefit ON benefit;  
GO  

แต่สิ่งนี้จะปิดการใช้งานและเปิดใช้งานทริกเกอร์จะส่งผลกระทบต่อผู้ใช้ทั้งหมดที่เข้าสู่ระบบในปัจจุบัน ดังนั้นจึงมีความเป็นไปได้ที่ผู้ใช้รายอื่นเรียกใช้ UPDATE / INSERT ในขณะที่ทริกเกอร์ถูกปิดใช้งานโดยสคริปต์ของฉันซึ่งไม่ดี นั่นเป็นเหตุผลที่ฉันต้องการปิดใช้งานและเปิดใช้งานทริกเกอร์สำหรับเซสชันปัจจุบันของฉันเท่านั้น เป็นไปได้ไหม? ถ้าใช่โปรดบอกว่า

ขอบคุณ


1
หากคุณไม่สามารถแก้ไขทริกเกอร์ได้คำตอบคือไม่
jyao

คำตอบ:


6

ฉันทำการทดสอบนี้และฉันคิดว่าคุณจะสบายดีถ้าคุณใช้กระบวนการของคุณในการทำธุรกรรมเดียว

BEGIN TRANSACTION
GO

DISABLE TRIGGER tiu_benefit ON benefit;
GO

UPDATE benefit
SET editor = 'srh'
WHERE benefit_id = 9876
GO

ENABLE TRIGGER tiu_benefit ON benefit;
GO

--Decide to commit or rollback

--commit
--rollback 

ในการทดสอบของฉันฉันเพียงเน้นและดำเนินการBEGIN TRANSACTIONและDISABLE TRIGGERครั้งแรก จากนั้นผมก็เปิดขึ้นใหม่ (ที่สอง) หน้าต่างแบบสอบถามและพยายามที่จะเรียกใช้คำสั่ง DML ต่างๆ ( SELECT, INSERT, UPDATE DELETE) กับตารางฐาน ความพยายามทั้งหมดในการเข้าถึงตารางฐานในหน้าต่างคิวรีที่สองรอการล็อกที่เก็บโดยหน้าต่างด้วยธุรกรรมที่ชัดเจน เมื่อฉันยืนยัน (หรือย้อนกลับ) ธุรกรรมที่ชัดเจนของฉันหน้าต่างที่สองก็สามารถเข้าถึงตารางได้


สิ่งนี้จะใช้งานได้ แต่การล็อกอาจทำให้เกิดปัญหาที่ไม่ได้ตั้งใจดาวน์สตรีมขึ้นอยู่กับระยะเวลาที่คุณเปิดธุรกรรม
CaM

@CaM - ฉันจะสมมติว่าการอัปเดตหนึ่งแถวนั้นใช้เวลาไม่นานนักสมมติว่า OP ยอมรับหรือย้อนกลับธุรกรรมอย่างรวดเร็ว หวังว่าจะมีดัชนีในbenefit_id:)
สกอตต์ Hodgin

จริงๆชอบการแก้ปัญหานี้เป็นฉันไม่จำเป็นต้องทำการเปลี่ยนแปลงใด ๆ ที่จะเรียก
SRH

18

เพื่อแก้ปัญหาของคุณเราต้องใช้วิธีการเขียนโปรแกรมเพื่อแก้ไขปัญหา มีสองเส้นทางที่คุณสามารถไปที่นี่ได้ เหตุผลที่ต้องใช้วิธีการเหล่านี้เนื่องจากคุณไม่สามารถปิดการใช้งานทริกเกอร์สำหรับคำสั่งเฉพาะมันสามารถถูกปิดการใช้งานสำหรับตารางทั้งหมดเท่านั้น

ตัวเลือก 1: Context_Info ()

Samuel Vanga บน MS SQL Tipsเป็นตัวอย่างที่ดี:

USE AdventureWorks; 
GO 
-- creating the table in AdventureWorks database 
IF OBJECT_ID('dbo.Table1') IS NOT NULL 
DROP TABLE dbo.Table1 
GO 
CREATE TABLE dbo.Table1(ID INT) 
GO 
-- Creating a trigger 
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE 
AS 
DECLARE @Cinfo VARBINARY(128) 
SELECT @Cinfo = Context_Info() 
IF @Cinfo = 0x55555 
RETURN 
PRINT 'Trigger Executed' 
-- Actual code goes here 
-- For simplicity, I did not include any code 
GO

ตอนนี้เมื่อซามูเอลไม่ต้องการให้ตัวกระตุ้นดำเนินการพวกเขาใช้สิ่งนี้:

SET Context_Info 0x55555 
INSERT dbo.Table1 VALUES(100)

Context_Info ใช้มุมมองระบบต่อไปนี้เพื่อดึงข้อมูลเกี่ยวกับเซสชันปัจจุบัน:

  • sys.dm_exec_requests

  • sys.dm_exec_sessions

  • sys.sysprocesses

อุดมการณ์ที่นี่คือสตริงไบนารีที่คุณตั้งค่าจะเปิดเผยเฉพาะกับเซสชันปัจจุบันดังนั้นเมื่อทริกเกอร์ดำเนินการในระหว่างเซสชันของคุณก็จะเห็นขอบเขตและการตั้งค่าตัวแปรของContext_infoฟังก์ชั่นและมันจะข้ามไปยังส่วนหลบหนีของทริกเกอร์ แทน.

ตัวเลือกที่ 2: ตารางชั่วคราว

itzik เบนกานมีทางออกที่ดีในหนังสือของเขา "ภายใน Microsoft SQL Server 2008 การเขียนโปรแกรม T-SQL: T-SQL Programming" ซึ่งยังอยู่ในหนังสือของเขาในภายหลังT-SQL สอบถาม ปัญหาหลักของการใช้context_infoฟังก์ชันนี้คือโอเวอร์เฮด TempDB เล็กน้อย

เพื่อทำให้ประหลาดใจ แต่ไม่ทำลายเนื้อเรื่องของหนังสือ (ฉันรู้สึกว่ามันคุ้มค่าที่จะซื้อและอ่าน) คุณจะเปลี่ยนทริกเกอร์ของคุณ

ทริกเกอร์ของคุณควรทำการตรวจสอบตารางชั่วคราว หากมีตารางชั่วคราวทริกเกอร์ควรรู้ที่จะสิ้นสุดและไม่ดำเนินการใด ๆ

ในคำสั่งปรับปรุงที่คุณต้องการดำเนินการให้สร้างตารางชั่วคราวก่อน มันจะเห็นในการทำธุรกรรมเช่นเดียวกับทริกเกอร์และจะทำให้ทริกเกอร์ที่จะละเว้นคำสั่งของคุณ

ตัวอย่างของทริกเกอร์:

CREATE TRIGGER TRIGGERNAME ON TABLENAME for INSERT AS

IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
GO

ตัวอย่างของข้อความเริ่มต้นเมื่อคุณไม่ต้องการให้ทริกเกอร์เรียกใช้:

CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);

วางไว้ทั้งหมดสำหรับตัวอย่างของคุณ:

ALTER TRIGGER tiu_benefit ON benefit FOR 
... 
AS
...
IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
--... rest of code here
GO

CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);
UPDATE benefit SET editor = 'srh' where benefit_id = 9876;
GO

2
ฉันจะใช้ context_info () แทนตาราง temp ในทริกเกอร์ กล่าวอีกนัยหนึ่งถ้าทริกเกอร์ตรวจพบ context_info จะส่งกลับค่าเฉพาะทริกเกอร์จะทำงานตามนั้น คุณสามารถอ้างอิงคำถาม SO ที่เกี่ยวข้องได้ที่นี่: stackoverflow.com/questions/3025662/…
jyao

1
นอกจากนี้คุณยังสามารถใส่เช็คที่คล้ายกับการcontext_infoใช้original_login()เพื่อบอกทริกเกอร์ว่าจะไม่ทำงานหากบุคคลใดบุคคลหนึ่งกดปุ่มทริกเกอร์
Kenneth Fisher

2

ผมจะใช้อย่างใดอย่างหนึ่งหรือใหม่กว่าCONTEXT_INFO SESSION_CONTEXTทั้งสองเป็นค่าตามเซสชัน

  • CONTEXT_INFOเป็นVARBINARY(128)ค่าเดียว สิ่งนี้มีให้ตั้งแต่ SQL Server 2000 CONTEXT_INFOเป็นอย่างน้อยใคร ๆ ก็สามารถดูได้VIEW SERVER STATEเพราะเป็นฟิลด์ที่ส่งคืนโดยsys.dm_exec_sessionsDMV ฉันเคยใช้อันนี้มาก่อนและใช้งานได้ค่อนข้างดี

    ตั้งค่าผ่านSET CONTEXT_INFO รับ
    ผ่านCONTEXT_INFO ()หรือsys.dm_exec_sessions

    ขึ้นอยู่กับประเภทของค่าที่คุณเก็บไว้CONTEXT_INFOมีความแตกต่างบางอย่างที่ต้องระวัง ฉันพูดถึงเรื่องนี้ในบล็อกโพสต์ต่อไปนี้:

    เหตุใดจึงไม่ CONTEXT_INFO () ส่งคืนชุดค่าที่แน่นอนโดย SET CONTEXT_INFO

  • Session_context เป็นคู่ของSQL_VARIANTค่า/ คีย์ สิ่งนี้ถูกนำมาใช้ใน SQL Server 2016 การแยกค่าเพื่อวัตถุประสงค์ที่แตกต่างกันค่อนข้างดี Session_context สามารถดูได้โดยเซสชันปัจจุบันเท่านั้น

    ตั้งค่านี้ผ่านsp_set_session_context รับ
    ค่านี้ผ่านSESSION_CONTEXT

สิ่งหนึ่งที่ควรพิจารณาเกี่ยวกับตัวเลือกตารางชั่วคราวในพื้นที่และแม้กระทั่งตัวเลือกปิดการใช้งาน / เปิดใช้งานทริกเกอร์: ทั้งสองอย่างต้องการกิจกรรมล็อคและทรานบันทึกจำนวนหนึ่ง ตัวเลือกทั้งสองนั้นเพิ่มโอกาสในการแข่งขันแม้ว่าจะน้อยที่สุด ตัวเลือก "บริบท" สองรายการควรมีน้ำหนักเบากว่า / หน่วยความจำเท่านั้น


context_info เป็นตัวลดความเจ็บปวดเมื่อใดก็ตามที่คุณต้องการเรียกใช้การเปลี่ยนแปลงข้อมูลการผลิตสิ่งนี้มีประโยชน์โดยเฉพาะอย่างยิ่งการปิดใช้งานทริกเกอร์อาจทำให้การดำเนินการอื่นไม่ส่งสัญญาณทริกเกอร์
Biju jose
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.