SQL Server: Yalnızca geçerli oturumunuz için bir güncelleştirme için tetikleyici nasıl devre dışı bırakılır?


15

SQL Server 2008 R2 üzerinde çalışıyorum.

Tiu_benefit adlı bir SONRASI INSERT, UPDATE tetikleyicisi olan bir tablo faydası var .

1 Satır güncelleştirmek için bu tablo için bir UPDATE deyimi yazmak istiyorum ama tetik tetiklemek istemiyorum. UPDATE öncesi tetikleyiciyi devre dışı bırakabileceğimi ve sonra UPDATE sonrası tetikleyiciyi etkinleştirebileceğimi biliyorum:

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

Ancak bu devre dışı bırakma ve etkinleştirme tetikleyicisi, şu anda oturum açmış olan tüm kullanıcıları etkileyecektir. Bu nedenle, tetikleyici komut dosyam tarafından devre dışı bırakıldığında başka bir kullanıcının UPDATE / INSERT çalıştırması olasılığı vardır, bu da iyi değildir. Bu yüzden sadece geçerli oturumum için tetikleyiciyi devre dışı bırakmak ve etkinleştirmek istiyorum. Mümkün mü? Cevabınız evet ise, lütfen nasıl yapılacağını söyleyin.

Teşekkürler


1
Tetikleyicinizi değiştiremezseniz, cevap hayırdır.
jyao

Yanıtlar:


6

Bu konuda biraz test yaptım ve işleminizi tek bir işlemde çalıştırırsanız iyi olacağını düşünüyorum.

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 

Testlerimde sadece BEGIN TRANSACTIONve DISABLE TRIGGERilkini vurguladım ve uyguladım . Sonra yeni bir (ikinci) sorgu penceresini açtı ve çeşitli DML ifadeleri (kaçmayı denedi SELECT, INSERT, UPDATE DELETEbaz tabloya karşı). İkinci sorgu penceresindeki temel tabloya erişmek için yapılan tüm girişimler, açık işlemle pencere tarafından tutulan kilitleri bekledi. Açık işlemimi gerçekleştirdikten (veya geri aldıktan) sonra ikinci pencere tabloya erişebildi.


Bu işe yarayacaktır, ancak kilitler işlemi ne kadar süre açık tuttuğunuza bağlı olarak aşağı yönde istenmeyen sorunlara neden olabilir.
CaM

@CaM - OP'nin işlemi hızlı bir şekilde tamamladığını veya geri aldığını varsayarak bir satır güncellemesinin çok uzun sürmeyeceğini varsayıyorum. Umarım, bir endeks vardır benefit_id:)
Scott Hodgin

tetikte herhangi bir değişiklik yapmak zorunda olmadığım için gerçekten bu çözümü beğendim
srh

18

Sorununuzu çözmek için, soruna programlı bir yaklaşım izlemeliyiz. Buraya gidebileceğiniz iki rota var. Bu yaklaşımlara ihtiyaç duymanın nedeni, belirli bir ifade için tetikleyiciyi devre dışı bırakamamanızdır, yalnızca tablonun tamamı için devre dışı bırakılabilir.

1. Seçenek: Context_Info ()

MS SQL Tips'teki Samuel Vanga'nın harika bir örneği vardı:

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

Şimdi Samuel tetiğin yürütülmesini istemediğinde bunu kullanıyorlar:

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

Context_Info geçerli oturumla ilgili bilgileri almak için aşağıdaki sistem görünümlerini kullanır:

  • sys.dm_exec_requests

  • sys.dm_exec_sessions

  • sys.sysprocesses

Buradaki ideoloji, ayarladığınız ikili dizginin yalnızca geçerli oturuma maruz kalmasıdır, bu nedenle tetikleyici oturumunuz sırasında yürütüldüğünde, Context_infoişlevin kapsamını ve değişken ayarını görür ve tetikleyicinin çıkış bölümüne atlar. yerine.

Seçenek 2: Sıcaklık Tablosu

