2009-03-16 20 views
20

में कॉलम परिवर्तन का पता लगाने के लिए सबसे प्रभावी तरीका हमारी प्रणाली SQL Server 2000 पर चलती है, और हम SQL Server 2008 में अपग्रेड करने की तैयारी की प्रक्रिया में हैं। हमारे पास बहुत सारे ट्रिगर कोड हैं जहां हमें पहचानने की आवश्यकता है दिए गए कॉलम में बदलाव और फिर उस कॉलम पर काम करते हैं यदि यह बदल गया है।एमएस एसक्यूएल सर्वर

जाहिर है एसक्यूएल सर्वर UPDATE() और COLUMNS_UPDATED() कार्य प्रदान करता है, लेकिन इन कार्यों केवल आपको बता जो स्तंभ SQL विवरण में फंसाया गया है, जो कॉलम वास्तव में बदल दिया है नहीं

निर्धारित करने के लिए कौन से कॉलम को बदल दिया है, तो आप (एक स्तंभ है कि NULLs का समर्थन करता है के लिए) निम्न के समान कोड की जरूरत है:

IF UPDATE(Col1) 
    SELECT @col1_changed = COUNT(*) 
    FROM Inserted i 
     INNER JOIN Deleted d ON i.Table_ID = d.Table_ID 
    WHERE ISNULL(i.Col1, '<unique null value>') 
      != ISNULL(i.Col1, '<unique null value>') 

इस कोड को प्रत्येक स्तंभ आप परीक्षण में रुचि रखते हैं के लिए दोहराया जाना चाहिए। फिर आप यह निर्धारित करने के लिए 'बदले गए' मूल्य की जांच कर सकते हैं कि महंगा परिचालन करना है या नहीं। बेशक, यह कोड स्वयं समस्याग्रस्त है, क्योंकि यह केवल आपको बताता है कि कॉलम में कम से कम एक मूल्य संशोधित सभी पंक्तियों में बदल गया है।

आप कुछ इस तरह के साथ व्यक्तिगत अद्यतन बयान का परीक्षण कर सकते हैं:

UPDATE Table SET Col1 = CASE WHEN i.Col1 = d.Col1 
      THEN Col1 
      ELSE dbo.fnTransform(Col1) END 
FROM Inserted i 
    INNER JOIN Deleted d ON i.Table_ID = d.Table_ID 

... लेकिन यह अच्छी तरह से काम नहीं करता है जब आप एक संग्रहीत प्रक्रिया को लागू करने की आवश्यकता होगी, कर रहे हैं। उन मामलों में जहां तक ​​मैं कह सकता हूं, आपको अन्य दृष्टिकोणों पर वापस आना होगा।

मेरा प्रश्न यह है कि किसी के पास अंतर्दृष्टि (या बेहतर, अभी तक कठिन डेटा) है कि एक संशोधित पंक्ति में एक विशेष कॉलम मान पर ट्रिगर में डेटाबेस ऑपरेशन की भविष्यवाणी करने की समस्या के लिए सबसे अच्छा/सस्ता तरीका क्या है वास्तव में बदल गया है या नहीं। ऊपर दिए गए तरीकों में से कोई भी आदर्श प्रतीत नहीं होता है, और मैं सोच रहा था कि एक बेहतर विधि मौजूद है या नहीं।

+1

मैं इस पुराने सवाल है कि प्रासंगिक है के लिए एक नया जवाब जोड़ दिया है: http://stackoverflow.com/questions/1254787/sql-server-update-trigger -जेट-केवल-संशोधित-फ़ील्ड/8020461 # 8020461 –

+0

यह बहुत दिलचस्प है, हेड-अप के लिए धन्यवाद! – mwigdahl

उत्तर

7

हालांकि एचएलजीईएम ने ऊपर कुछ अच्छी सलाह दी है, यह बिल्कुल वही नहीं था जो मुझे चाहिए था। मैंने पिछले कुछ दिनों में काफी परीक्षण किया है, और मुझे लगा कि मैं कम से कम परिणाम यहां साझा करूंगा क्योंकि ऐसा लगता है कि कोई और जानकारी आगामी नहीं होगी।

मैंने एक टेबल स्थापित किया जो प्रभावी रूप से हमारे सिस्टम की प्राथमिक तालिकाओं में से एक का एक संक्षिप्त सबसेट (9 कॉलम) था, और इसे उत्पादन डेटा के साथ पॉप्युलेट किया गया ताकि यह तालिका के हमारे उत्पादन संस्करण के रूप में गहरा था।

