Урок курса
Вычисляемые столбцы и функции для строк и чисел
SQL с нуля: бесплатный курс с практикойДо сих пор SELECT возвращал ровно те данные, которые лежат в таблице — столбец целиком, как есть. Сейчас посмотрим, что происходит, когда вместо имени столбца в SELECT стоит выражение: база данных вычислит его для каждой строки и вернёт уже готовый результат.
Арифметическое выражение в SELECT и псевдоним AS
Представьте таблицу order_items со столбцами product_id, price и quantity. Чтобы узнать сумму по каждой позиции, не нужно выгружать данные и считать вручную — достаточно написать выражение прямо в SELECT:
SELECT product_id, price * quantity FROM order_items;
СУБД пройдёт по каждой строке, перемножит price и quantity и добавит результат как отдельный столбец в итоговый набор. Строк будет ровно столько же, сколько в исходной таблице, — выражение применяется построчно.
Заголовок этого нового столбца окажется буквально price * quantity — строка из текста запроса. В небольшом скрипте это ещё терпимо, но в приложении, которое читает результат по имени столбца, или при выводе отчёта такой заголовок превращается в проблему.
Здесь в игру входит уже знакомое ключевое слово AS. Вы применяли его раньше для переименования обычных столбцов — для вычисляемых выражений оно работает абсолютно так же:
SELECT product_id, price * quantity AS сумма FROM order_items;
Теперь второй столбец в результате называется сумма. Ни синтаксис, ни порядок вычисления не меняются — AS только задаёт заголовок.
В SELECT можно использовать все стандартные арифметические операторы: +, -, *, /. Скобки тоже работают, если нужно управлять порядком операций:
SELECT product_id,
price * quantity AS сумма,
(price * quantity) * 0.1 AS налог
FROM order_items;
Оба вычисляемых столбца независимы: каждый — это отдельное выражение, которое база данных считает для каждой строки. Важно понимать, что между вычисляемыми столбцами одного SELECT нельзя ссылаться на псевдоним: написать price * quantity AS сумма, сумма * 0.1 AS налог не получится — SQLite увидит сумма как неизвестное имя столбца. Нужно повторить выражение целиком, как в примере выше.
Строковые функции UPPER, LOWER, LENGTH, TRIM в SELECT
Арифметические операторы работают с числами; для строк в SQL есть встроенные функции. Синтаксис прямой: имя функции, а в скобках — столбец или строковый литерал. Результат становится вычисляемым столбцом — всё то же самое, что с price * quantity, только вместо оператора — вызов функции.
Четыре функции, которые используются чаще всего:
UPPER(строка)— переводит латинские буквы в верхний регистр.LOWER(строка)— переводит латинские буквы в нижний регистр.LENGTH(строка)— возвращает количество символов в строке.TRIM(строка)— удаляет пробелы с левого и правого краёв строки.
Практический запрос с таблицей products, где есть столбец title:
SELECT UPPER(title) AS название_верхний,
LENGTH(title) AS длина_названия,
TRIM(title) AS название_без_пробелов
FROM products;
Каждая строка таблицы даст три вычисленных значения. LENGTH вернёт целое число — количество символов без учёта регистра и содержимого. TRIM полезен, когда название попало в таблицу с лишними пробелами: строки ' Мышь' и 'Мышь' при сравнении не совпадут, а после TRIM — совпадут.
Важное ограничение стандартной сборки SQLite: UPPER и LOWER меняют только символы ASCII-диапазона — латиницу. Кириллические буквы функция «не знает» и оставляет без изменения. Запрос SELECT UPPER('привет'); вернёт 'привет' — строку без каких-либо изменений. Это не ошибка и не сообщение — просто функция не применяется к символам вне ASCII. В других СУБД поддержка регистра вне ASCII зависит от конкретной конфигурации; для стандартной сборки SQLite важно помнить именно это ограничение.
Функции можно комбинировать в одном столбце. Например, чтобы убрать пробелы и затем привести к верхнему регистру:
SELECT UPPER(TRIM(title)) AS название_верхний FROM products;
SQLite вычислит выражение изнутри наружу: сначала TRIM(title), затем UPPER от результата. Результат в таблице не изменится — по той же причине, что и при арифметике: SELECT только читает данные.
Числовые функции ROUND и ABS; неизменность исходной таблицы после SELECT
ROUND и ABS работают по той же схеме, что строковые функции: получают выражение и возвращают преобразованное число как вычисляемый столбец.
ABS(число) снимает знак: отрицательное значение становится положительным, положительное остаётся как есть. Удобно, когда в таблице хранятся балансы или разницы, которые могут уходить в минус, а нужна только величина:
SELECT id, ABS(balance) AS остаток FROM accounts;
ROUND(число, n) округляет до n знаков после запятой. Если n равен нулю или не указан, число округляется до целого, но тип результата в SQLite остаётся REAL — то есть ROUND(2.6) вернёт 3.0, а не 3. На практике это редко мешает, но стоит иметь в виду при сравнении результатов.
SELECT price,
ROUND(price * 1.13, 2) AS цена_с_ндс
FROM products;
Здесь сначала вычисляется price * 1.13, а затем результат округляется до двух знаков. Обе операции происходят в момент исполнения запроса — в строке таблицы ничего не записывается.
И вот это — ключевой момент всего урока. Любой SELECT, сколько бы функций и выражений в нём ни стояло, только читает данные. Чтобы убедиться в этом, достаточно выполнить два запроса подряд:
SELECT price, ROUND(price * 1.13, 2) AS цена_с_ндс FROM products;
SELECT * FROM products;
Второй запрос вернёт исходные значения price — ровно такие, какими они были до первого запроса. ROUND(price * 1.13, 2) существовал только в результирующем наборе первого SELECT, нигде больше.
Это фундаментальное свойство SELECT: он работает как линза — показывает данные в нужном виде, не трогая источник. Изменить значения в таблице могут только другие команды — не те, которые мы разбираем сейчас.
Попробуйте решить
Что вернёт запрос SELECT UPPER(title) AS название FROM products; для строки с title = 'mouse'?
Продолжить с проверкой и прогрессом
Откройте интерактивный раннер с заданиями урока.
