Використання ISNULL проти використання COALESCE для перевірки конкретного стану?


74

Я знаю, що можна передавати декілька параметрів COALESCE, але коли ви хочете перевірити лише один вираз, щоб побачити, чи не існує він, ви використовуєте за замовчуванням чи це краща практика використовувати ISNULLзамість цього?

Чи є підвищення продуктивності між ними?


5
У документації COALESCE є така примітка: ISNULL і COALESCE, хоча і еквівалентні, можуть поводитися по-різному. Вираз, що включає ISNULL з ненульовими параметрами, вважається NOT NULL, тоді як вирази, що включають COALESCE з ненульовими параметрами, вважаються NULL ...

3
ISNULLтакож приведе результат до типу даних першого виразу, як показано тут
Мартін Сміт

4
У цій статті досить добре викладені відмінності ... sqlmag.com/t-sql/coalesce-vs-isnull
Масажист даних

Це також хороша стаття ... mssqltips.com/sqlservertip/2689/…
goodeye

Відповіді:


58

Ця проблема, про яку повідомляється в Microsoft Connect, виявляє деякі відмінності між COALESCEта ISNULL:

рання частина нашої обробки переписує COALESCE( expression1, expression2 )як CASE WHEN expression1 IS NOT NULL THEN expression1 ELSE expression2 END. У цьому прикладі:

COALESCE ( ( SELECT Nullable
             FROM Demo
             WHERE SomeCol = 1 ), 1 )

ми генеруємо:

SELECT CASE
          WHEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) IS NOT NULL
          THEN (SELECT Nullable FROM Demo WHERE SomeCol = 1)
          ELSE 1
       END

Пізніші етапи обробки запитів не розуміють, що два підзапити спочатку були однаковим виразом, тому вони виконують підзапит двічі ...

Одним із обхідних шляхів, хоч я і ненавиджу це пропонувати, є перехід COALESCEна ISNULL, оскільки останній не дублює підзапит.


2
Швидке запитання, якщо у вас є 3 значення, такі як злиття (вираз1, вираз2, вираз3, 1), де ці `` вирази '' насправді є операторами вибору, чи було б тоді сенсом фактично виконувати вкладені інульові оператори? тобто isnull (вираз1, isnull (вираз2, isnull (вираз3, 1)))
ganders

25

Я думаю, що ні, але COALESCE відповідає стандарту SQL '92 і підтримується різними базами даних. Якщо ви хочете переносити, не використовуйте ISNULL.


@AaronAnodide MySQL використовує ifnullсервер sql isnull.
nawfal

12

У COALESCE ви можете мати кілька виразів, де, як і в ISNULL, ви можете перевірити лише один вираз

COALESCE ( expression [ ,...n ] ) 

ISNULL ( check_expression , replacement_value )

8

Варто зазначити, що обробка типів між ними також може змінити ситуацію (див. Відповідний пункт відповіді (2) ).

Скажімо, запит намагається використовувати ярлик для написання нульового порівняння:

select * from SomeTable
 where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);

що відрізняється від

select * from SomeTable
 where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);

Оскільки в першому випадку IsNull () змушує тип бути бітом (так -1 перетворюється на істинний), тоді як другий випадок буде підвищувати обидва до int.

with input as 
(
  select convert(bit, 1) as BitOn,      
         convert(bit, 0) as BitOff,
         convert(bit, null) as BitNull
)
select BitOn, 
       BitOff,
       BitNull,
       IsNull(BitOn, -1) IsNullBitOn,         -- true
       IsNull(BitOff, -1) IsNullBitOff,       -- false
       IsNull(BitNull, -1) IsNullBitNull,     -- true, converts the -1 to bit
       coalesce(BitOn, -1) CoalesceBitOn,     -- 1
       coalesce(BitOff, -1) CoalesceBitOff,   -- 0       
       coalesce(BitNull, -1) CoalesceBitNull  -- -1
  from input;

Існує подібний коментар / посилання (@Martin Smith) щодо самого питання.