मैंने फिर उस तालिका को डुप्लिकेट किया, और पहले व्यक्ति ने एक व्यक्तिगत ट्रिगर परिवर्तन का पता लगाने का प्रयास किया, और फिर प्रत्येक कॉलम अपडेट को भविष्यवाणी की कि उस कॉलम में डेटा वास्तव में बदल गया है या नहीं।

दूसरी तालिका के लिए, मैंने एक ट्रिगर लिखा जिसने एक ही कथन में सभी कॉलम के सभी अपडेट करने के लिए व्यापक सशर्त केस तर्क का उपयोग किया।

मैं तो 4 परीक्षण भागा:

  1. एक ही पंक्ति के लिए एक एकल-स्तंभ अद्यतन
  2. एक एकल-स्तंभ अद्यतन 10000 पंक्तियों
  3. एक ही पंक्ति के लिए एक नौ स्तंभ अद्यतन
  4. एक नौ स्तंभ अद्यतन 10000 पंक्तियों

मैं टेबल के दोनों अनुक्रमित और गैर सूचीबद्ध संस्करणों के लिए इस परीक्षा में बार-बार, और फिर दोहराया वें एसक्यूएल 2000 और एसक्यूएल 2008 सर्वर पर पूरी बात है।

परिणाम मुझे मिल गया काफी दिलचस्प थे:

दूसरी विधि (सेट खंड में बालों मामला तर्क के साथ एक ही अद्यतन बयान) समान रूप से अलग-अलग परिवर्तन का पता लगाने की तुलना में बेहतर प्रदर्शन करने वाले की गई थी (एक अधिक से अधिक या कम हद तक परीक्षण के आधार पर) एकल कॉलम परिवर्तन के एकल अपवाद के साथ, कॉलम को अनुक्रमित किया गया था, जहां कई पंक्तियों को प्रभावित किया गया था, SQL 2000 पर चल रहा है। हमारे विशेष मामले में हम इस तरह के कई संकीर्ण, गहरे अपडेट नहीं करते हैं, इसलिए मेरे उद्देश्यों के लिए एकल-कथन दृष्टिकोण निश्चित रूप से जाने का तरीका है।


मैं, परीक्षण के समान प्रकार के अन्य लोगों के परिणाम के रूप में सुनवाई मुझे लगता है वे कर रहे हैं या कि क्या वे हमारे विशेष विन्यास के लिए विशिष्ट हैं कि मेरे निष्कर्ष सार्वभौमिक रूप में देखने के लिए में रुचि होगी।

आरंभ करने के लिए, यहाँ परीक्षण स्क्रिप्ट मैं प्रयोग किया जाता है - आप स्पष्ट रूप से से पॉप्युलेट करने के लिए अन्य डेटा के साथ आने के लिए की आवश्यकता होगी:

create table test1 
( 
    t_id int NOT NULL PRIMARY KEY, 
    i1 int NULL, 
    i2 int NULL, 
    i3 int NULL, 
    v1 varchar(500) NULL, 
    v2 varchar(500) NULL, 
    v3 varchar(500) NULL, 
    d1 datetime NULL, 
    d2 datetime NULL, 
    d3 datetime NULL 
) 

create table test2 
( 
    t_id int NOT NULL PRIMARY KEY, 
    i1 int NULL, 
    i2 int NULL, 
    i3 int NULL, 
    v1 varchar(500) NULL, 
    v2 varchar(500) NULL, 
    v3 varchar(500) NULL, 
    d1 datetime NULL, 
    d2 datetime NULL, 
    d3 datetime NULL 
) 

-- optional indexing here, test with it on and off... 
CREATE INDEX [IX_test1_i1] ON [dbo].[test1] ([i1]) 
CREATE INDEX [IX_test1_i2] ON [dbo].[test1] ([i2]) 
CREATE INDEX [IX_test1_i3] ON [dbo].[test1] ([i3]) 
CREATE INDEX [IX_test1_v1] ON [dbo].[test1] ([v1]) 
CREATE INDEX [IX_test1_v2] ON [dbo].[test1] ([v2]) 
CREATE INDEX [IX_test1_v3] ON [dbo].[test1] ([v3]) 
CREATE INDEX [IX_test1_d1] ON [dbo].[test1] ([d1]) 
CREATE INDEX [IX_test1_d2] ON [dbo].[test1] ([d2]) 
CREATE INDEX [IX_test1_d3] ON [dbo].[test1] ([d3]) 

