Операторы и выражения в SQLite
При написании SQL-запросов синтаксис некоторых операторов или выражений может отличаться в разных базах данных. В SQLite тоже есть некоторые особенности, о которых я напишу в этой статье. Для получения информации использовался первоисточник: https://www.sqlite.org/lang_expr.html
SQLite понимает следующие операторы в порядке от наивысшего к низшему приоритету:
|| * / % + - << >> & | < <= > >= = == != <> IS IS NOT IN LIKE GLOB MATCH REGEXP AND OR NOT
В SQLite операторы сравнения двух значений могут быть записаны в 2 вариантах. Равенство может быть записано как = так и ==. А неравенство может быть записано != и <>.
Оператор || – означает конкатенацию (объединение) строк. При этом, если одно из значений число, оно будет преобразовано в текст и объединено с другим значением. Например, select 1||1 вернет 11.
Оператор % – означает определение остатка от деления одного значения на другое. Например, select 8%3& вернет 2.
Операторы IS и IS NOT – означают то же самое, что и операторы = и != за исключением случаев, когда одно или оба значения NULL. В этом случае если оба значения NULL, тогда IS вернет 1 (истина), а IS NOT вернет 0 (ложь). Если одно из значений NULL а другое отличное от NULL, тогда IS вернет 0 (ложь), а IS NOT вернет 1 (истина). Эти операторы используются для сравнения значений с NULL.
Оператор LIKE – осуществляет сравнение по шаблону. Значение справа от оператора LIKE должно содержать шаблон, а значение слева – строку, которая будет сравниваться. Символ процента (%) в шаблоне означает совпадение с любым количеством (в т.ч. и ноль) символов. Символ нижнее подчеркивание (_) – означает один любой символ. Замечание: оператор LIKE различает верхний и нижний регистр только для ASCII символов. Это означает, что ‘z’ LIKE ‘Z’ – истина, а ‘я’ LIKE ‘Я’ – ложь. Оператор LIKE можно сделать чувствительным к регистру использовав PRAGMA case_sensitive_like
Оператор GLOB – аналогичен оператору LIKE, но использует синтаксис как функция glob в Unix.
Оператор BETWEEN логически эквивалентен двум парным сравнениям. Выражение “x BETWEEN y AND z” будет эквивалентно “x>=y AND x<=z” за исключением только того, что значение x будет вычисляться только один раз.
Выражение CASE
Выражение (оператор) CASE имеет тот же смысл как IF THEN ELSE в языках программирования. Обычно используется для получение разных значений из разных полей базы в зависимости от условия, либо для разной сортировки в зависимости от условия. Выражение, записанное между CASE и WHEN называется “базовым”. Есть два варианта использования CASE с базовым значением и без него.
Если CASE используется без базового значения, тогда будут вычисляться все выражения после каждого WHEN. Сравнение происходит в порядке слева направо. Если ни одно сравнение WHEN не дело истину (true), тогда будет возвращено значение после ELSE. Пример:
SELECT CASE WHEN 1=2 THEN ‘a’ WHEN 1=1 THEN ‘b’ ELSE ‘c’ END – вернет значение “b”.
Если CASE используется с базовым значением, тогда базовое значение будет вычислено один раз и результат будет сравниваться с каждым выражением после WHEN. Если ни одно из значений после WHEN не совпало с базовым и есть оператор ELSE, будет возращено значение после ELSE. Если оператора ELSE нет и ни одно из значений WHEN не совпало с базовым, будет возвращено NULL. Пример:
SELECT 1 CASE WHEN 2 THEN ‘a’ WHEN 1 THEN ‘b’ ELSE ‘c’ END – вернет значение “b”.
Если базовое значение будет NULL, тогда результат всегда будет значением после ELSE, если оно есть или NULL, если нет.
Еще несколько примеров оператора условия CASE можете посмотреть здесь.
Операторы IN и NOT IN
Операторы IN и NOT IN сравнивают значение слева от оператора со списком значений справа от него. В случае, если в качестве списка значений используется подзапрос, тогда он должен возвращать столько же колонок, что и имеет выражение слева. Если в правой части написано название таблицы, тогда это будет эквивалентно select * from table (table – название таблицы).
Оператор EXISTS
Оператор EXISTS всегда возвращает одно из двух значений 0 (ложь) или 1 (истина). Если в правом выражении используется подзапрос, возвращающий одно или более значений, тогда оператор EXISTS вернет 1 (истина). Если подзапрос в выражении справа не возвращает ни одной строки, тогда EXISTS вернет 0 (ложь).
Количество возвращаемых подзапросом столбцов не имеет значения. Так же не имеет значения есть ли в возвращаемых столбцах NULL значения.
Выражение CAST
Выражение CAST(X AS Y) позволяет преобразовать (конвертировать) данные X в данные другого типа Y. Если значение X равно NULL, результат тоже будет NULL. Преобразование возможно в следующие типы данных:
NONE |
Преобразование значения без указания типа приводит к преобразованию в тип BLOB.
|
TEXT |
Преобразование BLOB к тексту происходит так что последовательности байтов, составляющих BLOB объект, интерпретируется как текст, закодированный с использованием кодировки базы данных.
Преобразование INTEGER или REAL в TEXT приводит к отображению результата как если бы применялась функция sqlite3_snprintf() за исключением того что TEXT будет в кодировке соединения с базой данных
|
REAL |
Если преобразуемое значение BLOB, тогда оно сначала преобразуется в TEXT, а затем происходит дальнейшая конвертация.
Если TEXT преобразовывается в REAL, используется максимальное количество символов в начале тексте, способных быть представленными как число.
|
INTEGER |
Если преобразуемое значение BLOB, тогда оно сначала преобразуется в TEXT, а затем происходит дальнейшая конвертация.
Если TEXT преобразовывается в INTEGER, использется максимальное количество символов в начале тексте, способных быть представленными как число. Остальные символы игнорируются. Начальные пробелы так же игнорируются. Если в начале текста нет символов, которые можно представить как число, тогда возвращается значение 0. Если значение превышает +9223372036854775807, тогда возвращается 9223372036854775807 и соответственно, если меньше чем -9223372036854775808, тогда возвращается -9223372036854775808.
Если преобразуемое значение выглядит как число с плавающей точкой с показателем степени, тогда степень игнорируется.
|
NUMERIC |
Преобразование TEXT или BLOB значения в NUMERIC приводит сначала к преобразованию в REAL, а затем преобразованию в INTEGER, если только преобразование из REAL в INTEGER происходит без потерь и обратимо. В этом и есть отличие от преобразования в INTEGER – преобразование в NUMERIC происходит только в случае если нет потерь при преобразовании.
|
Урок 3. Порядок AND и OR
При использовании в SELECT-запросах операторов OR и AND можно легко ошибиться в составлении логического выражения. И проблема таких ошибок в том, что запрос выполняется как будто ошибки нет, но данные выводятся неверные.
Если у вас мало опыта в написании таких SQL-запросов, то можно легко не заметить проблему. Давайте разберем несколько популярных ошибок.
Работать будем с таблицей team, которая содержит список разработчиков:
id | first_name | last_name | language | level |
---|---|---|---|---|
1 | Дмитрий | Васильев | python | junior |
2 | Валерий | Юрьев | php | middle |
3 | Андрей | Ушаков | python | senior |
4 | Петр | Кузуб | javascript | junior |
5 | Наталья | Кузнецова | python | middle |
6 | Руслан | Исаков | php | senior |
7 | Сергей | Медведев | php | junior |
8 | Алексей | Борисов | python | middle |
9 | Валерия | Маркова | javascipt | senior |
Каждый разработчик оценивается project-менеджером по двум критериям, после чего он отбирает программиста на тот или иной проект. Основные критерии — это уровень владения технологией: junior, middle или senior, и базовый язык программирования, на котором пишет разработчик.
Нам как менеджерам поступает заявка на разработку проекта и на основании этой заявки мы должны подобрать необходимых разработчиков.
Представьте, что сейчас нас интересуют только мидллы и сеньоры. Напишем SQL-запрос:
SELECT * FROM team WHERE level = 'middle' AND level = 'senior'
После выполнения запроса мы увидим пустую таблицу.
id | first_name | last_name | language | level |
---|
И тут мы столкнулись с первой ошибкой. В нашем запросе база данных по очереди берет строку и проверяет находится ли в колонке level значение “middle” И значение “senior”. Оператор AND — это условие одновременности. То есть исходя из нашего запроса в поле level должно находится одновременно и “middle”, и “senior”, что невозможно, так разработчик может быть только одного уровня.
Почему мы допустили такую ошибку? И дело в формулировках, когда я озвучивал задание, то сказал, что нас интересуют только мидлы И сеньоры. Это правильное выражение с точки зрения русского языка, но неверное с точки зрения логики. Чтобы получить верный результат надо чтобы поле level содержало ИЛИ “middle”, ИЛИ “senior”. Поэтому заменим AND на OR:
SELECT * FROM team WHERE level = 'middle' OR level = 'senior'
Теперь разработчики подобраны верно:
id | first_name | last_name | language | level |
---|---|---|---|---|
2 | Валерий | Юрьев | php | middle |
3 | Андрей | Ушаков | python | senior |
5 | Наталья | Кузнецова | python | middle |
6 | Руслан | Исаков | php | senior |
8 | Алексей | Борисов | python | middle |
9 | Валерия | Маркова | javascipt | senior |
Такую ошибку легко допустить, если в формулировке задачи стоит союз И. Но не стоит его напрямую переносить в SQL-запрос. Возможно здесь кроется ошибка, особенно если мы сравниваем с одним полем.
Давайте рассмотрим другой случай. На этот раз нам нужно разработать бэкенд для сайта. И для этого нам нужны все Python и PHP разработчики. Напишем:
SELECT * FROM team WHERE basic_language = 'Python' OR basic_language = "PHP"
Обратите внимание, что нужны нам все Python И PHP разработчики, но пишем мы OR. После выполнения запроса мы получим такую таблицу:
id | first_name | last_name | language | level |
---|---|---|---|---|
1 | Дмитрий | Васильев | python | junior |
2 | Валерий | Юрьев | php | middle |
3 | Андрей | Ушаков | python | senior |
5 | Наталья | Кузнецова | python | middle |
6 | Руслан | Исаков | php | senior |
7 | Сергей | Медведев | php | junior |
8 | Алексей | Борисов | python | middle |
В итоговую таблицу попали и те и другие программисты. Отлично. Но давайте расширим условие. Скажем, нам нужны только middle разработчики на этих языках. Добавим:
SELECT * FROM team WHERE basic_language = 'Python' OR basic_language = "PHP" AND level = "middle"
После выполнения мы получим такую таблицу:
id | first_name | last_name | language | level |
---|---|---|---|---|
1 | Дмитрий | Васильев | python | junior |
2 | Валерий | Юрьев | php | middle |
3 | Андрей | Ушаков | python | senior |
5 | Наталья | Кузнецова | python | middle |
8 | Алексей | Борисов | python | middle |
И результат довольно странный, в итоговой таблице присутствуют также джуниоры и сеньоры. И дело в том, что операторы OR и AND имеют приоритет выполнения и у AND он выше. Поэтому в первую очередь база данных находит всех мидлов, которые пишут на PHP. Такому условию соответствует только одна запись, а далее срабатывает оператор OR, который добавляет всех Python-разработчиков.
То есть мы ищем ИЛИ мидлов на PHP, ИЛИ Python-разработчиков без указания их уровня владения языком. Поэтому в таблицу также попали джуниоры и сеньоры.
Чтобы решить поставленную задачу, нужно четко расставить приоритет с помощью скобок. Как в математике. Поместим скобки справа и слева от OR:
SELECT * FROM team WHERE (basic_language = 'Python' OR basic_language = "PHP") AND level = "middle"
Теперь в таблице остались только мидлы на Python и PHP:
id | first_name | last_name | language | level |
---|---|---|---|---|
2 | Валерий | Юрьев | php | middle |
5 | Наталья | Кузнецова | python | middle |
8 | Алексей | Борисов | python | middle |
Каждый раз когда в одном запросе встречаются OR и AND, обращайте внимание на порядок выполнения, иначе можно легко получить неверные данные.
Вообще, даже не так, каждый раз когда у вас есть в запросе есть OR и AND применяйте скобки для расстановки приоритетов, даже если уверены в своём коде.
Такая практика позволит избежать неприятных логических ошибок.
Следующий урок
Урок 4. Сортировка результатов
В этом уроке вы научитесь сортировать итоговые результаты в возрастающем и убывающем порядке с помощью ORDER BY.
Посмотреть
Без воды
Поддержка
Регистрация
Письмо со ссылкой для доступа отправлено.
Проверьте почту.
Письмо не пришло? Посмотрите в спаме.
Регистрируясь, вы соглашаетесь с
условиями предоставления услуг (пользовательское соглашение).
ПОКА (Transact-SQL) — SQL Server
Редактировать
Твиттер
Фейсбук
Электронная почта
- Статья
Применяется к: SQL Server Azure SQL База данных Azure SQL Управляемый экземпляр Azure Synapse Analytics Analytics Platform System (PDW)
Задает условие для повторного выполнения оператора SQL или блока операторов. Операторы выполняются многократно, пока заданное условие истинно. Выполнение операторов в цикле WHILE можно контролировать изнутри цикла с помощью ключевых слов BREAK и CONTINUE.
Соглашения о синтаксисе Transact-SQL
Синтаксис
-- Синтаксис для SQL Server и базы данных SQL Azure WHILE Boolean_expression { sql_statement | блок_операторов | ПЕРЕРЫВ | ПРОДОЛЖАТЬ }
-- Синтаксис для Azure Azure Synapse Analytics и хранилища параллельных данных WHILE Boolean_expression { sql_statement | блок_операторов | ПЕРЕРЫВ }
Примечание
Чтобы просмотреть синтаксис Transact-SQL для SQL Server 2014 и более ранних версий, см. документацию по предыдущим версиям.
Аргументы
Boolean_expression
Выражение, возвращающее TRUE или FALSE . Если логическое выражение содержит оператор SELECT, оператор SELECT должен быть заключен в круглые скобки.
{ sql_statement | statement_block }
Любой оператор Transact-SQL или группа операторов, определенная с помощью блока операторов. Чтобы определить блок операторов, используйте ключевые слова управления потоком BEGIN и END.
BREAK
Вызывает выход из самого внутреннего цикла WHILE. Любые операторы, которые появляются после ключевого слова END, обозначающего конец цикла, выполняются.
CONTINUE
Вызывает перезапуск цикла WHILE, игнорируя все операторы после ключевого слова CONTINUE.
Если два или более цикла WHILE вложены друг в друга, внутренний BREAK переходит к следующему самому внешнему циклу. Сначала выполняются все операторы после окончания внутреннего цикла, а затем перезапускается следующий внешний цикл.
Примеры
A. Использование BREAK и CONTINUE с вложенными IF…ELSE и WHILE
В следующем примере, если средняя прейскурантная цена продукта меньше $300
, цикл WHILE
удваивает цены, а затем выбирает максимальная цена. Если максимальная цена меньше или равна $500
, цикл WHILE
перезапускается и снова удваивает цены. Этот цикл продолжает удваивать цены до тех пор, пока максимальная цена не превысит $ 500
, а затем выходит из 9-го диапазона.0065 ПОКА цикл и печатает сообщение.
ИСПОЛЬЗОВАТЬ AdventureWorks2012; ИДТИ ПОКА (ВЫБЕРИТЕ СРЕДНЮЮ (ListPrice) ИЗ Production.Product) < $300 НАЧИНАТЬ ОБНОВЛЕНИЕ Производство.Продукт УСТАНОВИТЬ СписокЦена = СписокЦена * 2 SELECT MAX (ListPrice) FROM Production.Product ЕСЛИ (ВЫБЕРИТЕ МАКС.(СписокЦен) ИЗ Производство.Продукт) > 500 долл. США ПЕРЕРЫВ ЕЩЕ ПРОДОЛЖАТЬ КОНЕЦ PRINT «Слишком много для рынка»;
B.
Использование WHILE в курсоре
В следующем примере используется @@FETCH_STATUS
для управления действиями курсора в цикле WHILE
.
ОБЪЯВИТЬ @EmployeeID как NVARCHAR(256) DECLARE @Title как NVARCHAR(50) DECLARE Employee_Cursor CURSOR ДЛЯ ВЫБЕРИТЕ LoginID, JobTitle ОТ AdventureWorks2012.HumanResources.Employee ГДЕ JobTitle = 'Специалист по маркетингу'; ОТКРЫТЬ Сотрудник_Курсор; FETCH NEXT FROM Employee_Cursor INTO @EmployeeID, @Title; ПОКА @@FETCH_STATUS = 0 НАЧИНАТЬ Вывести ' ' + @EmployeeID + ' '+ @Title FETCH NEXT FROM Employee_Cursor INTO @EmployeeID, @Title; КОНЕЦ; ЗАКРЫТЬ Сотрудник_Курсор; DEALLOCATEEmployee_Cursor; ИДТИ
Примеры: Azure Synapse Analytics and Analytics Platform System (PDW)
C: Простой цикл While
В следующем примере, если средняя прейскурантная цена продукта меньше 300 долларов США цены, а затем выбирает максимальную цену. Если максимальная цена меньше или равна
, а затем выходит из цикла $500
, цикл WHILE
перезапускается и снова удваивает цены. Этот цикл продолжает удваивать цены до тех пор, пока максимальная цена не превысит 9.0065 $500
WHILE
.
-- Использует AdventureWorks ПОКА (ВЫБРАТЬ AVG(ListPrice) FROM dbo.DimProduct) < $300 НАЧИНАТЬ ОБНОВЛЕНИЕ dbo.DimProduct УСТАНОВИТЬ СписокЦена = СписокЦена * 2; ВЫБЕРИТЕ МАКСИМАЛЬНОЕ (ListPrice) ИЗ dbo.DimProduct ЕСЛИ ( ВЫБЕРИТЕ МАКСИМАЛЬНУЮ (ListPrice) ИЗ dbo.DimProduct) > 500 долларов США ПЕРЕРЫВ; КОНЕЦ
См. также
ALTER TRIGGER (Transact-SQL)
Язык управления потоком (Transact-SQL)
CREATE TRIGGER (Transact-SQL)
Курсоры (Transact-SQL)
SELECT (Transact-SQL)
Оператор SQL Server IF ELSE в примерах
Резюме : в этом руководстве вы изучите оператор SQL Server IF...ELSE
для управления потоком программы.
Оператор IF...ELSE
— это оператор потока управления, который позволяет выполнять или пропускать блок операторов на основе заданного условия.
Оператор IF
Ниже показан синтаксис оператора IF
:
IF boolean_expression НАЧИНАТЬ { блок_операторов } КОНЕЦ Язык кода: SQL (язык структурированных запросов) (sql)
В этом синтаксисе, если Boolean_expression
оценивается как TRUE
, то выполняется блок_операторов
в блоке BEGIN...END
. В противном случае блок _операторов
пропускается, а управление программой передается оператору после 9.0065 КОНЕЦ ключевое слово.
Обратите внимание, что если логическое выражение содержит оператор SELECT
, вы должны заключить оператор SELECT
в круглые скобки.
Следующий пример сначала получает сумму продаж из таблицы sales.order_items
в образце базы данных, а затем выводит сообщение, если сумма продаж превышает 1 миллион.
НАЧАЛО DECLARE @sales INT; ВЫБИРАТЬ @продажи = СУММ(цена_списка * количество) ОТ sales.order_items я ВНУТРЕННЕЕ СОЕДИНЕНИЕ sales.orders o ON o.order_id = i.order_id ГДЕ ГОД(дата_заказа) = 2018; ВЫБЕРИТЕ @продажи; ЕСЛИ @продажи > 1000000 НАЧИНАТЬ ПЕЧАТЬ 'Отлично! Сумма продаж в 2018 году превышает 1 000 000; КОНЕЦ КОНЕЦ Язык кода: SQL (язык структурированных запросов) (sql)
Вывод блока кода:
Отлично! Сумма продаж в 2018 году превышает 1 000 000 Язык кода: SQL (язык структурированных запросов) (sql)
Обратите внимание, что вам нужно щелкнуть вкладку Сообщения , чтобы увидеть приведенное выше выходное сообщение:
Оператор
IF ELSE
Когда условие в ЕСЛИ предложение
оценивается как FALSE
, и вы хотите выполнить другой блок операторов, вы можете использовать ИНАЧЕ
пункт.
Ниже показан оператор IF ELSE
:
IF Boolean_expression НАЧИНАТЬ -- Блок операторов выполняется, когда логическое выражение равно TRUE КОНЕЦ ЕЩЕ НАЧИНАТЬ -- Блок инструкций выполняется, когда логическое выражение равно FALSE КОНЕЦ Язык кода: SQL (язык структурированных запросов) (sql)
Каждый оператор IF
имеет условие. Если условие оценивается как
TRUE
, тогда блок операторов в Пункт IF
выполнен. Если условие FALSE
, то выполняется кодовый блок в предложении ELSE
.
См. следующий пример:
НАЧАЛО DECLARE @sales INT; ВЫБИРАТЬ @продажи = СУММ(цена_списка * количество) ОТ sales.order_items я ВНУТРЕННЕЕ СОЕДИНЕНИЕ sales.orders o ON o.order_id = i.order_id ГДЕ ГОД(дата_заказа) = 2017; ВЫБЕРИТЕ @продажи; ЕСЛИ @продажи > 10000000 НАЧИНАТЬ ПЕЧАТЬ 'Отлично! Сумма продаж в 2018 году превышает 10 000 000; КОНЕЦ ЕЩЕ НАЧИНАТЬ PRINT 'Объем продаж в 2017 году не достиг 10 000 000'; КОНЕЦ КОНЕЦ Язык кода: SQL (язык структурированных запросов) (sql)
В этом примере:
Во-первых, следующий оператор устанавливает общий объем продаж в 2017 году в переменную @sales
:
SELECT @продажи = СУММ(цена_списка * количество) ОТ sales.order_items я ВНУТРЕННЕЕ СОЕДИНЕНИЕ sales.orders o ON o.order_id = i.order_id ГДЕ ГОД(дата_заказа) = 2017; Язык кода: SQL (язык структурированных запросов) (sql)
Во-вторых, этот оператор возвращает продажи на выходе:
ВЫБЕРИТЕ @продажи; Язык кода: SQL (язык структурированных запросов) (sql)
Наконец, условие IF
проверяет, превышает ли сумма продаж в 2017 году 10 миллионов. Поскольку сумма продаж меньше этой суммы, выполняется блок операторов в предложении ELSE
.
ЕСЛИ @продажи > 10000000 НАЧИНАТЬ ПЕЧАТЬ 'Отлично! Сумма продаж в 2018 году превышает 10 000 000; КОНЕЦ ЕЩЕ НАЧИНАТЬ PRINT 'Объем продаж в 2017 году не достиг 10 000 000'; КОНЕЦ Язык кода: SQL (язык структурированных запросов) (sql)
Ниже показаны выходные данные:
Сумма продаж не достигла 10 000 000 Язык кода: SQL (язык структурированных запросов) (sql)
Вложенный
IF.
..ELSE
SQL Server позволяет вкладывать оператор IF...ELSE
в другой оператор IF...ELSE
, см. следующий пример:
BEGIN ОБЪЯВИТЬ @x INT = 10, @у ИНТ = 20; ЕСЛИ (@x > 0) НАЧИНАТЬ ЕСЛИ (@x < @y) PRINT 'x > 0 и x < y'; ЕЩЕ PRINT 'x > 0 и x >= y'; КОНЕЦ КОНЕЦ Язык кода: SQL (язык структурированных запросов) (sql)
В этом примере:
Сначала объявите две переменные @x и @y и установите их значения равными 10 и 20 соответственно:
DECLARE @x INT = 10 , @у ИНТ = 20; Язык кода: SQL (язык структурированных запросов) (sql)
Во-вторых, вывод IF
проверяет, больше ли @x
нуля. Поскольку для @x
установлено значение 10, условие ( @x > 10
) выполняется. Таким образом, вложенные Выполняется оператор IF
.
Наконец, вложенный оператор IF
проверяет, меньше ли @x, чем @y ( @x < @y
).