Раздел 35 · SQLite с нуля

SELECT, столбцы и псевдонимы

junior~20 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке ты создал первую таблицу и достал из неё всё через SELECT *. Звёздочка удобна, когда смотришь на таблицу впервые. Но в работе почти всегда нужна не вся таблица, а несколько столбцов, иногда пересчитанных и под понятными заголовками. Этот урок про то, как сказать базе, что именно показать.

Витрина вместо склада

Представь склад кофейни. На полках лежит всё: зерно, сиропы, стаканы, коробки с салфетками, старая кофемашина. Гостю склад не показывают. Ему показывают витрину: на ней только то, что нужно сейчас, разложено в нужном порядке и подписано понятными ценниками.

Таблица это склад. Список после слова SELECT это витрина: ты выбираешь, какие столбцы выставить, в каком порядке и с какими подписями. Сама таблица при этом не меняется, SELECT только читает.

Звёздочка: показать всё

Начнём со склада целиком. Звёздочка после SELECT значит «все столбцы в том порядке, в каком они объявлены в таблице»:

sqlite> SELECT * FROM drinks;
╭────┬────────────────┬──────────┬───────┬────────╮
│ id │      name      │ category │ price │ volume │
╞════╪════════════════╪══════════╪═══════╪════════╡
│  1 │ Эспрессо       │ кофе     │   120 │     40 │
│  2 │ Американо      │ кофе     │   150 │    250 │
│  3 │ Капучино       │ кофе     │   190 │    300 │
│  4 │ Латте          │ кофе     │   210 │    400 │
│  5 │ Раф            │ кофе     │   240 │    350 │
│  6 │ Какао          │ другое   │   180 │ 300 мл │
│  7 │ Чай с чабрецом │ чай      │   130 │    500 │
│  8 │ Матча-латте    │ чай      │ NULL  │    350 │
│  9 │ Тархун         │ холодное │   200 │    0.5 │
╰────┴────────────────┴──────────┴───────┴────────╯

Девять напитков, пять столбцов. Заметь неровности, о которых шла речь в уроке про типы: у Матча-латте нет цены (NULL), объём Какао записан строкой, а Тархун измерен в литрах. Мы будем натыкаться на них весь раздел.

Список столбцов

Чтобы показать только название и цену, перечисли столбцы через запятую. Такой выбор столбцов называют проекцией, подробнее про неё в теоретическом уроке:

sqlite> SELECT name, price FROM drinks;
╭────────────────┬───────╮
│      name      │ price │
╞════════════════╪═══════╡
│ Эспрессо       │   120 │
│ Американо      │   150 │
│ Капучино       │   190 │
│ Латте          │   210 │
│ Раф            │   240 │
│ Какао          │   180 │
│ Чай с чабрецом │   130 │
│ Матча-латте    │ NULL  │
│ Тархун         │   200 │
╰────────────────┴───────╯

Порядок столбцов в ответе тот, что ты написал, а не тот, что в таблице. Один и тот же столбец можно упомянуть дважды, база не возразит. Опечатку в имени она уже не простит:

sqlite> SELECT name, nme FROM drinks;
Parse error near line 1: no such column: nme
  SELECT name, nme FROM drinks;
               ^--- error here

Ошибка честная: столбца nme нет, и стрелка показывает, где именно споткнулся разбор. Читай такие сообщения целиком, в них почти всегда есть ответ.

Выражения вместо столбцов

В списке SELECT можно писать не только имена столбцов, но и выражения: арифметику, склейку строк, вызовы функций. База вычислит выражение для каждой строки:

sqlite> SELECT name, price, price * 2, price - 20 FROM drinks LIMIT 3;
╭───────────┬───────┬───────────┬────────────╮
│   name    │ price │ price * 2 │ price - 20 │
╞═══════════╪═══════╪═══════════╪════════════╡
│ Эспрессо  │   120 │       240 │        100 │
│ Американо │   150 │       300 │        130 │
│ Капучино  │   190 │       380 │        170 │
╰───────────┴───────┴───────────┴────────────╯

LIMIT 3 оставляет первые три строки, чтобы ответ не занимал экран. Подробно его разберём в уроке про сортировку.

