Чи виконуються умови в SQL WHERE-перевірці в порядку їх розташування?

Зазвичай, коли я пишу програму і використовую умови, наприклад: if (${condition1} && ${condition2}), я звик ставити умови, які легше перевірити і які можуть завершити виконання раніше, на початок, а більш ресурсоємні умови — на кінець, щоб підвищити ефективність виконання.

Але чи працює це так у SQL? Чи виконуються умови в WHERE-перевірці також зліва направо? Відповідь така:

Не завжди. Це визначається планом виконання, який складає компонент під назвою Optimizer.

Цю особливість я помітив, коли на роботі змінив середовище виконання моєї збереженої процедури і отримав помилку, яку раніше не зустрічав.

Ось код, де сталася проблема:

select * from table1 t1  
inner join table2 t2 on ...  
where t1.ColName = 'ExpDatetime' --condition1  
and t2.ColValue <> '' --condition2  
and t2.ColValue < getdate() --condition3

З того, як я розташував умови, можна було б очікувати, що спочатку будуть фільтрувати записи, що задовольняють condition1, потім condition2, а вже потім — condition3. Тому що condition1 спочатку фільтрує дані, які можна перетворити на тип datetime, і лише після цього можна проводити порівняння за допомогою condition3.

Але, як я зазначив у вступі, оскільки Optimizer насправді вирішує, що виконати першим, в даному випадку він почав виконувати condition3. І це призвело до помилки Error: Conversion failed when converting date and/or time from character string, оскільки деякі значення не могли бути перетворені в datetime.

Простими словами, щоб підвищити ефективність виконання, Optimizer перетворює SQL-запит в дерево, створює кілька планів виконання і вибирає той, який, на його думку, буде найефективніший. В результаті він визначає реальний порядок виконання запиту.

Цей випадок нагадує мені, що під час написання SQL-запитів потрібно завжди подумки перевіряти, чи є залежність між умовами в WHERE, чи їх порядок виконання не призведе до помилки, щоб уникнути подібних ситуацій у майбутньому.

Ось два способи вирішення цієї проблеми:

  1. Використовувати конструкцію case when, щоб явно вказати порядок виконання умов.
  2. Виконати два етапи: спочатку отримати записи, що відповідають condition1 і condition2, і зберегти їх у тимчасовій таблиці, а потім провести порівняння для condition3 на цій таблиці.

Перекладено з: SQL Where 子句內的多條件會按照順序執行嗎?

Leave a Reply

Your email address will not be published. Required fields are marked *