Урок 5.2 — CREATE TABLE
Создаём свои таблицы, выбираем типы данных, задаём ограничения. Всё, что нужно для проектирования базы данных с нуля.
CREATE TABLE, типы данных (INTEGER, REAL, TEXT), PRIMARY KEY, AUTOINCREMENT, NOT NULL, DEFAULT, UNIQUE, CHECK, внешние ключи, IF NOT EXISTS.
🏗️ 1. CREATE TABLE — создаём таблицу
Команда CREATE TABLE — это способ сказать базе данных: «Создай для меня новую таблицу с такими-то столбцами». Вы задаёте имя таблицы, имена столбцов, их типы и правила (ограничения).
1.1 Базовый синтаксис
CREATE TABLE table_name ( column1 type constraints, column2 type constraints, ...
); Разберём по частям:
- table_name — имя новой таблицы (обычно во множественном числе:
users,products) - column1, column2 — имена столбцов
- type — тип данных (INTEGER, REAL, TEXT и другие)
- constraints — ограничения (NOT NULL, PRIMARY KEY, DEFAULT и другие)
1.2 Простейшая таблица
-- Создаём таблицу для хранения имён пользователей
CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL
); -- Вставляем данные
INSERT INTO users (name) VALUES ('Анна'), ('Иван'), ('Пётр'); -- Проверяем
SELECT * FROM users; 📊 2. Типы данных в SQLite
В SQLite всего 5 основных типов данных. Для начала вам хватит трёх:
2.1 INTEGER — целые числа
Для счётчиков, возрастов, количества товаров, id — всего, что не требует дробной части:
CREATE TABLE example_integer ( id INTEGER PRIMARY KEY, age INTEGER, quantity INTEGER DEFAULT 0, year INTEGER
); INSERT INTO example_integer VALUES (1, 25, 10, 2024);
INSERT INTO example_integer VALUES (2, 33, -5, 2023); -- можно отрицательные
INSERT INTO example_integer VALUES (3, 18, 100500, 2025); SELECT * FROM example_integer; 2.2 REAL — дробные числа
Для цен, рейтингов, процентов, координат — всего, где нужна дробная часть:
CREATE TABLE example_real ( id INTEGER PRIMARY KEY, price REAL, rating REAL, temperature REAL
); INSERT INTO example_real VALUES (1, 99.99, 4.5, 36.6);
INSERT INTO example_real VALUES (2, 0.50, 3.75, -5.2);
INSERT INTO example_real VALUES (3, 1000000.0, 5.0, 22.0); SELECT * FROM example_real; 2.3 TEXT — строки и текст
Для имён, описаний, email, адресов, дат — любых текстовых данных:
CREATE TABLE example_text ( id INTEGER PRIMARY KEY, name TEXT, email TEXT, bio TEXT -- длинный текст
); INSERT INTO example_text VALUES (1, 'Мария', 'maria@example.com', 'Начинающий разработчик из Москвы'), (2, 'Алексей', 'alex@example.com', 'Люблю базы данных и кофе'), (3, 'Дарья', 'daria@example.com', 'Студентка, учу SQL'); SELECT * FROM example_text; 💡 Даты в SQLite: В SQLite нет отдельного типа для дат. Обычно даты хранят как TEXT в формате YYYY-MM-DD или YYYY-MM-DD HH:MM:SS. Так их можно сравнивать и сортировать как обычные строки.
🔑 3. PRIMARY KEY — уникальный идентификатор
PRIMARY KEY — это столбец (или набор столбцов), который уникально идентифицирует каждую строку. Две строки не могут иметь одинаковый PRIMARY KEY.
3.1 PRIMARY KEY с AUTOINCREMENT
AUTOINCREMENT заставляет SQLite автоматически подставлять следующее целое число при вставке новой строки. Так id всегда будет уникальным:
-- Таблица с автоинкрементом
CREATE TABLE notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL
); -- Не указываем id — он подставится сам
INSERT INTO notes (title) VALUES ('Первая заметка');
INSERT INTO notes (title) VALUES ('Вторая заметка');
INSERT INTO notes (title) VALUES ('Третья заметка'); SELECT * FROM notes;
-- Результат:
-- 1 | Первая заметка
-- 2 | Вторая заметка
-- 3 | Третья заметка -- Можно указать id вручную (но убедитесь, что он уникален)
INSERT INTO notes (id, title) VALUES (100, 'Специальная заметка');
INSERT INTO notes (title) VALUES ('Следующая заметка');
-- id будет 101 (счётчик продолжает от максимального значения) 💡 AUTOINCREMENT без AUTOINCREMENT: В SQLite, если просто написать INTEGER PRIMARY KEY (без AUTOINCREMENT), id тоже будет автоматически увеличиваться. AUTOINCREMENT гарантирует, что новый id никогда не повторит старый (даже после удаления последней строки). Для обучения достаточно простого INTEGER PRIMARY KEY.
🚫 4. NOT NULL — обязательные поля
NOT NULL запрещает хранить NULL (пустое значение) в столбце. Если попытаться вставить NULL, SQLite выдаст ошибку:
-- Таблица, где имя и email обязательны
CREATE TABLE subscribers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL, phone TEXT -- телефон может быть NULL (необязательный)
); -- Ошибка! name не может быть NULL
INSERT INTO subscribers (email) VALUES ('test@mail.com'); -- ❌ -- Ошибка! email не может быть NULL
INSERT INTO subscribers (name) VALUES ('Вася'); -- ❌ -- Так правильно
INSERT INTO subscribers (name, email) VALUES ('Вася', 'vasya@mail.com'); -- phone можно не указывать (будет NULL)
INSERT INTO subscribers (name, email) VALUES ('Петя', 'petya@mail.com'); 🎯 5. DEFAULT — значение по умолчанию
DEFAULT задаёт значение, которое подставится, если при вставке столбец не указан. Очень удобно для дат, статусов, счётчиков:
CREATE TABLE tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, status TEXT DEFAULT 'new', -- по умолчанию 'new' priority INTEGER DEFAULT 1, -- по умолчанию 1 created_at TEXT DEFAULT (date('now')), -- сегодняшняя дата is_completed INTEGER DEFAULT 0 -- по умолчанию 0 (нет)
); -- Вставляем только заголовок — остальное подставится автоматически
INSERT INTO tasks (title) VALUES ('Купить продукты');
INSERT INTO tasks (title) VALUES ('Сделать ДЗ по SQL');
INSERT INTO tasks (title) VALUES ('Позвонить врачу'); -- Можно переопределить значения по умолчанию
INSERT INTO tasks (title, priority) VALUES ('Срочный отчёт', 5);
INSERT INTO tasks (title, status, is_completed) VALUES ('Готово!', 'done', 1); SELECT * FROM tasks;
-- Результат:
-- 1 | Купить продукты | new | 1 | 2024-12-01 | 0
-- 2 | Сделать ДЗ по SQL | new | 1 | 2024-12-01 | 0
-- 3 | Позвонить врачу | new | 1 | 2024-12-01 | 0
-- 4 | Срочный отчёт | new | 5 | 2024-12-01 | 0
-- 5 | Готово! | done | 1 | 2024-12-01 | 1 🔐 6. UNIQUE — уникальные значения
UNIQUE гарантирует, что все значения в столбце (или комбинации столбцов) будут разными. Никакие две строки не могут иметь одинаковое значение в UNIQUE-столбце:
CREATE TABLE users_unique ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, -- email должен быть уникальным username TEXT NOT NULL UNIQUE -- username тоже уникальный
); INSERT INTO users_unique (email, username) VALUES ('alice@mail.com', 'alice99');
INSERT INTO users_unique (email, username) VALUES ('bob@mail.com', 'bob_the_builder'); -- Ошибка! email 'alice@mail.com' уже существует
INSERT INTO users_unique (email, username) VALUES ('alice@mail.com', 'alice_new'); -- ❌ -- Ошибка! username 'bob_the_builder' уже существует
INSERT INTO users_unique (email, username) VALUES ('bob_new@mail.com', 'bob_the_builder'); -- ❌ -- UNIQUE можно комбинировать с NOT NULL ✅ 7. CHECK — проверка значений
CHECK задаёт условие, которому должны соответствовать значения. Если условие ложно — вставка или обновление не сработает:
CREATE TABLE products_check ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, price REAL NOT NULL CHECK (price >= 0), -- цена не может быть отрицательной stock INTEGER DEFAULT 0 CHECK (stock >= 0), -- остаток не может быть отрицательным age_restriction INTEGER CHECK (age_restriction >= 0 AND age_restriction <= 21)
); -- Так работает
INSERT INTO products_check (name, price, stock) VALUES ('Товар', 100.0, 10); -- Ошибка! Цена не может быть отрицательной
INSERT INTO products_check (name, price, stock) VALUES ('Товар', -50.0, 10); -- ❌ -- Ошибка! Остаток не может быть отрицательным
INSERT INTO products_check (name, price, stock) VALUES ('Товар', 100.0, -5); -- ❌ -- Ошибка! Возрастное ограничение должно быть от 0 до 21
INSERT INTO products_check (name, price, age_restriction) VALUES ('Товар', 100.0, 25); -- ❌ 🔗 8. Внешние ключи (FOREIGN KEY)
Внешний ключ связывает таблицы. Он гарантирует, что значение столбца в одной таблице существует в другой. В SQLite внешние ключи нужно включать отдельно:
PRAGMA foreign_keys = ON; -- включаем поддержку внешних ключей -- Таблица категорий
CREATE TABLE categories ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE
); -- Таблица товаров со ссылкой на категорию
CREATE TABLE products_fk ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, category_id INTEGER REFERENCES categories(id), -- внешний ключ price REAL NOT NULL
); -- Сначала добавим категории
INSERT INTO categories (name) VALUES ('Электроника'), ('Книги'), ('Одежда'); -- Теперь товары — category_id должен существовать в categories
INSERT INTO products_fk (name, category_id, price) VALUES ('Ноутбук', 1, 75000.0);
INSERT INTO products_fk (name, category_id, price) VALUES ('Книга SQL', 2, 1500.0);
INSERT INTO products_fk (name, category_id, price) VALUES ('Футболка', 3, 1500.0); -- Ошибка! Категории с id = 100 не существует
INSERT INTO products_fk (name, category_id, price) VALUES ('Что-то', 100, 500.0); -- ❌ 🛡️ 9. IF NOT EXISTS — защита от ошибок
IF NOT EXISTS проверяет, существует ли уже таблица с таким именем. Если существует — команда просто ничего не делает (без ошибки):
-- Без IF NOT EXISTS — если таблица существует, будет ошибка
CREATE TABLE test (id INTEGER PRIMARY KEY);
CREATE TABLE test (id INTEGER PRIMARY KEY); -- ❌ ошибка! -- С IF NOT EXISTS — ошибки не будет
CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY);
CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY); -- просто игнорируется -- Всегда используйте IF NOT EXISTS в реальных скриптах! 🧪 10. Практика — создаём таблицу «Заметки»
Теперь сделаем полноценный проект. Создадим таблицу для заметок и поработаем с ней.
Шаг 1 — Создаём таблицу notes
-- Таблица для заметок
CREATE TABLE IF NOT EXISTS notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, created_at TEXT DEFAULT (date('now')), updated_at TEXT DEFAULT (date('now')), is_archived INTEGER DEFAULT 0, priority INTEGER DEFAULT 1 CHECK (priority BETWEEN 1 AND 5)
); Шаг 2 — Вставляем данные
-- Добавляем заметки
INSERT INTO notes (title, content) VALUES ('Купить продукты', 'Молоко, хлеб, яйца, сыр, помидоры'), ('Изучить SQL', 'Закончить уроки по CREATE TABLE и JOIN'), ('Идея для проекта', 'Создать приложение для учёта расходов на Python + SQLite'), ('Книги к прочтению', '"Изучаем SQL" Алан Бьюли, "SQL для смертных"'), ('План на неделю', 'Пн: SQL, Вт: Python, Ср: отдых, Чт: SQL, Пт: проект'); -- С заметкой с высоким приоритетом
INSERT INTO notes (title, content, priority) VALUES ('Срочно! Дедлайн проекта', 'Сдать отчёт до пятницы!', 5); -- Архивная заметка
INSERT INTO notes (title, content, is_archived) VALUES ('Старая идея', 'Когда-то хотел сделать игру', 1); Шаг 3 — SELECT из своей таблицы
-- Все заметки
SELECT * FROM notes; -- Только активные (не архивированные)
SELECT id, title, created_at, priority
FROM notes
WHERE is_archived = 0; -- Заметки с высоким приоритетом
SELECT title, priority FROM notes WHERE priority >= 4; -- Заметки, отсортированные по дате (сначала новые)
SELECT * FROM notes ORDER BY created_at DESC; -- Сколько заметок каждого приоритета?
SELECT priority, COUNT(*) AS cnt
FROM notes
GROUP BY priority
ORDER BY priority; -- Поиск заметок по тексту
SELECT * FROM notes
WHERE content LIKE '%SQL%' OR title LIKE '%SQL%'; Шаг 4 — Обновляем и удаляем
-- Обновить заметку
UPDATE notes
SET content = 'Молоко, хлеб, яйца, сыр, помидоры, шоколад', updated_at = date('now')
WHERE id = 1; -- Архивировать заметку
UPDATE notes SET is_archived = 1 WHERE id = 3; -- Удалить заметку
DELETE FROM notes WHERE id = 5; -- Посмотреть результат
SELECT * FROM notes; 🎯 11. Самостоятельные задания
Задание 1 — Таблица «Контакты»
-- Создайте таблицу contacts:
-- id — INTEGER PRIMARY KEY AUTOINCREMENT
-- name — TEXT NOT NULL
-- phone — TEXT NOT NULL
-- email — TEXT UNIQUE
-- is_favorite — INTEGER DEFAULT 0
-- created_at — TEXT DEFAULT date('now') -- Добавьте 5 контактов
-- Сделайте SELECT всех контактов, отсортированных по имени Задание 2 — Таблица «Книги»
-- Создайте таблицу books:
-- id, title (NOT NULL), author (NOT NULL), year (INTEGER), rating (REAL, 0-5), is_read (INTEGER DEFAULT 0) -- Вставьте 5 книг (укажите только title, author, year)
-- Вставьте ещё 3 книги (со всеми полями)
-- Найдите все книги, прочитанные (is_read = 1)
-- Найдите книги с рейтингом >= 4 Задание 3 — Таблица «Студенты и оценки»
-- Создайте таблицу students (id, name, group_name)
-- Создайте таблицу grades (id, student_id REFERENCES students(id), subject, grade INTEGER CHECK 1-5) -- Вставьте 3 студентов
-- Вставьте по 2-3 оценки каждому студенту
-- Выведите оценки каждого студента (JOIN)
-- Найдите средний балл каждого студента 📋 12. Шпаргалка CREATE TABLE
-- === БАЗОВЫЙ CREATE TABLE ===
CREATE TABLE table_name ( col1 TYPE CONSTRAINTS, col2 TYPE CONSTRAINTS
); -- === ТИПЫ ДАННЫХ ===
INTEGER -- целые числа: 0, 1, 42, -7, 100500
REAL -- дробные числа: 3.14, 99.99, -0.5
TEXT -- строки: 'hello', 'Москва', '2024-01-01' -- === ОГРАНИЧЕНИЯ ===
PRIMARY KEY -- уникальный идентификатор строки
AUTOINCREMENT -- авто-увеличение (только для INTEGER PRIMARY KEY)
NOT NULL -- поле обязательно
DEFAULT значение -- значение по умолчанию
UNIQUE -- все значения в столбце должны быть разными
CHECK (условие) -- проверка: CHECK (age >= 0)
REFERENCES table(col) -- внешний ключ -- === ПОЛЕЗНЫЕ ПРИЁМЫ ===
CREATE TABLE IF NOT EXISTS table_name (...
-- не выдаёт ошибку, если таблица уже существует -- === ПРИМЕР ГОТОВОЙ ТАБЛИЦЫ ===
CREATE TABLE IF NOT EXISTS example ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL UNIQUE, age INTEGER CHECK (age >= 0 AND age < 150), score REAL DEFAULT 0.0, is_active INTEGER DEFAULT 1, created_at TEXT DEFAULT (date('now'))
); CREATE TABLE — главная команда для создания структуры базы данных. Вы научились выбирать типы данных (INTEGER, REAL, TEXT), задавать PRIMARY KEY с AUTOINCREMENT, делать поля обязательными (NOT NULL), устанавливать значения по умолчанию (DEFAULT), гарантировать уникальность (UNIQUE) и проверять данные (CHECK). Теперь вы можете спроектировать и создать свою собственную базу данных с нуля!
ТЕСТ — Урок 5.2: CREATE TABLE
5 вопросов