Ограничения: правила за данните
Накратко: Ограниченията NOT NULL, DEFAULT, UNIQUE, CHECK и PRIMARY KEY са правила в CREATE TABLE, с които таблицата сама пази данните верни.
Проблем
Таблица, която приема всичко
Ето таблица за доставчиците без никакви правила. Пусни заявката:
Влезе доставчик без име. Влезе втори път един и същ ЕИК. Влезе оценка 7 по скала от 1 до 5. Никой не е проверил.
В модула за промяна на данните магазинът отказваше такива редове с грешки. Тези грешки идват от правила, записани в CREATE TABLE. Сега ти ще ги пишеш.
Идеята
NOT NULL и DEFAULT
Правилата се пишат след типа на колоната. Казват се ограничения (constraints).
NOT NULL: колоната не може да е празна.DEFAULT стойност: какво да се запише, акоINSERTне даде стойност.
Мандрата получи „София“, защото градът ѝ не е даден. Доставчик без име не влиза:
DEFAULT CURRENT_DATE записва днешната дата. Удобно е за „кога е добавен“:
1 значи „да, днешната дата е“. Смени added_at = CURRENT_DATE само с added_at и ще видиш самата дата.
По-точно, за любопитните
CURRENT_DATE в SQLite е датата по UTC, не по българско време. Между полунощ и 2–3 часа сутринта българската дата вече е новата, а UTC още е старата. CURRENT_TIMESTAMP дава дата и час, също по UTC.
Пробвай
Задължителните полета
Таблицата deliveries има id, supplier_id, amount и status. Направи доставчика и сумата задължителни, а състоянието да е задължително и по подразбиране 'expected'.
Решение
CREATE TABLE deliveries (
id INTEGER PRIMARY KEY,
supplier_id INTEGER NOT NULL,
amount REAL NOT NULL,
status TEXT NOT NULL DEFAULT 'expected'
);supplier_id INTEGER NOT NULL, amount REAL NOT NULL, status TEXT NOT NULL DEFAULT 'expected'. Новата доставка може да се запише без състояние: тя е „очаквана“, докато не пристигне.
Идеята
UNIQUE
UNIQUE забранява две еднакви стойности в колоната. ЕИК-ът на фирмата е един:
Понякога уникална е двойката. Всеки доставчик дава една цена за един продукт. Двама доставчици може да дават един и същ продукт, а един доставчик дава много продукти. Правилото се пише отделно, след колоните, с двете колони в скоби:
Първите три реда влизат. Четвъртият е втора цена от доставчик 1 за продукт 1.
По-точно, за любопитните
UNIQUE позволява много NULL-и: два доставчика без ЕИК не се смятат за еднакви, защото NULL не е равно на NULL. Ако ЕИК-ът е задължителен, пиши vat TEXT NOT NULL UNIQUE. Така е и в PostgreSQL. SQL Server по подразбиране пуска само един NULL в UNIQUE колона.
Идеята
CHECK
CHECK (условие) пуска реда само ако условието е вярно. Условието е като в WHERE:
Когато условието е за няколко колони, CHECK се пише след колоните. Промоцията не може да свърши, преди да е започнала:
Съобщението на SQLite казва кое условие не е минало. Затова пиши кратки и ясни условия.
Виж го
CHECK пропуска NULL
Оценката е от 1 до 5. А ако не е дадена?
Влезе. CHECK отказва реда само когато условието е невярно. NULL BETWEEN 1 AND 5 е „неизвестно“, както всяко сравнение с NULL. Това е обратното на WHERE, което пази само вярното.
Тук това е правилно: нов доставчик още няма оценка. Но ако стойността е задължителна, CHECK не стига. Трябва и NOT NULL.
Пробвай
Цените на доставчиците
Таблицата supplier_prices има supplier_id, product_id и price. Цената е задължителна и по-голяма от 0, а всеки доставчик има само една цена за даден продукт. Допиши правилата.
Решение
CREATE TABLE supplier_prices (
supplier_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
price REAL NOT NULL CHECK (price > 0),
UNIQUE (supplier_id, product_id)
);price REAL NOT NULL CHECK (price > 0) и на отделен ред UNIQUE (supplier_id, product_id). Без NOT NULL цена NULL щеше да мине покрай CHECK.
Идеята
PRIMARY KEY
Първичният ключ вече го познаваш: колоната, по която се разпознава редът. В CREATE TABLE е ограничение като другите. Не пуска два реда с един и същ ключ:
Когато ключът е от две колони, той се пише отделно, както UNIQUE. Така е в order_items: един продукт е веднъж в една поръчка, а количеството е в quantity.
order_items
- PK
order_idinteger→ orders - PK
product_idinteger→ products quantityinteger *unit_pricereal *
По-точно, за любопитните
В SQLite има стара особеност: първичен ключ, който не е INTEGER PRIMARY KEY, приема NULL. Пусни го:
Два купона без код. Това е грешка от ранните версии, която е оставена, за да не се развалят стари програми. В STRICT таблица първичният ключ не приема NULL. Навсякъде другаде пиши code TEXT NOT NULL PRIMARY KEY. В PostgreSQL и MySQL първичният ключ винаги е NOT NULL.
Упражнение
Доставчиците, както трябва
Направи окончателната таблица suppliers: id (първичен ключ), name (задължително), vat (ЕИК, задължителен и без повторения), city (задължителен, по подразбиране 'София') и rating (цяло число от 1 до 5, може да липсва). Проверката ще опита да добави и грешни доставчици.
Решение
CREATE TABLE suppliers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
vat TEXT NOT NULL UNIQUE,
city TEXT NOT NULL DEFAULT 'София',
rating INTEGER CHECK (rating BETWEEN 1 AND 5)
);name TEXT NOT NULL, vat TEXT NOT NULL UNIQUE, city TEXT NOT NULL DEFAULT 'София' и rating INTEGER CHECK (rating BETWEEN 1 AND 5).
Проверката опитва да добави седем доставчика. Трябва да влязат само двата верни. Не влизат повтореният ЕИК, доставчикът без име, този без ЕИК, този без град и оценката 7.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Функции за дати · Първичен и външен ключ · INSERT: нови редове · CREATE TABLE: нова таблица
- Продължава в: Външни ключове: връзки между таблиците · ALTER TABLE: промяна на таблица · Видове връзки: 1:1, 1:N, M:N · ER диаграма: от описание до схема
- Задачи по темата: Таблици и правила