CREATE INDEX [IX_test2_i1] ON [dbo].[test2] ([i1]) 
CREATE INDEX [IX_test2_i2] ON [dbo].[test2] ([i2]) 
CREATE INDEX [IX_test2_i3] ON [dbo].[test2] ([i3]) 
CREATE INDEX [IX_test2_v1] ON [dbo].[test2] ([v1]) 
CREATE INDEX [IX_test2_v2] ON [dbo].[test2] ([v2]) 
CREATE INDEX [IX_test2_v3] ON [dbo].[test2] ([v3]) 
CREATE INDEX [IX_test2_d1] ON [dbo].[test2] ([d1]) 
CREATE INDEX [IX_test2_d2] ON [dbo].[test2] ([d2]) 
CREATE INDEX [IX_test2_d3] ON [dbo].[test2] ([d3]) 

insert into test1 (t_id, i1, i2, i3, v1, v2, v3, d1, d2, d3) 
-- add data population here... 

insert into test2 (t_id, i1, i2, i3, v1, v2, v3, d1, d2, d3) 
select t_id, i1, i2, i3, v1, v2, v3, d1, d2, d3 from test1 

go 

create trigger test1_update on test1 for update 
as 
begin 

declare @i1_changed int, 
    @i2_changed int, 
    @i3_changed int, 
    @v1_changed int, 
    @v2_changed int, 
    @v3_changed int, 
    @d1_changed int, 
    @d2_changed int, 
    @d3_changed int 

IF UPDATE(i1) 
    SELECT @i1_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.i1,0) != ISNULL(d.i1,0) 
IF UPDATE(i2) 
    SELECT @i2_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.i2,0) != ISNULL(d.i2,0) 
IF UPDATE(i3) 
    SELECT @i3_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.i3,0) != ISNULL(d.i3,0) 
IF UPDATE(v1) 
    SELECT @v1_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.v1,'') != ISNULL(d.v1,'') 
IF UPDATE(v2) 
    SELECT @v2_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.v2,'') != ISNULL(d.v2,'') 
IF UPDATE(v3) 
    SELECT @v3_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.v3,'') != ISNULL(d.v3,'') 
IF UPDATE(d1) 
    SELECT @d1_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.d1,'1/1/1980') != ISNULL(d.d1,'1/1/1980') 
IF UPDATE(d2) 
    SELECT @d2_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.d2,'1/1/1980') != ISNULL(d.d2,'1/1/1980') 
IF UPDATE(d3) 
    SELECT @d3_changed = COUNT(*) FROM Inserted i INNER JOIN Deleted d 
     ON i.t_id = d.t_id WHERE ISNULL(i.d3,'1/1/1980') != ISNULL(d.d3,'1/1/1980') 

if (@i1_changed > 0) 
begin 
    UPDATE test1 SET i1 = CASE WHEN i.i1 > d.i1 THEN i.i1 ELSE d.i1 END 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.i1 != d.i1 
end 

if (@i2_changed > 0) 
begin 
    UPDATE test1 SET i2 = CASE WHEN i.i2 > d.i2 THEN POWER(i.i2, 1.1) ELSE POWER(d.i2, 1.1) END 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.i2 != d.i2 
end 

if (@i3_changed > 0) 
begin 
    UPDATE test1 SET i3 = i.i3^d.i3 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.i3 != d.i3 
end 

if (@v1_changed > 0) 
begin 
    UPDATE test1 SET v1 = i.v1 + 'a' 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.v1 != d.v1 
end 

UPDATE test1 SET v2 = LEFT(i.v2, 5) + '|' + RIGHT(d.v2, 5) 
FROM test1 
    INNER JOIN inserted i ON test1.t_id = i.t_id 
    INNER JOIN deleted d ON i.t_id = d.t_id 

if (@v3_changed > 0) 
begin 
    UPDATE test1 SET v3 = LEFT(i.v3, 5) + '|' + LEFT(i.v2, 5) + '|' + LEFT(i.v1, 5) 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.v3 != d.v3 
end 

if (@d1_changed > 0) 
begin 
    UPDATE test1 SET d1 = DATEADD(dd, 1, i.d1) 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.d1 != d.d1 
end 

