MERGE
বিবৃতি একটি জটিল বাক্য গঠন এবং একটি এমনকি আরো জটিল বাস্তবায়ন আছে, কিন্তু মূলত ধারণা দুই টেবিল যোগদানের জন্য, সারি পরিবর্তন করা (সন্নিবেশিত, আপডেট, বা মুছে ফেলা হয়েছে) প্রয়োজন ফিল্টার করুন, এবং তারপর অনুরোধ পরিবর্তন সম্পাদন করতে। নিম্নলিখিত নমুনা তথ্য দেওয়া:
DECLARE @CategoryItem AS TABLE
(
CategoryId integer NOT NULL,
ItemId integer NOT NULL,
PRIMARY KEY (CategoryId, ItemId),
UNIQUE (ItemId, CategoryId)
);
DECLARE @DataSource AS TABLE
(
CategoryId integer NOT NULL,
ItemId integer NOT NULL
PRIMARY KEY (CategoryId, ItemId)
);
INSERT @CategoryItem
(CategoryId, ItemId)
VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 3),
(3, 5),
(3, 6),
(4, 5);
INSERT @DataSource
(CategoryId, ItemId)
VALUES
(2, 2);
লক্ষ্য
╔════════════╦════════╗
║ CategoryId ║ ItemId ║
╠════════════╬════════╣
║ 1 ║ 1 ║
║ 2 ║ 1 ║
║ 1 ║ 2 ║
║ 1 ║ 3 ║
║ 2 ║ 3 ║
║ 3 ║ 5 ║
║ 4 ║ 5 ║
║ 3 ║ 6 ║
╚════════════╩════════╝
উৎস
╔════════════╦════════╗
║ CategoryId ║ ItemId ║
╠════════════╬════════╣
║ 2 ║ 2 ║
╚════════════╩════════╝
কাঙ্ক্ষিত ফলাফলটি হ'ল উত্স থেকে প্রাপ্ত ডেটা সহ লক্ষ্যমাত্রায় ডেটা প্রতিস্থাপন করা, তবে কেবল তার জন্য CategoryId = 2
। MERGE
উপরের বর্ণনার বিবরণ অনুসরণ করে , আমাদের এমন একটি ক্যোয়ারী লেখা উচিত যা উত্সটিতে যোগ দেয় এবং কেবল কীগুলিতে লক্ষ্য রেখে যায় এবং কেবলমাত্র WHEN
ক্লজগুলিতে সারিগুলি ফিল্টার করে:
MERGE INTO @CategoryItem AS TARGET
USING @DataSource AS SOURCE ON
SOURCE.ItemId = TARGET.ItemId
AND SOURCE.CategoryId = TARGET.CategoryId
WHEN NOT MATCHED BY SOURCE
AND TARGET.CategoryId = 2
THEN DELETE
WHEN NOT MATCHED BY TARGET
AND SOURCE.CategoryId = 2
THEN INSERT (CategoryId, ItemId)
VALUES (CategoryId, ItemId)
OUTPUT
$ACTION,
ISNULL(INSERTED.CategoryId, DELETED.CategoryId) AS CategoryId,
ISNULL(INSERTED.ItemId, DELETED.ItemId) AS ItemId
;
এটি নিম্নলিখিত ফলাফল দেয়:
╔═════════╦════════════╦════════╗
║ $ACTION ║ CategoryId ║ ItemId ║
╠═════════╬════════════╬════════╣
║ DELETE ║ 2 ║ 1 ║
║ INSERT ║ 2 ║ 2 ║
║ DELETE ║ 2 ║ 3 ║
╚═════════╩════════════╩════════╝
╔════════════╦════════╗
║ CategoryId ║ ItemId ║
╠════════════╬════════╣
║ 1 ║ 1 ║
║ 1 ║ 2 ║
║ 1 ║ 3 ║
║ 2 ║ 2 ║
║ 3 ║ 5 ║
║ 3 ║ 6 ║
║ 4 ║ 5 ║
╚════════════╩════════╝
কার্যকর করার পরিকল্পনাটি হ'ল:
উভয় টেবিল সম্পূর্ণ স্ক্যান করা আছে লক্ষ্য করুন। আমরা এই অদক্ষ মনে করতে পারি, কারণ কেবল সারি যেখানে CategoryId = 2
লক্ষ্য সারণীতে প্রভাবিত হবে। এখানেই বুকস অনলাইনে সতর্কতা আসে the লক্ষ্যমাত্রায় কেবল প্রয়োজনীয় সারিগুলিকে স্পর্শ করতে অনুকূলিত করার একটি বিভ্রান্ত প্রচেষ্টা:
MERGE INTO @CategoryItem AS TARGET
USING
(
SELECT CategoryId, ItemId
FROM @DataSource AS ds
WHERE CategoryId = 2
) AS SOURCE ON
SOURCE.ItemId = TARGET.ItemId
AND TARGET.CategoryId = 2
WHEN NOT MATCHED BY TARGET THEN
INSERT (CategoryId, ItemId)
VALUES (CategoryId, ItemId)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT
$ACTION,
ISNULL(INSERTED.CategoryId, DELETED.CategoryId) AS CategoryId,
ISNULL(INSERTED.ItemId, DELETED.ItemId) AS ItemId
;
ধারাটিতে যুক্তি যুক্ত হওয়ার ON
অংশ হিসাবে প্রয়োগ করা হয়। এই ক্ষেত্রে, যোগদানটি সম্পূর্ণ বাইরের যোগদান ( কেন এই পুস্তকাগুলি অনলাইন এন্ট্রি দেখুন )। বাহ্যিক যোগদানের অংশ হিসাবে লক্ষ্য সারিগুলিতে 2 বিভাগের জন্য চেক প্রয়োগ করার ফলে শেষ পর্যন্ত সারিগুলিতে আলাদা মান মুছে ফেলা হয় (কারণ তারা উত্সটির সাথে মেলে না):
╔═════════╦════════════╦════════╗
║ $ACTION ║ CategoryId ║ ItemId ║
╠═════════╬════════════╬════════╣
║ DELETE ║ 1 ║ 1 ║
║ DELETE ║ 1 ║ 2 ║
║ DELETE ║ 1 ║ 3 ║
║ DELETE ║ 2 ║ 1 ║
║ INSERT ║ 2 ║ 2 ║
║ DELETE ║ 2 ║ 3 ║
║ DELETE ║ 3 ║ 5 ║
║ DELETE ║ 3 ║ 6 ║
║ DELETE ║ 4 ║ 5 ║
╚═════════╩════════════╩════════╝
╔════════════╦════════╗
║ CategoryId ║ ItemId ║
╠════════════╬════════╣
║ 2 ║ 2 ║
╚════════════╩════════╝
মূল কারণটি হ'ল কারণটিতে ON
অনুচ্ছেদগুলিতে নির্দিষ্ট করা থাকলে তার চেয়ে বাহ্যিক সংযুক্তি দফায় ভিন্ন আচরণ করার পূর্বাভাস দেয় WHERE
। MERGE
সিনট্যাক্স (এবং বাস্তবায়ন যোগদানের ক্লজ নিদিষ্ট উপর নির্ভর করে) শুধু এটা কঠিন দেখতে এই তাই তা নিশ্চিত করুন।
বই অনলাইন নির্দেশিকা (ইন সম্প্রসারিত অপ্টিমাইজ পারফরমেন্স এন্ট্রি) হেদায়েত যে সঠিক শব্দার্থিক নিশ্চিত করবে ব্যবহার প্রকাশ করা হয় উপলব্ধ করা হয় MERGE
, বাক্য গঠন ব্যবহারকারী অগত্যা সব বাস্তবায়ন বিবরণ, অথবা উপায়ে অপটিমাইজার বৈধভাবে নতুন করে সাজানো হতে পারে জন্য অ্যাকাউন্ট বুঝতে না করেও কার্য সম্পাদনের দক্ষতার কারণে জিনিসগুলি।
প্রারম্ভিক ফিল্টারিং প্রয়োগের জন্য ডকুমেন্টেশনটি তিনটি সম্ভাব্য উপায় সরবরাহ করে:
একটি ফিল্টারিং শর্ত নির্দিষ্ট করা WHEN
দফা সঠিক ফলাফল গ্যারান্টী বা নিশ্চয়তা দিচ্ছে, কিন্তু এর অর্থ হতে পারে আরো সারি পড়া হয় এবং সোর্স এবং টার্গেট টেবিল থেকে প্রক্রিয়াজাত থেকে যথাযথভাবে বাধ্যতামূলক (হিসাবে প্রথম উদাহরণে দেখা)।
একটি দৃশ্য মাধ্যমে আপডেট করা হচ্ছে যে ফিল্টারিং শর্ত এছাড়াও রয়েছে সঠিক ফলাফল গ্যারান্টী বা নিশ্চয়তা দিচ্ছে (যেহেতু পরিবর্তিত সারি দৃশ্য মাধ্যমে আপডেটের জন্য প্রবেশযোগ্য হতে হবে) কিন্তু এই ডেডিকেটেড দৃশ্য প্রয়োজন নেই এবং এক যে মতামত আপডেট করার জন্য বিজোড় অবস্থার অনুসরণ করে।
একটি সাধারণ টেবিল এক্সপ্রেশন ব্যবহার ক্লজটিতে পূর্বাভাস যুক্ত করার অনুরূপ ঝুঁকি বহন করে ON
, তবে কিছুটা ভিন্ন কারণে। অনেক ক্ষেত্রে এটি নিরাপদ হবে, তবে এটির (এবং বিস্তৃত ব্যবহারিক পরীক্ষার) বিষয়টি নিশ্চিত করার জন্য এটি কার্যকর করার পরিকল্পনার বিশেষজ্ঞ বিশ্লেষণের প্রয়োজন। উদাহরণ স্বরূপ:
WITH TARGET AS
(
SELECT *
FROM @CategoryItem
WHERE CategoryId = 2
)
MERGE INTO TARGET
USING
(
SELECT CategoryId, ItemId
FROM @DataSource
WHERE CategoryId = 2
) AS SOURCE ON
SOURCE.ItemId = TARGET.ItemId
AND SOURCE.CategoryId = TARGET.CategoryId
WHEN NOT MATCHED BY TARGET THEN
INSERT (CategoryId, ItemId)
VALUES (CategoryId, ItemId)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT
$ACTION,
ISNULL(INSERTED.CategoryId, DELETED.CategoryId) AS CategoryId,
ISNULL(INSERTED.ItemId, DELETED.ItemId) AS ItemId
;
এটি আরও অনুকূল পরিকল্পনার সাথে সঠিক ফলাফলগুলি পুনরাবৃত্তি করে না:
পরিকল্পনাটি কেবলমাত্র সারণী থেকে 2 বিভাগের সারিগুলি পড়বে। লক্ষ্য সারণী বড় হলে এটি একটি গুরুত্বপূর্ণ পারফরম্যান্স বিবেচনা হতে পারে তবে MERGE
সিনট্যাক্স ব্যবহার করে ভুলটি পাওয়া খুব সহজ ।
কখনও কখনও, MERGE
পৃথক ডিএমএল ক্রিয়াকলাপ হিসাবে এটি লেখা আরও সহজ । এই পদ্ধতির একটি একক চেয়ে আরও ভাল অভিনয় করতে পারে MERGE
, একটি ঘটনা যা প্রায়শই মানুষকে অবাক করে।
DELETE ci
FROM @CategoryItem AS ci
WHERE ci.CategoryId = 2
AND NOT EXISTS
(
SELECT 1
FROM @DataSource AS ds
WHERE
ds.ItemId = ci.ItemId
AND ds.CategoryId = ci.CategoryId
);
INSERT @CategoryItem
SELECT
ds.CategoryId,
ds.ItemId
FROM @DataSource AS ds
WHERE
ds.CategoryId = 2;