Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Най-добри отговори на 5 горящи въпроса относно функцията COALESCE в SQL Server

Колко готина е функцията COALESCE в SQL?

Достатъчно готино е, за да е толкова важно за мен. И ще се радвам да наема нов човек, който няма лош навик да игнорира целта на COALESCE. Това включва други изрази и функции за справяне с подобни ситуации.

Днес ще намерите отговорите на петте най-често задавани въпроса относно SQL COALESCE израза. Едно от тях се обсъжда отново и отново.

Да започнем ли?

Какво е използването на функцията COALESCE в SQL?

Може да се отговори с 2 думи:обработка на нули .

Null е празнота от стойности. С други думи, неизвестен. Той е различен от празен низ или нулево число. Обработката на null изисква използването на изрази и функции. Един от тях е СЛИВАНЕ.

За да разберете какво имам предвид, вижте изявленията по-долу:

DECLARE @number INT

SELECT @number + 33587

Ще работи ли добре? Ще стане.

Има ли някакъв проблем? Няма, в момента.

Но изразите ще доведат до NULL, защото добавянето на null към число е равно на NULL.

Ако всичките ви заявки паднат само до това ниво, можете да спрете да четете. Но разбира се, те не са. Плащаме ни за повече от това да произвеждаме този вид код.

Сега, нека добавим малко „катастрофа“:

DECLARE @number INT

SET @number = @number + 33587

UPDATE myTable
set col1 = @number   -- Surprise! col1 is NOT NULLABLE
where ID = 1

PRINT 'Success!'

Изпълнението на кода по-горе ще бъде в задънена улица, когато достигне оператора UPDATE. Няма да отпечата „Успех!“, защото не можете да поставите нула в колона, която не може да бъде нула. Това твърдение говори ли ясно защо трябва да обработваме нулеви стойности?

Нека променим кода, за да добавим предпазна мрежа:

DECLARE @number INT

SET @number = COALESCE(@number,0) + 33587     -- our safety net. Thanks to COALESCE.

UPDATE myTable
set col1 = @number               -- Disaster averted!
where ID = 1

PRINT 'Success!'

COALESCE ще промени нулевата стойност на нула и сумата няма да бъде нула.

Урокът е, че COALESCE е една от предпазните мрежи срещу нулеви стойности. Още по-добре, правилното боравене с нули във вашия SQL код намалява главоболието ви и ви позволява да се приберете по-рано. Това е сигурно.

Сега разбирате защо искам в екипа си някой усърден в боравене с нули.

Още практически примери за използването на SQL COALESCE

Нека се обърнем към по-практични примери.

Да предположим, че живеете в регион, където някои хора имат средни имена, но други не. Как ще формирате пълното име от собственото, бащиното и фамилното име, без да попадате в нулевия капан?

Ето едно възможно решение с помощта на COALESCE:

USE AdventureWorks
GO

SELECT
p.LastName + ', ' + p.FirstName + ' ' + COALESCE(p.MiddleName + ' ','') AS FullName
FROM Person.Person p

Друг пример:да предположим, че сте служител в компания, където брутното заплащане се изчислява по различен начин за всеки служител. За някои от тях има почасови ставки. Други получават плащания на седмични или месечни ставки.

Ето примерна таблица заедно с решение за заявка с помощта на COALESCE:

-- STEP 1: Create the table
CREATE TABLE EmployeeWages (
    employee_id INT PRIMARY KEY,
    hourly_rate SMALLMONEY,
    weekly_rate SMALLMONEY,
    monthly_rate MONEY,
    CHECK(
        hourly_rate IS NOT NULL OR
        weekly_rate IS NOT NULL OR
        monthly_rate IS NOT NULL)
);

-- STEP 2: Insert data
INSERT INTO
    EmployeeWages(
        employee_id,
        hourly_rate,
        weekly_rate,
        monthly_rate
    )
VALUES
    (1,60, NULL,NULL),
    (2,40, NULL,NULL),
    (3,NULL, 1000,NULL),
    (4,NULL, NULL,7000),
    (5,NULL, NULL,5000);

-- STEP 3: Query the monthly salary.
SELECT
    employee_id,
    COALESCE(
        hourly_rate*22.00*8.00,
        weekly_rate*4.00,
        monthly_rate
    ) AS monthly_salary
FROM
    EmployeeWages;

Таблицата съдържа различни режими на заплащане на идентификатор на служител. Заявката изисква да изведете месечна заплата за всички.

