В прошлом уроке ты создал первую таблицу и достал из неё всё через 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 и операторы сравнения.
домашка