if (@d2_changed > 0) 
begin 
    UPDATE test1 SET d2 = DATEADD(dd, DATEDIFF(dd, i.d2, d.d2), d.d2) 
    FROM test1 
     INNER JOIN inserted i ON test1.t_id = i.t_id 
     INNER JOIN deleted d ON i.t_id = d.t_id 
    WHERE i.d2 != d.d2 
end 

UPDATE test1 SET d3 = DATEADD(dd, 15, i.d3) 
FROM test1 
    INNER JOIN inserted i ON test1.t_id = i.t_id 
    INNER JOIN deleted d ON i.t_id = d.t_id 

end 

go 

create trigger test2_update on test2 for update 
as 
begin 

    UPDATE test2 SET 
     i1 = 
      CASE 
      WHEN ISNULL(i.i1, 0) != ISNULL(d.i1, 0) 
      THEN CASE WHEN i.i1 > d.i1 THEN i.i1 ELSE d.i1 END 
      ELSE test2.i1 END, 
     i2 = 
      CASE 
      WHEN ISNULL(i.i2, 0) != ISNULL(d.i2, 0) 
      THEN CASE WHEN i.i2 > d.i2 THEN POWER(i.i2, 1.1) ELSE POWER(d.i2, 1.1) END 
      ELSE test2.i2 END, 
     i3 = 
      CASE 
      WHEN ISNULL(i.i3, 0) != ISNULL(d.i3, 0) 
      THEN i.i3^d.i3 
      ELSE test2.i3 END, 
     v1 = 
      CASE 
      WHEN ISNULL(i.v1, '') != ISNULL(d.v1, '') 
      THEN i.v1 + 'a' 
      ELSE test2.v1 END, 
     v2 = LEFT(i.v2, 5) + '|' + RIGHT(d.v2, 5), 
     v3 = 
      CASE 
      WHEN ISNULL(i.v3, '') != ISNULL(d.v3, '') 
      THEN LEFT(i.v3, 5) + '|' + LEFT(i.v2, 5) + '|' + LEFT(i.v1, 5) 
      ELSE test2.v3 END, 
     d1 = 
      CASE 
      WHEN ISNULL(i.d1, '1/1/1980') != ISNULL(d.d1, '1/1/1980') 
      THEN DATEADD(dd, 1, i.d1) 
      ELSE test2.d1 END, 
     d2 = 
      CASE 
      WHEN ISNULL(i.d2, '1/1/1980') != ISNULL(d.d2, '1/1/1980') 
      THEN DATEADD(dd, DATEDIFF(dd, i.d2, d.d2), d.d2) 
      ELSE test2.d2 END, 
     d3 = DATEADD(dd, 15, i.d3) 
    FROM test2 
     INNER JOIN inserted i ON test2.t_id = i.t_id 
     INNER JOIN deleted d ON test2.t_id = d.t_id 

end 

go 

----- 
-- the below code can be used to confirm that the triggers operated identically over both tables after a test 
select top 10 test1.i1, test2.i1, test1.i2, test2.i2, test1.i3, test2.i3, test1.v1, test2.v1, test1.v2, test2.v2, test1.v3, test2.v3, test1.d1, test1.d1, test1.d2, test2.d2, test1.d3, test2.d3 
from test1 inner join test2 on test1.t_id = test2.t_id 
where 
    test1.i1 != test2.i1 or 
    test1.i2 != test2.i2 or 
    test1.i3 != test2.i3 or 
    test1.v1 != test2.v1 or 
    test1.v2 != test2.v2 or 
    test1.v3 != test2.v3 or 
    test1.d1 != test2.d1 or 
    test1.d2 != test2.d2 or 
    test1.d3 != test2.d3 

-- test 1 -- one column, one row 
update test1 set i3 = 64 where t_id = 1000 
go 
update test2 set i3 = 64 where t_id = 1000 
go 

update test1 set i3 = 64 where t_id = 1001 
go 
update test2 set i3 = 64 where t_id = 1001 
go 

-- test 2 -- one column, 10000 rows 
update test1 set v3 = LEFT(v3, 50) where t_id between 10000 and 20000 
go 
update test2 set v3 = LEFT(v3, 50) where t_id between 10000 and 20000 
go 