Това е мястото, където COALESCE ще блесне:той приема списък със стойности и може да има произволен брой елементи. COALESCE ще избере първия, който не е нулев:

Кокетно, нали?

Как работи COALESCE в SQL?

Дефиницията на COALESCE е израз, който връща първата ненулева стойност от списък със стойности. Синтаксисът COALESCE е:

СЛИВАНЕ (израз [ ,…n ] )

Предишният ни пример с различни начини на плащане за заплати илюстрира това.

Какво има под капака

Под капака функцията COALESCE в SQL е покрит със захар израз за много по-дълъг CASE израз. Това премахва необходимостта от въвеждане на еквивалентен CASE, който е по-дълъг (и изморителен за мързеливи машинописки като мен). Резултатът ще бъде същият.

Можем ли да го докажем? Да! От една страна, Microsoft го признава.

Но добре за нас, Microsoft го включи в плана за изпълнение. Така знаем какво става.

Нека опитаме с помощта на предишен пример със заплатите. Но преди да стартирате отново заявката по-долу, включете Включи действителен план за изпълнение или просто натиснете CTRL-M .

SELECT
    employee_id,
    COALESCE(
        hourly_rate * 22.00 * 8.00,
        weekly_rate * 4.00,
        monthly_rate
    ) AS monthly_salary
FROM
    EmployeeWages;

Щракнете върху План за изпълнение раздел в резултатите. Изглежда просто, но нашия скрит скъпоценен камък се крие в Compute Scalar възел. Когато задържите курсора на мишката върху него, виждате израз с име Expr1002 (Фигура 2). Какво може да бъде?

Да копаем по-дълбоко. Щракнете с десния бутон върху него и изберете Покажи XML на плана за изпълнение . Ще се появи нов прозорец. Разгледайте фигура 3 по-долу:

Ето вашето изявление CASE. По-долу е цялото нещо, форматирано и с отстъп за четливост:

CASE WHEN CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)
                                            *(22.00)*(8.00) IS NOT NULL
     THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),
                       [TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)*(22.00)*(8.00),0)
     ELSE CASE WHEN    
          CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)
                                            *(4.00) IS NOT NULL
          THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),                                                         
                       [TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*(4.00),0)
          ELSE CONVERT_IMPLICIT(numeric(23,8),[TestDatabase].[dbo].[EmployeeWages].[monthly_rate],0)
          END
END

Това е доста дълго в сравнение с

COALESCE(
        hourly_rate * 22.00 * 8.00,
        weekly_rate * 4.00,
        monthly_rate
        )

Това направи SQL Server с нашата заявка с COALESCE. Всичко е за получаване на първата стойност, която не е нула в списък със стойности.

Може ли да бъде по-кратко?

знам какво си мислиш. Ако SQL Server направи това по време на обработката на заявка, COALESCE трябва да е бавен. Да не говорим за многобройните изяви на CONVERT_IMPLICIT. Предпочитате ли да използвате алтернативи?

От една страна, можете сами да въведете по-кратък израз CASE. Или можете да използвате ISNULL. Повече за това по-късно. Говорейки за бавност, имах това покритие преди края на тази публикация.

Какви са разликите между COALESCE и ISNULL в SQL?

Една от алтернативите на COALESCE е ISNULL. Използването на COALESCE с 2 стойности го прави подобен на ISNULL. Поне резултатите изглеждат сходни. Все пак има забележими разлики. Можете да го използвате като ръководство, за да решите дали ще използвате COALESCE или ISNULL.

(1) ISNULL приема 2 аргумента. COALESCE приема списък с аргументи

Това е най-очевидната разлика. От синтаксиса сигурно е различно.

ISNULL ( check_expression , replacement_value )
КОАЛЕСИРАНЕ (израз [ ,…n ] )

Когато използвате и двете с 2 аргумента, резултатите са еднакви. 2-те изявления по-долу ще доведат до 1:

SELECT ISNULL(NULL, 1)
SELECT COALESCE(NULL, 1)

Въпреки че резултатите са еднакви, те се имат предвид различно:

  • ISNULL(NULL, 1) върна 1, защото първият аргумент е NULL.
  • COALESCE(NULL, 1) върна 1, защото 1 е първата ненулева стойност в списъка .

(2) COALESCE е стандарт SQL-92

Това е вярно. Можете да го проверите. Например, ако искате да пренесете своя SQL код към MySQL от SQL Server, COALESCE ще функционира по същия начин. Вижте Фигура 4 и сравнете резултата от Фигура 1:

