এসকিউএল ক্যোয়ারী লেখার সর্বোত্তম উপায় যা নন-নুল মান বা NULL এর জন্য একটি কলাম চেক করে


17

আমার একটি এসপি রয়েছে একটি প্যারামিটারের সাথে ডিফল্ট মান হিসাবে নুল থাকে এবং তারপরে আমি এই জাতীয় একটি কোয়েরি করতে চাই:

SELECT ...
FROM ...
WHERE a.Blah = @Blah AND (a.VersionId = @VersionId OR (@VersionId IS NULL AND a.VersionId IS NULL));

WHEREউভয় একটি অ শূন্য মান এবং জন্য একটি নাল মান জন্য উপরে চেক @VersionId

পারফরম্যান্সের দিক থেকে আরও কী ভাল হবে যে পরিবর্তে কোনও IFবিবৃতি ব্যবহার করা এবং সেই প্রশ্নেরটিতে নকল করা যা এমন একটি এনআউএলএল নয় এবং অন্যটি এনওএলএল-এর মতো অনুসন্ধান করে? :

IF @VersionId IS NULL BEGIN
    SELECT ...
    FROM ...
    WHERE a.Blah = @Blah AND a.VersionId IS NULL;
ELSE BEGIN
    SELECT ...
    FROM ...
    WHERE a.Blah = @Blah AND a.VersionId = @VersionId;
END

অথবা ক্যোয়ারী অপ্টিমাইজার এটিকে মূলত একই করে তোলে?

হালনাগাদ:

(দ্রষ্টব্য: আমি এসকিউএল সার্ভার ব্যবহার করছি)

(এবং যতদূর আমি জানি, a.VersionId = @VersionIdউভয় ক্ষেত্রেই ব্যবহার করা কার্যকর হবে না,?)



আমি সাধারণত নিম্নলিখিতটি ব্যবহার করি: ইসনুল (এ। ভার্সনআইডি, @ ভার্সনআইডি) = @ ভার্সনআইডি
628426

উত্তর:


36

এই প্যাটার্ন

column = @argument OR (@argument IS NULL AND column IS NULL)

সঙ্গে প্রতিস্থাপন করা যেতে পারে

EXISTS (SELECT column INTERSECT SELECT @argument)

এটি আপনাকে একটি NULL এর সাথে একটি NUL এর সাথে মিলিয়ে দেবে এবং ইঞ্জিনটিকে columnদক্ষতার সাথে একটি সূচক ব্যবহার করার অনুমতি দেবে । এই কৌশলটির দুর্দান্ত গভীর-বিশ্লেষণের জন্য, আমি আপনাকে পল হোয়াইটের ব্লগ নিবন্ধটি উল্লেখ করছি:

আপনার নির্দিষ্ট ক্ষেত্রে যেমন দুটি যুক্তি রয়েছে, আপনি একই মেলানো কৌশলটি ব্যবহার করতে পারেন @Blah- এইভাবে আপনি আরও বা কম সংক্ষেপে পুরো WHERE ধারাটি পুনরায় লিখতে সক্ষম হবেন:

WHERE
  EXISTS (SELECT a.Blah, a.VersionId INTERSECT SELECT @Blah, @VersionId)

এটি সূচক চালু রেখে দ্রুত কাজ করবে (a.Blah, a.VersionId)


অথবা ক্যোয়ারী অপ্টিমাইজার এটিকে মূলত একই করে তোলে?

এই ক্ষেত্রে, হ্যাঁ। এসকিউএল সার্ভার ২০০৫ সাল থেকে সমস্ত সংস্করণে (কমপক্ষে), অপ্টিমাইজার প্যাটার্নটি সনাক্ত করতে পারে col = @var OR (@var IS NULL AND col IS NULL)এবং এটিকে যথাযথ ISতুলনার সাথে প্রতিস্থাপন করতে পারে । এটি অভ্যন্তরীণ পুনর্লিখনের মিলের উপর নির্ভর করে, তাই আরও জটিল কিছু ক্ষেত্রে থাকতে পারে যেখানে এটি সর্বদা নির্ভরযোগ্য নয়।

SQL সার্ভার এর সংস্করণে 2008 এসপি 1 CU5 সমেত থেকে , এছাড়াও আপনি ব্যবহার করার অপশন আছে প্যারামিটার এমবেডিং অপ্টিমাইজেশান মাধ্যমে OPTION (RECOMPILE), যেখানে কোনো প্যারামিটার বা ভেরিয়েবলের রানটাইম মান সংকলন আগে একটি আক্ষরিক যেমন ক্যোয়ারীতে এমবেড করা হয়।

সুতরাং, কমপক্ষে একটি বৃহত পরিমাণে, এই ক্ষেত্রে পছন্দটি স্টাইলের বিষয়, যদিও INTERSECTনির্মাণটি অনস্বীকার্যভাবে কমপ্যাক্ট এবং মার্জিত।

নিম্নলিখিত উদাহরণগুলি প্রতিটি পরিবর্তনের জন্য 'একই' কার্যকরকরণ পরিকল্পনাটি দেখায় (আক্ষরিক বনাম চলক উল্লেখগুলি বাদ দেওয়া হয়):

DECLARE @T AS table
(
    c1 integer NULL,
    c2 integer NULL,
    c3 integer NULL

    UNIQUE CLUSTERED (c1, c2)
);

-- Some data
INSERT @T
    (c1, c2, c3)
SELECT 1, 1, 1 UNION ALL
SELECT 2, 2, 2 UNION ALL
SELECT NULL, NULL, NULL UNION ALL
SELECT 3, 3, 3;

-- Filtering conditions
DECLARE 
    @c1 integer,
    @c2 integer;

SELECT
    @c1 = NULL,
    @c2 = NULL;

-- Writing the NULL-handling out explicitly
SELECT * 
FROM @T AS T
WHERE 
(
    T.c1 = @c1
    OR (@c1 IS NULL AND T.c1 IS NULL)
)
AND 
(
    T.c2 = @c2
    OR (@c2 IS NULL AND T.c2 IS NULL)
);

-- Using INTERSECT
SELECT * 
FROM @T AS T
WHERE EXISTS 
(
    SELECT T.c1, T.c2 
    INTERSECT 
    SELECT @c1, @c2
);

-- Using separate queries
IF @c1 IS NULL AND @c2 IS NULL
    SELECT * 
    FROM @T AS T
    WHERE T.c1 IS NULL
    AND T.c2 IS NULL
ELSE IF @c1 IS NULL
    SELECT * 
    FROM @T AS T
    WHERE T.c1 IS NULL
    AND T.c2 = @c2
ELSE IF @c2 IS NULL
    SELECT * 
    FROM @T AS T
    WHERE T.c1 = @c1
    AND T.c2 IS NULL
ELSE
    SELECT * 
    FROM @T AS T
    WHERE T.c1 = @c1
    AND T.c2 = @c2;

-- Using OPTION (RECOMPILE)
-- Requires 2008 SP1 CU5 or later
SELECT * 
FROM @T AS T
WHERE 
(
    T.c1 = @c1
    OR (@c1 IS NULL AND T.c1 IS NULL)
)
AND 
(
    T.c2 = @c2
    OR (@c2 IS NULL AND T.c2 IS NULL)
)
OPTION (RECOMPILE);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.