7

Одне головне, що я не бачу явно вказаним, - це те ISNULL, що тип виводу аналогічний першому виразу, але разом з COALESCEним повертає тип даних значення найвищого пріоритету.

DECLARE @X VARCHAR(3) = NULL
DECLARE @Y VARCHAR(10) = '123456789'
/* The datatype returned is similar to X, or the first expression*/
SELECT ISNULL(@X, @Y) ---> Output is '123'
/* The datatype returned is similar to Y, or to the value of highest precedence*/
SELECT COALESCE(@X, @Y) ---> Output is '123456789'

3
Це не питання виразу перший проти другого / N-го. Дивіться тут :ISNULL uses the data type of the first parameter, COALESCE follows the CASE expression rules and returns the data type of value with the highest precedence.
underscore_d

5

NULLІ COALESCEне завжди взаємозамінні. Він заслуговує на знання їх відмінностей, щоб знати, коли краще використовувати одне над іншим:

введіть тут опис зображення

У таблиці вище порівняння ISNULLі COALESCEз Exam Ref 70-761 Querying Data with Transact-SQLкниги , написаної Іцик Бен-Ган.


  1. Кількість підтримуваних параметрів - 2для ISNULLпроти >2при використанніCOALESCE
  2. ISNULLє власною функцією T-SQL і COALESCEє стандартом ISO / ANSI SQL
  3. Тип даних результату є важливим. Прочитавши примітки у таблиці вище, перевірте такі випадки:

    DECLARE @x VARCHAR(3)  = NULL
           ,@y VARCHAR(10) = '1234567890';
    
    SELECT ISNULL(@x, @y) AS [ISNULL], COALESCE(@x, @y) AS [COALESCE];
    

    введіть тут опис зображення

    ISNULLОтримує тип даних перший аргумент , оскільки це не NULLбуквально. Це VARCHAR(3)і є результатом, дані другого аргументу вирізаються відповідно до них. З COALESCEтипом даних, якщо використовується найвищий пріоритет.

    DECLARE @x VARCHAR(8)  = '123x5'
           ,@y INT = 123;
    
    SELECT ISNULL(@x, @y) AS [ISNULL];
    SELECT COALESCE(@x, @y) AS [COALESCE];
    

    введіть тут опис зображення

    введіть тут опис зображення

    ISNULLПовертає тип даних першого аргументу, в той час як COALESCEми отримуємо помилку, так як INTмає самий високий пріоритет і перетворення першого значення аргументу в INTзазнає невдачі.

  4. Недійсність результату також може бути важливою. Наприклад:

    DECLARE @x VARCHAR(3) = NULL
           ,@y VARCHAR(3) = NULL;
    
    DROP TABLE IF EXISTS [dbo].[DataSource01];
    
    SELECT ISNULL(10, 20) AS [C1]
          ,ISNULL(@x, 'text') AS [C2]
          ,ISNULL(@x, @y) AS [C3]
    INTO [dbo].[DataSource01];
    
    DROP TABLE IF EXISTS [dbo].[DataSource02];
    
    SELECT COALESCE(10, 20) AS [C1]
          ,COALESCE(@x, 'text') AS [C2]
          ,COALESCE(@x, @y) AS [C3]
    INTO [dbo].[DataSource02];
    

    Давайте перевіримо Nullableвластивість кожного стовпця:

    введіть тут опис зображення

    введіть тут опис зображення

    Використовуючи COALESCEми маємо NOT NULLвластивість стовпця, встановлене на Yes, лише тоді, коли всі входи не мають нульового значення.

  5. Відповідно до стандарту SQL COALESCEвираз перекладається на:

    CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
    

    Якщо результат виконання підзапиту в реченні WHEN не має значення NULL, SQL Server виконує його вдруге в реченні THEN. Іншими словами, у такому випадку він виконує його двічі. Тільки якщо результат виконання в реченні WHEN має значення NULL, SQL Server не виконує підзапит знову, а повертає вираз ELSE. Отже, при використанні підзапитів функція ISNULL має перевагу в продуктивності.