Използването на ISNULL в MySQL обаче ще предизвика грешка, ако използвате синтаксиса на SQL Server.

например изпълнете следното в SQL Server Management Studio и MySQL Workbench:

SELECT ISNULL(null,1)

Какво стана? В SQL Server изходът е 1. Но в MySQL изходът е грешка:

06:36:52 SELECT ISNULL(null,1) Код на грешка:1582. Неправилен брой параметри в извикването на функцията „ISNULL“

Работата е там, че ISNULL в MySQL приема 1 аргумент и връща 1, ако аргументът е нулев. В противен случай връща 0.

(3) Предаването на 2 нула в COALESCE задейства грешка. Добре е с ISNULL

Това ще предизвика грешка:

SELECT COALESCE(NULL, NULL)

Грешката е:„Поне един от аргументите на COALESCE трябва да е израз, който не е NULL константа.“

Това ще бъде добре:

SELECT ISNULL(NULL, NULL)

Промяната на кода COALESCE на нещо подобно по-долу няма да предизвика грешка:

DECLARE @value INT = NULL
SELECT COALESCE(@value,null)

Това се случи, защото @value не е нулева константа.

(4) SQL COALESCE се преобразува в CASE. ISNULL остава ISNULL

Видяхме това в „Как работи COALESCE в SQL?“ раздел. Ето, нека разгледаме друг пример:

SELECT
P.LastName + ', ' + P.FirstName + ' ' + COALESCE(P.MiddleName + ' ','') AS FullName
FROM Person.Person p

Проверка на XML плана за изпълнение за скаларния оператор разкрива преобразуването в CASE:

 [AdventureWorks].[Person].[Person].[LastName] as [p].[LastName]+N', '
+[AdventureWorks].[Person].[Person].[FirstName] as [p].[FirstName]+N' '
+CASE WHEN ([AdventureWorks].[Person].[Person].[MiddleName] as [p].[MiddleName]+N' ') IS NOT NULL
      THEN [AdventureWorks].[Person].[Person].[MiddleName] as [p].[MiddleName]+N' '
      ELSE N''
 END

Сега изпълнете еквивалентна заявка, използвайки ISNULL:

SELECT
P.LastName + ', ' + P.FirstName + ' ' + ISNULL(P.MiddleName + ' ','') AS FullName
FROM Person.Person p

След това проверете XML плана за изпълнение за скаларния оператор:

 [AdventureWorks].[Person].[Person].[LastName] as [p].[LastName]+N', '
+[AdventureWorks].[Person].[Person].[FirstName] as [p].[FirstName]+N' '
+isnull([AdventureWorks].[Person].[Person].[MiddleName] as [p].[MiddleName]+N' ',N'')

ISNULL все още е ISNULL.

(5) Типът данни на резултантния израз е различен

Определянето на типа данни на резултантния израз също е различно между COALESCE и ISNULL:

  • ISNULL използва типа данни на първия параметър.
  • COALESCE връща типа данни на стойността с най-висок приоритет.

За списък с приоритет на типове данни вижте тази връзка.

Нека имаме пример:

SELECT
 employee_id
,COALESCE(CAST(weekly_rate * 4 AS MONEY),0.0000) AS monthly_rate
FROM EmployeeWages

След това проверете преобразуването в CASE в XML плана за изпълнение :

CASE WHEN CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate]
                                           *CONVERT_IMPLICIT(smallmoney,[@1],0),0) IS NOT NULL
     THEN CONVERT_IMPLICIT(numeric(19,4), CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate]
                                           *CONVERT_IMPLICIT(smallmoney,[@1],0),0),0)
     ELSE (0.0000)
END

В израза CASE по-горе, типът данни на резултата ще бъде numeric(19,4).

Защо? Той има по-висок приоритет от парите идребни пари дори и да го КАСТВАШ на пари . Защоцифрована а не пари ? Поради константата 0,0000.

В случай, че се чудите какво е @1, XML за план за изпълнение има отговора. Това е константа номер 4.

<ParameterList>
 <ColumnReference Column="@1" ParameterDataType="int" ParameterCompiledValue="(4)"  
       ParameterRuntimeValue="(4)" />
</ParameterList>

Нека опитаме с ISNULL:

SELECT
 employee_id
,ISNULL(CAST(weekly_rate * 4 AS MONEY),0.0000) AS monthly_rate
FROM EmployeeWages

Отново потърсете Скаларния оператор s ScalarString :

ISNULL(CONVERT(MONEY,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate]*($4.0000),0),($0.0000))