Itzik Ben-Gan bir sahiptir harika bir çözüm onun daha sonraki kitabında da: kitabında "T-SQL programlama İçinde Microsoft SQL Server 2008, T-SQL programlama" in T-SQL Sorgulama . Bu context_infoişlev üzerindeki birincil sorun , küçük TempDB yüküdür.

Sürprizi bozmak ama kitapların arsalarını mahvetmek için (satın almaya ve okumaya değer olduklarını hissettim), tetikleyicinizi değiştireceksiniz.

Tetikleyiciniz geçici bir tablo için bir kontrol gerçekleştirmelidir. Geçici tablo varsa, tetikleyici işlemi sonlandırmalı ve eylemleri gerçekleştirmemelidir.

Gerçekleştirmek istediğiniz güncelleme deyiminde, önce geçici tabloyu oluşturun. Tetikleyici ile aynı işlemde görülür ve tetikleyicinin ifadenizi yoksaymasına neden olur.

Tetikleyici örneği:

CREATE TRIGGER TRIGGERNAME ON TABLENAME for INSERT AS

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

Tetiğin çalışmasını istemediğinizde başlangıç ​​ifadesine örnek:

CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);

Örneğiniz için bir araya getirmek:

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
Tetikleyicide geçici tablo yerine context_info () kullanırdım. Başka bir deyişle, bir tetikleyici context_info'nun belirli bir değer döndürdüğünü algılarsa, tetikleyici buna göre çalışır. İlgili SO sorusuna buradan başvurabilirsiniz: stackoverflow.com/questions/3025662/…
jyao

1
Ayrıca, belirli bir kişi tetikleyiciye isabet ederse tetiğe asla çalışmamasını söylemek için context_infokullanmaya benzer bir kontrol yapabilirsiniz original_login().
Kenneth Fisher

2

İkisinden birini CONTEXT_INFOveya daha yenisini kullanırdım SESSION_CONTEXT. Her ikisi de oturuma dayalı değerlerdir.

  • CONTEXT_INFOtek bir VARBINARY(128)değerdir. Bu, en azından SQL Server 2000'den beri mevcuttur . DMV tarafından döndürülen bir alan olduğu için CONTEXT_INFOherkes tarafından görüntülenebilir . Bunu daha önce kullandım ve oldukça iyi çalışıyor.VIEW SERVER STATEsys.dm_exec_sessions

    Aracılığıyla Set SET CONTEXT_INFO
    yoluyla alın CONTEXT_INFO () veya sys.dm_exec_sessions

    Sakladığınız değerin türüne bağlı olarak, CONTEXT_INFOfarkında olmanız gereken bazı nüanslar vardır. Bunu aşağıdaki blog yazısında ele aldım:

    CONTEXT_INFO () neden SET CONTEXT_INFO tarafından ayarlanan Tam Değeri döndürmüyor?

  • Session_context anahtar / değer çiftidir SQL_VARIANT. Bu SQL Server 2016'da tanıtıldı. Farklı amaçlar için değerlerin ayrılması oldukça güzel. Session_context yalnızca geçerli oturum tarafından görüntülenebilir.

    Bu değeri sp_set_session_context ile ayarlayın Bu değeri SESSION_CONTEXT ile
    alın

Yerel geçici tablo seçeneği ve hatta Devre Dışı Bırak / Etkinleştir seçeneği ile ilgili dikkate alınması gereken bir şey: her ikisi de bir miktar kilitleme ve tran log etkinliği gerektirir. Bu seçeneklerin her ikisi de asgari düzeyde olsa bile çekişme potansiyelini arttırır. İki "bağlam" seçeneği daha hafif / yalnızca bellek olmalıdır.


context_info bir ağrı kesici, bir üretim veri değişikliği çalıştırmak istediğinizde bu kullanışlı olur, özellikle tetiğin devre dışı bırakılması diğer işlemlerin tetikleyiciyi ateşlememesine neden olabilir.
Biju jose
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.