Строки склеивает оператор ||, его называют конкатенацией. Плюс для этого не подходит: в SQL + всегда складывает числа.

sqlite> SELECT name || ' (' || category || ')' AS drink, price AS rub FROM drinks LIMIT 4;
╭──────────────────┬─────╮
│      drink       │ rub │
╞══════════════════╪═════╡
│ Эспрессо (кофе)  │ 120 │
│ Американо (кофе) │ 150 │
│ Капучино (кофе)  │ 190 │
│ Латте (кофе)     │ 210 │
╰──────────────────┴─────╯

Псевдонимы через AS

Посмотри на заголовки в примере с арифметикой: price * 2 и price - 20. Оболочка назвала столбцы текстом выражения. Для двух столбцов терпимо, для запроса из отчёта неудобно. Поэтому столбцу дают псевдоним словом AS, как в примере выше: склейка стала столбцом drink, а цена столбцом rub.

Псевдоним живёт только в ответе. В таблице столбец по-прежнему называется price. Это ценник на витрине, а не новая надпись на коробке на складе.

Если в псевдониме пробел, запятая или он совпадает с ключевым словом SQL, возьми его в двойные кавычки. Так можно подписать столбцы и по-русски:

sqlite> SELECT name AS "напиток", price AS "цена, ₽" FROM drinks LIMIT 3;
╭───────────┬─────────╮
│  напиток  │ цена, ₽ │
╞═══════════╪═════════╡
│ Эспрессо  │     120 │
│ Американо │     150 │
│ Капучино  │     190 │
╰───────────┴─────────╯

Запомни разницу кавычек: двойные кавычки окружают имена (столбцов, таблиц, псевдонимов), одинарные окружают строковые значения вроде ' ('. Перепутать их легко, и SQLite из вежливости иногда угадывает, что ты имел в виду. Лучше на это не рассчитывать.

Дробная арифметика

Поднимем цены на 10 процентов:

sqlite> SELECT name, price * 1.1 AS new_price FROM drinks LIMIT 3;
╭───────────┬────────────────────╮
│   name    │     new_price      │
╞═══════════╪════════════════════╡
│ Эспрессо  │              132.0 │
│ Американо │              165.0 │
│ Капучино  │ 209.00000000000003 │
╰───────────┴────────────────────╯

Хвост 0000000000003 не ошибка SQLite. Дробные числа хранятся в двоичном виде, и 1,1 в нём записывается не точно, а с крошечной погрешностью. Для цен на витрине такое округляют функцией round():

sqlite> SELECT name, round(price * 1.1) AS new_price FROM drinks LIMIT 3;
╭───────────┬───────────╮
│   name    │ new_price │
╞═══════════╪═══════════╡
│ Эспрессо  │     132.0 │
│ Американо │     165.0 │
│ Капучино  │     209.0 │
╰───────────┴───────────╯

Целое и дробное SQLite различает строго: .0 в конце значит, что результат дробный. К функциям и приведению типов вернёмся в уроке про встроенные функции.

Почему SELECT * плох в коде

В терминале звёздочка удобна. В программе она коварна:

  • Лишние данные. Если завтра в таблицу добавят столбец с фотографией напитка, каждый SELECT * начнёт таскать мегабайты, которые никто не просил.
  • Хрупкий порядок. Код, который берёт «второй столбец ответа», сломается, когда кто-то поменяет таблицу.
  • Непонятно читателю. По SELECT name, price сразу видно, что нужно запросу. По SELECT * приходится открывать схему.

Правило простое: звёздочка для разведки, список столбцов для всего остального. Тот же совет даёт и урок про SELECT в PostgreSQL.

Попробуй сам

Песочница ниже собирает строку меню, считает цену двух порций и подписывает столбцы по-русски. Поменяй выражения: добавь в строку объём, посчитай цену со скидкой.

Длинный запрос можно разбить на строки: оболочка ждёт точку с запятой и показывает продолжение приглашением ...>.

Проверь себя

Задание

Дальше

Пока запрос показывает все строки таблицы. Чтобы оставить только нужные, например кофе дешевле 200 рублей, нужен фильтр: следующий урок про WHERE и операторы сравнения.

домашка

Домашка