Урок курса

Вычисляемые столбцы и функции для строк и чисел

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'?

Продолжить с проверкой и прогрессом

Откройте интерактивный раннер с заданиями урока.

Перейти к интерактивному уроку