И накрая, типът данни на получения израз ще бъде money . Това е типът данни на първия аргумент.

Как да надхитрим приоритета на данните

Можете да „надхитрите“ приоритета на данните, като добавите няколко промени към кода си. По-рано резултатът имашечисловен тип данни. Ако искате резултатът да е впари тип данни и се отървете от CONVERT_IMPLICIT, направете следното:

SELECT
 employee_id
,COALESCE(CAST(weekly_rate AS MONEY) * ($4.0000),($0.0000)) AS monthly_rate
FROM EmployeeWages

Забелязахте ли константите ($4,000) и ($0,0000)? Това са пари константи. Какво се случва по-нататък се показва в XML плана за изпълнение s ScalarString :

CASE WHEN CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*($4.0000) IS NOT NULL 
     THEN CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*($4.0000) 
     ELSE ($0.0000) 
END

Това е много по-добре. По-кратко е и CONVERT_IMPLICIT изчезна. И полученият тип данни е пари .

(6) Допустимостта NULL на резултантния израз е различна

ISNULL(NULL, 1) и COALESCE(NULL, 1) имат сходни резултати, но техните стойности за нулиране са различни. COALESCE е нула. ISNULL не е. Можете да видите това, когато го използвате върху изчислени колони.

Нека се позоваваме на пример. Изявлението по-долу ще предизвика грешка, защото ПЪРВИЧНИЯТ КЛЮЧ не може да приеме стойности NULL. В същото време нулата на израза COALESCE за колона2 оценява на NULL.

CREATE TABLE NullabilityDemo  
(  
  column1 INTEGER NULL,  
  column2 AS COALESCE(column1, 0) PRIMARY KEY,  
  column3 AS ISNULL(column1, 0)  
);

Това изявление е успешно, защото възможността за нула на функцията ISNULL се оценява КАТО НЕ НУЛИ.

CREATE TABLE NullabilityDemo  
(  
  column1 INTEGER NULL,  
  column2 AS COALESCE(column1, 0),  
  column3 AS ISNULL(column1, 0) PRIMARY KEY  
);

(7) Левият аргумент на ISNULL се оценява веднъж. Обратното е с COALESCE

Помислете отново за предишния пример:

SELECT
    employee_id,
    COALESCE(
        hourly_rate*22.00*8.00,
        weekly_rate*4.00,
        monthly_rate
    ) AS monthly_salary
FROM
    EmployeeWages;

След това проверете ScalarString за това:

CASE WHEN CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)
                                              *(22.00)*(8.00) IS NOT NULL 
     THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),
                                              [TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)
                                              *(22.00)*(8.00),0) 
     ELSE CASE WHEN CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)
                                              *(4.00) IS NOT NULL 
               THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),
                                        [TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*(4.00),0) 
               ELSE CONVERT_IMPLICIT(numeric(23,8),[TestDatabase].[dbo].[EmployeeWages].[monthly_rate],0) 
          END 
END

Когато функцията COALESCE в SQL се преобразува в CASE, всеки израз се оценява два пъти (с изключение на последния). Както можете да видите по-горе, hourly_rate*22.00*8.00 се появи два пъти. Същото нещо с weekly_rate*4.00 . Последният израз, месечна_ставка , се появи веднъж.

Тъй като COALESCE ще оцени изразите два пъти, може да има наказание за изпълнение. Повече за това по-късно.

Все пак вижте еквивалента на ISNULL:

SELECT
 employee_id,
 ISNULL(hourly_rate * 22.00 * 8.00,ISNULL(weekly_rate * 4.00,monthly_rate)) AS  
                                                       monthly_salary
FROM EmployeeWages

След това проверяваме ScalarString в XML план за изпълнение :

isnull(CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)*(22.00)*(8.00),
       CONVERT_IMPLICIT(numeric(19,8),
isnull(CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*(4.00),
CONVERT_IMPLICIT(numeric(14,6),[TestDatabase].[dbo].[EmployeeWages].[monthly_rate],0)),0))

Както можете да видите по-горе, hourly_rate , седмична_ставка и месечна_ставка се появи само веднъж. Така че не е нужно да се притеснявате, че изразите се оценяват два пъти с ISNULL.

Можем ли да използваме COALESCE в клауза WHERE?

Дадено. Няма по-добър начин от това да покажете пример, за да докажете това.

-- Query all the names in Person table with no middle name

USE AdventureWorks
GO

SELECT
 p.LastName
,p.FirstName
FROM person.Person p
WHERE COALESCE(p.MiddleName,'') = ''

