CHECKSUM()
প্রকৃত মানগুলি পরিবর্তিত হয়েছে কিনা তা তুলনা করার জন্য আপনি মোটামুটি সহজ পদ্ধতি হিসাবে ব্যবহার করতে পারেন । CHECKSUM()
উত্তীর্ণ হওয়া মানগুলির একটি তালিকা জুড়ে একটি চেকসাম তৈরি করবে, যার মধ্যে নম্বর এবং প্রকারটি অনির্দিষ্ট। সাবধান, এই জাতীয় চেকসামের সাথে তুলনা করার একটি ছোট সুযোগ রয়েছে যার ফলে মিথ্যা নেতিবাচক ফলাফল আসবে। আপনি যদি এটি মোকাবেলা করতে না পারেন, আপনি HASHBYTES
পরিবর্তে 1 ব্যবহার করতে পারেন ।
নীচের উদাহরণটি কেবলমাত্র যদি কলামের মান বা কলামের পরিবর্তিত হয় তবে কেবলমাত্র টেবিলটিতে করা AFTER UPDATE
পরিবর্তনের ইতিহাস ধরে রাখতে একটি ট্রিগার ব্যবহার করে । যদি পরিবর্তন হয়, কোনও পদক্ষেপ নেওয়া হয় না।TriggerTest
Data1
Data2
Data3
USE tempdb;
IF COALESCE(OBJECT_ID('dbo.TriggerTest'), 0) <> 0
BEGIN
DROP TABLE dbo.TriggerTest;
END
CREATE TABLE dbo.TriggerTest
(
TriggerTestID INT NOT NULL
CONSTRAINT PK_TriggerTest
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, Data1 VARCHAR(10) NULL
, Data2 VARCHAR(10) NOT NULL
, Data3 DATETIME NOT NULL
);
IF COALESCE(OBJECT_ID('dbo.TriggerResult'), 0) <> 0
BEGIN
DROP TABLE dbo.TriggerResult;
END
CREATE TABLE dbo.TriggerResult
(
TriggerTestID INT NOT NULL
, Data1OldVal VARCHAR(10) NULL
, Data1NewVal VARCHAR(10) NULL
, Data2OldVal VARCHAR(10) NULL
, Data2NewVal VARCHAR(10) NULL
);
GO
IF COALESCE(OBJECT_ID('dbo.TriggerTest_AfterUpdate'), 0) <> 0
BEGIN
DROP TRIGGER TriggerTest_AfterUpdate;
END
GO
CREATE TRIGGER TriggerTest_AfterUpdate
ON dbo.TriggerTest
AFTER UPDATE
AS
BEGIN
INSERT INTO TriggerResult
(
TriggerTestID
, Data1OldVal
, Data1NewVal
, Data2OldVal
, Data2NewVal
)
SELECT d.TriggerTestID
, d.Data1
, i.Data1
, d.Data2
, i.Data2
FROM inserted i
LEFT JOIN deleted d ON i.TriggerTestID = d.TriggerTestID
WHERE CHECKSUM(i.Data1, i.Data2) <> CHECKSUM(d.Data1, d.Data2);
END
GO
INSERT INTO dbo.TriggerTest (Data1, Data2, Data3)
VALUES ('blah', 'foo', GETDATE());
UPDATE dbo.TriggerTest
SET Data1 = 'blah', Data2 = 'fee'
WHERE TriggerTestID = 1;
SELECT *
FROM dbo.TriggerTest;
SELECT *
FROM dbo.TriggerResult
আপনি যদি COLUMNS_UPDATED () ফাংশনটি ব্যবহার করার জন্য জেদ করেন তবে আপনার প্রশ্নের মধ্যে থাকা কলামগুলির মূল মানটি হার্ড-কোড করা উচিত নয়, যেহেতু সারণির সংজ্ঞাটি বদলে যেতে পারে, যা হার্ড-কোডিং মানকে অকার্যকর করতে পারে। সিস্টেম টেবিলগুলি ব্যবহার করে রানটাইমের সময় মানটি কী হওয়া উচিত তা আপনি গণনা করতে পারেন। সচেতন থাকুন যে বিবৃতি দ্বারা প্রভাবিত কোনও সারিতে COLUMNS_UPDATED()
কলামটি সংশোধন করা থাকলে প্রদত্ত কলাম বিটের জন্য ফাংশনটি সত্য প্রত্যাবর্তন করে । UPDATE TABLE
USE tempdb;
IF COALESCE(OBJECT_ID('dbo.TriggerTest'), 0) <> 0
BEGIN
DROP TABLE dbo.TriggerTest;
END
CREATE TABLE dbo.TriggerTest
(
TriggerTestID INT NOT NULL
CONSTRAINT PK_TriggerTest
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, Data1 VARCHAR(10) NULL
, Data2 VARCHAR(10) NOT NULL
, Data3 DATETIME NOT NULL
);
IF COALESCE(OBJECT_ID('dbo.TriggerResult'), 0) <> 0
BEGIN
DROP TABLE dbo.TriggerResult;
END
CREATE TABLE dbo.TriggerResult
(
TriggerTestID INT NOT NULL
, Data1OldVal VARCHAR(10) NULL
, Data1NewVal VARCHAR(10) NULL
, Data2OldVal VARCHAR(10) NULL
, Data2NewVal VARCHAR(10) NULL
);
GO
IF COALESCE(OBJECT_ID('dbo.TriggerTest_AfterUpdate'), 0) <> 0
BEGIN
DROP TRIGGER TriggerTest_AfterUpdate;
END
GO
CREATE TRIGGER TriggerTest_AfterUpdate
ON dbo.TriggerTest
AFTER UPDATE
AS
BEGIN
DECLARE @ColumnOrdinalTotal INT = 0;
SELECT @ColumnOrdinalTotal = @ColumnOrdinalTotal
+ POWER (
2
, COLUMNPROPERTY(t.object_id,c.name,'ColumnID') - 1
)
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
WHERE s.name = 'dbo'
AND t.name = 'TriggerTest'
AND c.name IN (
'Data1'
, 'Data2'
);
IF (COLUMNS_UPDATED() & @ColumnOrdinalTotal) > 0
BEGIN
INSERT INTO TriggerResult
(
TriggerTestID
, Data1OldVal
, Data1NewVal
, Data2OldVal
, Data2NewVal
)
SELECT d.TriggerTestID
, d.Data1
, i.Data1
, d.Data2
, i.Data2
FROM inserted i
LEFT JOIN deleted d ON i.TriggerTestID = d.TriggerTestID;
END
END
GO
--this won't result in rows being inserted into the history table
INSERT INTO dbo.TriggerTest (Data1, Data2, Data3)
VALUES ('blah', 'foo', GETDATE());
SELECT *
FROM dbo.TriggerResult;
--this will insert rows into the history table
UPDATE dbo.TriggerTest
SET Data1 = 'blah', Data2 = 'fee'
WHERE TriggerTestID = 1;
SELECT *
FROM dbo.TriggerTest;
SELECT *
FROM dbo.TriggerResult;
--this WON'T insert rows into the history table
UPDATE dbo.TriggerTest
SET Data3 = GETDATE()
WHERE TriggerTestID = 1;
SELECT *
FROM dbo.TriggerTest;
SELECT *
FROM dbo.TriggerResult
--this will insert rows into the history table, even though only
--one of the columns was updated
UPDATE dbo.TriggerTest
SET Data1 = 'blum'
WHERE TriggerTestID = 1;
SELECT *
FROM dbo.TriggerTest;
SELECT *
FROM dbo.TriggerResult;
এই ডেমোটি ইতিহাস সারণিতে সারি সন্নিবেশ করায় যা সম্ভবত beোকানো উচিত নয়। সারিগুলির Data1
কয়েকটি সারিগুলির জন্য তাদের কলামটি আপডেট হয়েছে এবং কিছু সারিটির Data3
জন্য কলামটি আপডেট করা হয়েছে। যেহেতু এটি একটি একক বিবৃতি, সমস্ত সারি ট্রিগার মাধ্যমে একক পাস দ্বারা প্রক্রিয়া করা হয়। যেহেতু কিছু সারি Data1
আপডেট হয়েছে, যা COLUMNS_UPDATED()
তুলনার অংশ, তাই ট্রিগার দ্বারা দেখা সমস্ত সারি TriggerHistory
টেবিলের মধ্যে areোকানো হয়েছে । যদি এটি আপনার দৃশ্যের জন্য "ভুল" হয় তবে আপনার কার্সার ব্যবহার করে প্রতিটি সারি আলাদাভাবে পরিচালনা করতে হবে।
INSERT INTO dbo.TriggerTest (Data1, Data2, Data3)
SELECT TOP(10) LEFT(o.name, 10)
, LEFT(o1.name, 10)
, GETDATE()
FROM sys.objects o
, sys.objects o1;
UPDATE dbo.TriggerTest
SET Data1 = CASE WHEN TriggerTestID % 6 = 1 THEN Data2 ELSE Data1 END
, Data3 = CASE WHEN TriggerTestID % 6 = 2 THEN GETDATE() ELSE Data3 END;
SELECT *
FROM dbo.TriggerTest;
SELECT *
FROM dbo.TriggerResult;
TriggerResult
টেবিল এখন কিছু সম্ভাব্য বিভ্রান্তিকর সারি যে চেহারা মত তাদের সে অধিকার না যেহেতু অন্তর্গত তারা একেবারে (যে টেবিলের দুই কলাম পর্যন্ত) কোনো পরিবর্তন দেন হয়েছে। নীচের চিত্রের সারিগুলির 2 য় সেটটিতে, ট্রিগারস্টেস্টআইডি 7 কেবলমাত্র এটির মতো পরিবর্তিত হয়েছে বলে মনে হচ্ছে। অন্যান্য সারিগুলিতে কেবল Data3
কলামটি আপডেট হয়েছিল; তবে যেহেতু ব্যাচের এক সারিটি Data1
আপডেট হয়েছিল, সমস্ত সারিটি TriggerResult
সারণিতে সন্নিবেশ করা হয়েছে ।
পর্যায়ক্রমে @ অ্যারনবার্ট্র্যান্ড এবং @ শ্রুতজকির নির্দেশ অনুসারে, আপনি inserted
এবং deleted
ভার্চুয়াল টেবিলগুলিতে প্রকৃত ডেটার তুলনা করতে পারবেন । যেহেতু উভয় টেবিলের কাঠামোটি অভিন্ন, আপনি EXCEPT
সারিগুলি ক্যাপচার করতে ট্রিগারটিতে একটি ধারা ব্যবহার করতে পারেন যেখানে আপনি আগ্রহী সঠিক কলামগুলি পরিবর্তিত হয়েছে:
IF COALESCE(OBJECT_ID('dbo.TriggerTest_AfterUpdate'), 0) <> 0
BEGIN
DROP TRIGGER TriggerTest_AfterUpdate;
END
GO
CREATE TRIGGER TriggerTest_AfterUpdate
ON dbo.TriggerTest
AFTER UPDATE
AS
BEGIN
;WITH src AS
(
SELECT d.TriggerTestID
, d.Data1
, d.Data2
FROM deleted d
EXCEPT
SELECT i.TriggerTestID
, i.Data1
, i.Data2
FROM inserted i
)
INSERT INTO dbo.TriggerResult
(
TriggerTestID,
Data1OldVal,
Data1NewVal,
Data2OldVal,
Data2NewVal
)
SELECT i.TriggerTestID
, d.Data1
, i.Data1
, d.Data2
, i.Data2
FROM inserted i
INNER JOIN deleted d ON i.TriggerTestID = d.TriggerTestID
END
GO
1 - দেখুন এইচটিএসএইচবিআইটিইএস গণনাটি সংঘর্ষেরও কারণ হতে পারে এমন ছোট্ট সুযোগের বর্জন করার জন্য /programming/297960/hash-collision- কি-are-the- সুযোগগুলি দেখুন। প্রেসিংয়ের পাশাপাশি এই সমস্যার একটি শালীন বিশ্লেষণ রয়েছে।
SET
তালিকায় উল্লেখ করা হয়েছে , বা মানগুলি আসলে পরিবর্তিত হয়েছে কিনা? উভয়UPDATE
এবংCOLUMNS_UPDATED()
শুধুমাত্র আপনাকে প্রাক্তনকে বলে। মানগুলি আসলে পরিবর্তন হয়েছে কিনা তা যদি আপনি জানতে চান তবে আপনাকেinserted
এবং এর একটি সঠিক তুলনা করতে হবেdeleted
।