2

Там, де є лише одна нульова умова, ISNULLбуде менше витрат. Однак різниця, мабуть, незначна.


1
Чи маєте ви підтримку твердження, що накладні витрати менші ISNULL?
Джошуа Дрейк

1
@JoshuaDrake: Є дві сфери, де COALESCEможна ввести більше накладних витрат при взаємозамінному використанні. По-перше, мова ISNULLйде про фіксовану кількість входів, де COALESCEпризначена робота з будь-якою кількістю входів. По-друге, COALESCEналаштовано на повернення типу даних виразу з найвищим пріоритетом типу даних, тоді як ISNULLповертає той самий тип, що і check_expression. Як я вже говорив вище, у пізніших версіях SQL Server різниця, ймовірно, незначна, але, строго кажучи, все ще є накладні витрати.
Джеймс Джонсон,

2

Це пояснення дає чітке уявлення про злиття та відсутність

Функція COALESCE в SQL повертає перший вираз, що не має значення NULL, серед своїх аргументів. Синтаксис для COALESCE такий:

 COALESCE ("expression 1", "expressions 2", ...)

Це те саме, що і наступне твердження CASE:

SELECT CASE ("column_name")
  WHEN "expression 1 is not NULL" THEN "expression 1"
  WHEN "expression 2 is not NULL" THEN "expression 2"
  ...
  [ELSE "NULL"]
  END
FROM "table_name";

У SQL Server функція ISNULL () використовується для заміни значення NULL іншим значенням.

select CountryName = ISNULL("columnname", 'INDIA') from Countries

Coalesce повертає перший ненульовий вираз, де як isnull () використовується для заміни нульового значення нашим бажаним значенням.

COALESCE є частиною стандартів ANSI і доступний майже у всіх базах даних.

при виборі рішення ISNULL проти COALESCE слід враховувати параметри:

  1. COALESCE визначає тип вихідних даних на основі пріоритету типу даних, де як у випадку ISNULL, на тип даних не впливає пріоритет типу даних.
  2. Розглянемо наступні оператори sql

    DECLARE @c5 VARCHAR(5);
    SELECT 'COALESCE', COALESCE(@c5, 'longer name')
    UNION ALL
    SELECT 'ISNULL',   ISNULL(@c5,   'longer name');
    

Результати:

COALESCE longer name
ISNULL   longe

Це відбувається тому, що ISNULL приймає тип даних першого аргументу, тоді як COALESCE перевіряє всі елементи та вибирає найкращий варіант (у цьому випадку VARCHAR (11))

Для більш детального пояснення щодо вибору між COALESCE та ISNULL перевірте це: https://www.mssqltips.com/sqlservertip/2689/deciding-between-coalesce-and-isnull-in-sql-server/


-2

У COALESCE можна використовувати декілька виразів, він поверне значення, яке не є нульовим і виникає першим ... наприклад

DECLARE @Value1 INT, @Value2 INT, @Value3 INT, @Value4 INT
SELECT @Value2 = 2, @Value4 = 4
SELECT COALESCE(@Value1, @Value2, @Value3, @Value4)
SELECT COALESCE(@Value1, @Value4, @Value3, @Value2)

І в ISNULL, якщо вираз null, він поверне вказаний другий параметр, і, звичайно, ви можете перевірити лише один вираз ...

Отже, якщо ви хочете перевірити кілька виразів і вибрати спочатку не null серед них, то використовуйте coalesce, інакше перейдіть до ISNULL


2
OP заявив, що їм відомо про здатність COALESCE обробляти кілька параметрів, питання полягає в конкретному випадку, коли їх є лише два.
Джошуа Дрейк

@JoshuaDrake, будь ласка, прочитайте повну відповідь ... Я прочитав питання і прошу вас прочитати мою відповідь повністю ... Дуже легко переглядати якийсь момент і голосувати
проти
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.