COALESCE ще върне празен низ, ако MiddleName е NULL. Разбира се, има по-кратък начин за постигане на резултата. Но това показва, че COALESCE работи в клауза WHERE.

Кое е по-бързо:COALESCE или ISNULL?

Най-накрая стигнахме до гореща тема:производителност!

Ще получите много страници с тестове и сравнения, но ще има битка на привърженици COALESCE и ISNULL в коментарите. Ще изчистим праха и дима от тези войни.

Кое е по-бързо:COALESCE или ISNULL? Нека започна с това, че отговорът е:

(търкаляне на барабани)

ЗАВИСИ!

(спусната челюст)

Разочарован? Ще го обясня след малко.

Първо, съгласен съм, че и двете изглежда имат разлики в производителността, ако използвате изминалото време като свой показател. Някои хора подкрепиха този факт, когато SQL Server превежда COALESCE в CASE изрази. Междувременно ISNULL остава както е.

Други може да разсъждават по различен начин поради различните резултати. Освен това за тях преобразуването на COALESCE в CASE е по-бързо, отколкото мигаме с очите си. Точно както е посочено в тази тема, разликата в производителността е „незначителна“. Съгласен съм. Ето още една статия, в която се казва, че разликата е „незначителна“.

Тук обаче има голяма работа:можем ли да се доверим на минимално изминало време като показател? Това, което наистина има значение, е колко логически четения има заявката. Това е, което ще посочим в следващите ни примери.

(Вижте другата ми статия за логическите четения и защо този фактор изостава във вашите заявки.)

Пример 1

Нека разгледаме същия пример и да сравним техните логически четения и планове за изпълнение. Преди да стартирате това, уверете се, че STATISTICS IO е ВКЛЮЧЕНО и Включете действителен план за изпълнение е активирана.

SET STATISTICS IO ON

SELECT
P.LastName + ', ' + P.FirstName + ' ' + COALESCE(P.MiddleName + ' ','') AS FullName
FROM Person.Person p

SELECT
P.LastName + ', ' + P.FirstName + ' ' + ISNULL(P.MiddleName + ' ','') AS FullName
FROM Person.Person p

Ето фактите:

Логическите показания и за двете заявки са еднакви. И двете са 107 * 8KB страници. Ако имаме милион записи, логическите показания ще се увеличат, разбира се. Но логическите показания и за двете заявки ще бъдат равни. Това е така, дори ако COALESCE се преобразува в CASE:

Нека разгледаме плана за изпълнение. Ето как ще го направим:

  1. Изпълнете първия оператор SELECT с израза COALESCE.
  2. Щракнете върху План за изпълнение раздел в резултатите. Щракнете с десния бутон върху него и изберете Запазване на плана за изпълнение като . И наименувайте файла plan1.sqlplan .
  3. Изпълнете втория оператор SELECT с функцията ISNULL.
  4. Щракнете върху План за изпълнение раздел в резултатите.
  5. Щракнете с десния бутон върху него и изберете Сравни Showplan .
  6. Изберете файла plan1.sqlplan . Ще се появи нов прозорец.

Ето как ще проверим плана за изпълнение за всички примери.

Връщайки се към първия ни пример, вижте Фигура 6, за да видите сравнението на плана за изпълнение:

Забелязахте ли тези важни точки на фигура 6?

  • Защрихованата част от двата плана (Индексните сканирания) означава, че SQL Server е използвал същите операции за 2-те заявки.
  • QueryPlanHash за двата плана е 0x27CEB4CCE12DA5E7, което означава, че планът е един и същ и за двата.
  • Разликите от няколко милисекунди за изминалото време са незначителни.

Вземане за вкъщи

Това е като да сравнявате ябълки с ябълки, но от различни видове. Едната е ябълка Фуджи от Япония, друга е червена ябълка от Ню Йорк. Все пак и двете са ябълки.

По същия начин SQL Server изисква същите ресурси и избрания план за изпълнение и за двете заявки. Единствената разлика е използването на COALESCE или ISNULL. Малки разлики, тъй като крайният резултат е същият.

Пример 2

Голямата разлика се появява, когато използвате подзаявка като аргумент за COALESCE и ISNULL:

USE AdventureWorks
GO

SELECT COALESCE(
       (SELECT
        SUM(th.ActualCost)
        FROM Production.TransactionHistory th
        WHERE th.ProductID = 967)
       ,0) 