-- test 3 -- all columns, 1 row, non-self-referential 
update test1 set i1 = 1000, i2 = 2000, i3 = 3000, v1 = 'R12345123', v2 = 'Happy!', v3 = 'I am v3!!!', d1 = '1/1/1985', d2 = '1/1/1988', d3 = NULL 
where t_id = 3000 
go 
update test2 set i1 = 1000, i2 = 2000, i3 = 3000, v1 = 'R12345123', v2 = 'Happy!', v3 = 'I am v3!!!', d1 = '1/1/1985', d2 = '1/1/1988', d3 = NULL 
where t_id = 3000 
go 

-- test 4 -- all columns, 10000 rows, non-self-referential 
update test1 set i1 = 1000, i2 = 2000, i3 = 3000, v1 = 'R12345123', v2 = 'Happy!', v3 = 'I am v3!!!', d1 = '1/1/1985', d2 = '1/1/1988', d3 = NULL 
where t_id between 30000 and 40000 
go 
update test2 set i1 = 1000, i2 = 2000, i3 = 3000, v1 = 'R12345123', v2 = 'Happy!', v3 = 'I am v3!!!', d1 = '1/1/1985', d2 = '1/1/1988', d3 = NULL 
where t_id between 30000 and 40000 
go 

----- 

drop table test1 
drop table test2 
16

चलिए शुरू करते हैं मैं कभी नहीं कहूंगा और मेरा मतलब है कि किसी ट्रिगर में संग्रहित प्रो को कभी भी न आमंत्रित करें। एक बहु पंक्ति डालने के लिए खाते में आपको proc के माध्यम से कर्सर करना होगा। इसका मतलब यह है कि सेट-आधारित क्वेरी के बावजूद 200,000 पंक्तियों को लोड किया गया है (कहें कि सभी कीमतों को 10% तक अपडेट करना) मेज को अच्छी तरह से लॉक कर सकता है क्योंकि ट्रिगर भार को संभालने के लिए बहादुरी से प्रयास करता है। इसके अलावा यदि proc में कुछ बदलाव होता है, तो आप टेबल पर किसी भी इन्सर्ट को तोड़ सकते हैं या पूरी तरह से टेबल को लटक सकते हैं। मैं एक फर्म बेलीवर हूं जो ट्रिगर कोड को ट्रिगर के बाहर और कुछ नहीं कहना चाहिए।

व्यक्तिगत रूप से मैं बस अपना काम करना पसंद करता हूं। यदि मैंने उन कार्रवाइयों को लिखा है जो मैं ट्रिगर में ठीक से करना चाहता हूं तो यह केवल अपडेट, हटाएं या डालें जहां कॉलम बदल गए हैं।

उदाहरण: मान लीजिए कि आप अंतिम कारण नाम को अपडेट करना चाहते हैं जिसे आप दो स्थानों पर संग्रहीत कर रहे हैं क्योंकि प्रदर्शन कारणों से वहां एक असामान्यता के कारण रखा गया है।

update t 
set lname = i.lname 
from table2 t 
join inserted i on t.fkfield = i.pkfield 
where t.lname <>i.lname 

जैसा कि आप देख सकते हैं कि यह केवल उन नामों को अपडेट करेगा जो वर्तमान में तालिका में मौजूद है उससे अलग हैं।

आप लेखा परीक्षा और रिकॉर्ड केवल उन पंक्तियों जो तब बदल जहां i.field1 <> d.field1 या i.field2 <> d.field3 (आदि के माध्यम से सभी तुलना की तरह सभी क्षेत्रों कुछ का उपयोग कर करना चाहते हैं तो फ़ील्ड)

+0

आपके द्वारा पेश किए जाने वाले मामले में, आप मूल तालिका में किए गए प्रत्येक संशोधन के लिए अद्यतन के लिए लॉकिंग तालिका 2 को समाप्त कर देंगे, भले ही आपने कभी भी नाम को संशोधित नहीं किया हो। यही वह हिस्सा है जिसे मैं टालने की कोशिश कर रहा हूं। मगर आपकी सलाह के लिए धन्यवाद! – mwigdahl

+1

मैंने इसे वोट दिया क्योंकि मुझे एसपी को ट्रिगर्स से नहीं बुलाए जाने का कठिन तरीका पता चला .... कभी नहीं! – RolandTumble

9

मुझे लगता है कि आप ऑपरेटर छोड़कर का उपयोग कर जांच करने के लिए कर सकते हैं। यह एक सेट आधारित ऑपरेटर है जो पंक्तियों को कम कर सकता है जो नहीं बदला है। अच्छी बात यह है कि बराबर के रूप में शून्य मान समझता है के रूप में यह पहले सेट में पंक्तियों से पहले ऑपरेटर को छोड़कर और दूसरे के बाद सूचीबद्ध में नहीं छोड़कर

