INSERT: нови редове
Накратко: INSERT INTO добавя нови редове в таблица, един или много наведнъж или от резултата на SELECT, а RETURNING връща колони от новия ред, например номера му.
Проблем
Нов клиент
Досега само четеше от базата. Но всеки ден в нея влизат нови неща. Днес в сайта се регистрира Весела Райкова от Плевен.
Сайтът трябва да запише нов ред в customers. Никой не отваря таблицата на ръка: програмата праща заявка към базата.
Идеята
INSERT INTO
INSERT INTO казва в коя таблица и кои колони, а VALUES дава стойностите в същия ред:
Колоната id не е в списъка. Тя е първичен ключ от вида INTEGER PRIMARY KEY, затова SQLite сам дава номер с едно по-голям от най-големия: 21. Колона, която не е в списъка, получава стойността си по подразбиране (за stock в магазина тя е 0), а ако няма такава, NULL.
В едно поле може да има няколко заявки. Те се изпълняват една след друга, а SELECT накрая показва какво е станало.
Всяко поле има своя база и я пази между изпълненията. Пусни заявката още веднъж: вторият път базата ще откаже, защото Весела вече е вътре с този имейл. Бутонът „Нова база“ връща базата, както е била в началото.
Виж го
Без списъка с колони
Списъкът с колоните може да се пропусне. Тогава стойностите трябва да са за всички колони, в реда, в който са в таблицата:
Пропуснеш ли една, базата отказва:
Тук липсва id. Без списък базата не знае коя стойност за коя колона е. Затова винаги изброявай колоните. Така се вижда кое къде отива, а заявката не се чупи, когато таблицата получи нова колона.
Пробвай
Нов продукт
Магазинът започва да продава айрян. Добави продукта „Айрян“ в категория 4 (Млечни), на цена 1,30 €, с 30 бройки на склад, добавен днес (2026-10-25).
Решение
INSERT INTO products (name, category_id, price, stock, added_at)
VALUES ('Айрян', 4, 1.3, 30, '2026-10-25');INSERT INTO products (name, category_id, price, stock, added_at) VALUES ('Айрян', 4, 1.3, 30, '2026-10-25'). Номерът му е 26, базата го дава сама. В кода цената е с точка.
Идеята
RETURNING
Явор Пенев прави първата си поръчка. Сайтът записва поръчката, а после трябва да запише и продуктите в нея. За това му трябва номерът на новата поръчка, а него го дава базата.
RETURNING в края на INSERT връща колони от току-що записания ред:
Поръчката е с номер 61. Без RETURNING щеше да ти трябва втора заявка, за да го научиш. RETURNING приема всякакви колони: RETURNING id, ordered_at или RETURNING *.
По-точно, за любопитните
RETURNING го има в SQLite (от версия 3.35) и в PostgreSQL. В SQL Server същото се пише с OUTPUT. В MySQL го няма: там номерът се взима с LAST_INSERT_ID() след вмъкването. SQLite има подобна функция, last_insert_rowid().
Идеята
Много редове наведнъж
В поръчката на Явор има кафе и две кутии прясно мляко. Няколко реда се записват с едно INSERT: след VALUES идват няколко скоби, разделени със запетая. В тази база поръчка 61 вече я има:
Редовете може да идват и от заявка. Мария натиска „Поръчай пак“ на последната си поръчка (60). Новата поръчка е 61, а продуктите идват от SELECT вместо от VALUES:
Това е INSERT … SELECT: каквото върне SELECT, се записва. Колоните на SELECT трябва да отговарят на списъка след INSERT INTO. Цената се взима от products, а не от старата поръчка, защото оттогава може да се е сменила.
Виж го
Базата казва „не“
Таблиците на магазина имат правила. Нарушиш ли някое, базата отказва реда и казва кое правило е нарушено.
Имейлът на клиента трябва да е уникален (UNIQUE):
Името не може да липсва (NOT NULL):
Цената не може да е отрицателна (CHECK):
Поръчката трябва да е на клиент, който съществува. customer_id е външен ключ към customers, а клиент 99 няма:
Всеки път редът не се записва и в базата нищо не се променя. Това е за добро: грешка в програмата не може да напълни базата с поръчки на никого.
Тези правила са записани в самата таблица, когато е направена. В следващия модул ще ги пишеш сам.
Пробвай
Отзив без текст
Симона Йорданова (клиент 17) дава 5 звезди на прясното мляко (продукт 5) днес, 2026-10-25, без да пише текст. Запиши отзива.
Решение
INSERT INTO reviews (product_id, customer_id, rating, created_at)
VALUES (5, 17, 5, '2026-10-25');INSERT INTO reviews (product_id, customer_id, rating, created_at) VALUES (5, 17, 5, '2026-10-25'). Колоната body не е в списъка, затова остава NULL. Тя може да е празна, а rating не може: пробвай без него.
Упражнение
Две задачи
1. Магазинът разширява отдела „Дом“ (категория 2). Добави две подкатегории с една заявка: „Градина“ и „Баня“.
Двете нови категории в „Дом“:
Решение
INSERT INTO categories (name, parent_id)
VALUES ('Градина', 2),
('Баня', 2);INSERT INTO categories (name, parent_id) VALUES ('Градина', 2), ('Баня', 2). parent_id е 2, защото са част от „Дом“. Номерата им са 9 и 10.
2. Огнян Славов от Варна се регистрира днес с имейл ognyan.s@example.com. Сайтът иска веднага да му покаже профила с номера, който базата му е дала. Запиши го и върни целия нов ред със същата заявка.
Новият клиент, целият ред:
Решение
INSERT INTO customers (name, email, city, joined_at)
VALUES ('Огнян Славов', 'ognyan.s@example.com', 'Варна', '2026-10-25')
RETURNING *;INSERT INTO customers (name, email, city, joined_at) VALUES ('Огнян Славов', 'ognyan.s@example.com', 'Варна', '2026-10-25') RETURNING *. Той е клиент 21.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: WHERE: филтриране на редове · NULL: няма стойност · Първичен и външен ключ · JOIN: две таблици в една заявка
- Продължава в: UPDATE: промяна на редове · DELETE: изтриване на редове · UPSERT: вмъкни или обнови · Базата данни: от създаването до DROP
- Задачи по темата: Промяна на данните