SELECT ISNULL(
       (SELECT
        SUM(th.ActualCost)
        FROM Production.TransactionHistory th
        WHERE th.ProductID = 967)
       ,0)

Горният код ще има същия резултат, но вътрешността е много различна.

Нека започнем с логическите показания:

Инструкцията SELECT с израза COALESCE има двойно по-голямо логическо четене от това, което използва ISNULL.

Но защо да се удвояват логическите показания? Сравнението на плана за изпълнение ще разкрие още повече:

Фигура 8 обяснява защо логическите показания са двойни при използване на COALESCE. Вижте 2 възела Stream Aggregate в долния план:те са дубликати. Следващият въпрос е защо е дублиран?

Нека си припомним, че точката е свързана с това, когато COALESCE се преобразува в CASE. Колко пъти се оценяват изразите в аргументите? ДВА пъти!

И така, подзаявката се оценява два пъти. Показва се в плана за изпълнение с дублиращи се възли.

Това също обяснява двойните логически четения при използване на COALESCE в сравнение с ISNULL. Ако планирате да разгледате XML плана за изпълнение на заявката с COALESCE, той е доста дълъг. Но разкрива, че подзаявката ще бъде изпълнена два пъти.

Сега какво? Можем ли да надхитрим това? Разбира се! Ако някога сте се сблъсквали с нещо подобно, което според мен е рядкост, възможното решение е да разделяте и владеете. Или използвайте ISNULL, ако е само една подзаявка.

Как да избегнем двукратно оценяване на израза на подзаявката

Ето как да избегнете оценката на подзаявката два пъти:

  • Декларирайте променлива и й присвоете резултата от подзаявката.
  • След това предайте променливата като аргумент на COALESCE.
  • Повторете същите стъпки в зависимост от броя на подзаявките.

Както казах, би трябвало да е рядко, но ако се случи, знаете какво да правите сега.

Няколко думи за ниво на изолация

Оценяването на подзаявката два пъти може да причини друг проблем. В зависимост от нивото на изолация на вашата заявка, резултатът от първата оценка може да се различава от втората в многопотребителска среда. Това е лудост.

За да гарантирате връщането на стабилните резултати, можете да опитате да използвате МОМЕНТНА ИЗОЛАЦИЯ. Освен това можете да използвате ISNULL. Или може да бъде подход разделяй и владей, както беше посочено по-горе.

Вземане за вкъщи

И така, каква е същността?

  • Винаги проверявайте логическите показания. Има значение повече от изминалото време. Използвайте изминалото време и отнемете здравия си разум. Вашата машина и производствения сървър винаги ще имат различни резултати. Дайте си почивка.
  • Винаги проверявайте плана за изпълнение, за да знаете какво се случва под капака.
  • Имайте предвид, че когато COALESCE се превежда в CASE, изразите се оценяват два пъти. Тогава подзаявка или нещо подобно може да бъде проблем. Присвояването на резултата от подзаявката на променлива преди използването й в COALESCE може да бъде решение.
  • Кое е по-бързо зависи от резултатите от логическите четения и плановете за изпълнение. Няма общо правило, което да определи дали COALESCE или ISNULL е по-бърз. В противен случай Microsoft може да информира за това, както направиха в HierarchyID и SQL Graph.

В крайна сметка това наистина зависи.

Заключение

Надявам се, че ви е било полезно да прочетете тази статия. Ето точките, които обсъдихме:

  • COALESCE е един от начините за обработка на нулеви стойности. Това е предпазна мрежа за избягване на грешки в кода.
  • Приема списъка с аргументи и връща първата ненулева стойност.
  • Преобразува се в CASE израз по време на обработката на заявката, но не забавя заявката.
  • Въпреки че има някои прилики с ISNULL, има 7 забележителни разлики.
  • Може да се използва с клаузата WHERE.
  • Накрая, не е по-бързо или по-бавно от ISNULL.

Ако харесвате тази публикация, бутоните на социалните медии чакат вашето щракване. Споделянето е грижа.

Благодаря.

Прочетете също

Ефективна обработка на стойностите NULL с функцията SQL COALESCE за начинаещи

Практическа употреба на функцията SQL COALESCE


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Внедряване на отказ в MS SQL Server 2017 Standard

  2. Какво представляват ограниченията на базата данни?

  3. Използване на резултата от израз (например извикване на функция) в списък с параметри на запомнени процедури?

  4. Защо изпълнението на съхранени процедури е по-бързо от SQL заявката от скрипт?

  5. Използвайте XEvent Profiler за улавяне на заявки в SQL Server