WITH ChangedData AS (
SELECT d.Table_ID , d.Col1 FROM deleted d 
EXCEPT 
SELECT i.Table_ID , i.Col1 FROM inserted i 
) 
/*Do Something with the ChangedData */ 

यह कॉलम कि बिना Nulls की अनुमति देने के मुद्दे संभालती सूचीबद्ध के लिए दिखता है ट्रिगर में ISNULL() का उपयोग और केवल परिवर्तनों का पता लगाने के लिए एक अच्छा सेट आधारित दृष्टिकोण के लिए col1 में परिवर्तन के साथ पंक्तियों के आईडी को लौटाता है। मैंने दृष्टिकोण का परीक्षण नहीं किया है लेकिन यह आपके समय के लायक हो सकता है। मुझे लगता है कि EXCEPT को SQL Server 2005 के साथ पेश किया गया था।

+0

मैं इसकी जांच करूंगा, धन्यवाद! – mwigdahl

+0

मैं इस विधि का उपयोग अपने डेटाबेस में काफी कुछ कर रहा हूं और हालांकि मैंने प्रदर्शन को माप नहीं लिया है, यह काफी तेज लगता है। मैंने मापन नहीं किया है क्योंकि मुझे प्रदर्शन हिट दिखाई नहीं दे रही है। बीटीडब्लू, मेरा तर्क EXSERT को EXCEPT से पहले रखता है और INSERT और अद्यतन परिवर्तनों का पता लगाता है। बीटीडब्ल्यू, मैंने "साथ" कथन का उपयोग नहीं किया है, लेकिन यह दिलचस्प लग रहा है। नीचे मेरा थोड़ा अलग जवाब देखें। –

5

मैं उपरोक्त टोड/आर्घटाइप द्वारा उल्लिखित EXCEPT सेट ऑपरेटर का उपयोग करने की सलाह देता हूं।

मैंने यह उत्तर जोड़ा है क्योंकि मैंने "हटाए गए" से पहले "सम्मिलित" रखा है ताकि INSERTs के साथ-साथ UPDATEs का पता लगाया जा सके। तो मैं आमतौर पर दोनों प्रविष्टियों और अद्यतनों को कवर करने के लिए एक ट्रिगर कर सकता हूं। या जोड़कर हटाए गए डिलीट का पता लगा सकते हैं (EXISTS (चयन * से सम्मिलित) और EXISTS (चयन * हटाए गए से))

यह निर्धारित करता है कि केवल निर्दिष्ट कॉलम में कोई मान बदल गया है या नहीं। मैंने अन्य समाधानों की तुलना में अपने प्रदर्शन की जांच नहीं की है लेकिन यह मेरे डेटाबेस में अच्छी तरह से काम कर रहा है।

यह बाएं क्वेरी से किसी भी पंक्ति को वापस करने के लिए EXCEPT सेट ऑपरेटर का उपयोग करता है जो सही क्वेरी पर नहीं मिलता है। इस कोड का उपयोग INSERT, अद्यतन और हटाए गए ट्रिगर्स में किया जा सकता है।

"पीकेआईडी" कॉलम प्राथमिक कुंजी है। यह दो सेट के बीच मिलान सक्षम करने के लिए आवश्यक है। यदि आपके पास प्राथमिक कुंजी के लिए एकाधिक कॉलम हैं तो आपको सम्मिलित और हटाए गए सेट के बीच सही मिलान करने के लिए सभी कॉलम शामिल करना होगा।

-- Only do trigger logic if specific field values change. 
IF EXISTS(SELECT PKID 
       ,Column1 
       ,Column7 
       ,Column10 
      FROM inserted 
      EXCEPT 
      SELECT PKID 
       ,Column1 
       ,Column7 
       ,Column10 
      FROM deleted) -- Tests for modifications to fields that we are interested in 
OR (NOT EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)) -- Have a deletion 
BEGIN 
      -- Put code here that does the work in the trigger 

END 

आप बाद में ट्रिगर तर्क में परिवर्तित पंक्तियों उपयोग करना चाहते हैं, मैं आमतौर पर छोड़कर पूछताछ के परिणामों एक मेज चर कि बाद में संदर्भित किया जा सकता में डाल दिया।

मुझे आशा है कि यह ब्याज की है :-)

संबंधित मुद्दे