CREATE TABLE в SQL — создание таблиц
Коротко
CREATE TABLE — команда DDL (Data Definition Language) для создания таблиц в базе данных. Определяет столбцы, типы данных, ограничения и связи. Аналитику CREATE TABLE нужен для создания временных таблиц, витрин данных и понимания структуры БД. На собеседованиях спрашивают про типы ограничений, нормализацию и проектирование схемы.
Базовый синтаксис
CREATE TABLE table_name (
column1 data_type constraints,
column2 data_type constraints,
...
table_constraints
);Простой пример — таблица пользователей:
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT NOW()
);SERIAL— автоинкремент (PostgreSQL). В MySQL —INT AUTO_INCREMENTPRIMARY KEY— уникальный идентификатор строкиNOT NULL— запрет пустых значенийUNIQUE— все значения в столбце уникальныDEFAULT NOW()— значение по умолчанию
Типы данных
Основные типы для PostgreSQL (в других СУБД могут отличаться):
| Тип | Описание | Пример |
|---|---|---|
| INTEGER / INT | Целое число | 42 |
| BIGINT | Большое целое | 9223372036854775807 |
| SERIAL | Автоинкремент (INT) | 1, 2, 3... |
| NUMERIC(p, s) | Точное десятичное | 99999.99 |
| REAL / FLOAT | Приблизительное число | 3.14 |
| VARCHAR(n) | Строка до n символов | 'Иван' |
| TEXT | Строка без ограничения | длинный текст |
| BOOLEAN | true / false | true |
| DATE | Дата | 2025-03-15 |
| TIMESTAMP | Дата + время | 2025-03-15 14:30:00 |
| JSONB | JSON (бинарный) | {"key": "value"} |
| UUID | Универсальный ID | a0eebc99-9c0b... |
Подробнее о типах — в гайде по типам данных SQL.
Ограничения (constraints)
PRIMARY KEY
Уникальный идентификатор каждой строки. Не может быть NULL. Одна таблица — один PRIMARY KEY (может быть составным).
-- Одиночный ключ
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
-- Составной ключ
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT NOT NULL,
PRIMARY KEY (order_id, product_id)
);FOREIGN KEY
Связь между таблицами. Значение в столбце должно существовать в другой таблице.
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(user_id),
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
amount NUMERIC(10, 2) NOT NULL
);REFERENCES users(user_id) — каждый order_id должен указывать на существующего пользователя. Попытка вставить order с несуществующим user_id — ошибка.
-- Альтернативный синтаксис с ON DELETE
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
amount NUMERIC(10, 2) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(user_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);ON DELETE CASCADE— удаление пользователя удалит все его заказыON DELETE SET NULL— user_id станет NULLON DELETE RESTRICT— запретить удаление, если есть заказы (по умолчанию)
NOT NULL, UNIQUE, DEFAULT, CHECK
CREATE TABLE employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
salary NUMERIC(10, 2) CHECK (salary > 0),
department VARCHAR(50) DEFAULT 'Unassigned',
hire_date DATE NOT NULL DEFAULT CURRENT_DATE
);NOT NULL— значение обязательноUNIQUE— без дубликатов (NULL допускается, и несколько NULL не считаются дубликатами в PostgreSQL)CHECK— произвольное условиеDEFAULT— значение, если не указано при INSERT
Практические примеры
Схема интернет-магазина
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
parent_id INT REFERENCES categories(category_id)
);
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
category_id INT REFERENCES categories(category_id),
price NUMERIC(10, 2) NOT NULL CHECK (price >= 0),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(user_id),
status VARCHAR(20) DEFAULT 'pending'
CHECK (status IN ('pending', 'paid', 'shipped', 'delivered', 'cancelled')),
total NUMERIC(12, 2) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE order_items (
order_id INT REFERENCES orders(order_id) ON DELETE CASCADE,
product_id INT REFERENCES products(product_id),
quantity INT NOT NULL CHECK (quantity > 0),
price NUMERIC(10, 2) NOT NULL,
PRIMARY KEY (order_id, product_id)
);Витрина для аналитики
CREATE TABLE daily_metrics AS
SELECT
DATE(created_at) AS metric_date,
COUNT(DISTINCT user_id) AS dau,
COUNT(*) AS events,
SUM(amount) AS revenue
FROM events
GROUP BY DATE(created_at);CREATE TABLE ... AS SELECT — создаёт таблицу и заполняет результатом запроса. Удобно для витрин и материализованных отчётов.
Временная таблица
CREATE TEMP TABLE active_users AS
SELECT user_id, COUNT(*) AS sessions
FROM user_sessions
WHERE session_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
HAVING COUNT(*) >= 5;Временная таблица существует только в текущей сессии и автоматически удаляется при отключении.
IF NOT EXISTS
CREATE TABLE IF NOT EXISTS users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL
);Если таблица уже существует — команда ничего не сделает вместо ошибки. Полезно в скриптах миграций.
ALTER TABLE — изменение структуры
После создания таблицы структуру можно менять:
-- Добавить столбец
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- Удалить столбец
ALTER TABLE users DROP COLUMN phone;
-- Добавить ограничение
ALTER TABLE users ADD CONSTRAINT email_check
CHECK (email LIKE '%@%');
-- Изменить тип столбца
ALTER TABLE users ALTER COLUMN username TYPE VARCHAR(100);
-- Добавить NOT NULL
ALTER TABLE users ALTER COLUMN email SET NOT NULL;
-- Переименовать столбец
ALTER TABLE users RENAME COLUMN username TO login;DROP TABLE — удаление таблицы
-- Удалить таблицу
DROP TABLE order_items;
-- Удалить если существует (без ошибки)
DROP TABLE IF EXISTS order_items;
-- Удалить вместе с зависимыми таблицами
DROP TABLE users CASCADE;CASCADE удалит все внешние ключи и зависимые объекты. Используйте с осторожностью.
Вопросы с собеседований
-- Что такое PRIMARY KEY? -- Ограничение, гарантирующее уникальность и NOT NULL для столбца (или комбинации столбцов). Каждая таблица может иметь только один PRIMARY KEY. Создаёт уникальный индекс.
-- Чем отличается UNIQUE от PRIMARY KEY? -- PRIMARY KEY = UNIQUE + NOT NULL, и он один на таблицу. UNIQUE допускает NULL (в PostgreSQL) и может быть несколько.
-- Что такое FOREIGN KEY? -- Ограничение ссылочной целостности: значение в столбце должно существовать в другой таблице. Обеспечивает связь между таблицами и предотвращает «висячие» ссылки.
-- Когда аналитику нужен CREATE TABLE? -- Создание временных таблиц для сложных расчётов, витрин данных, промежуточных таблиц в ETL, тестовых данных. Также важно для понимания схемы БД и проектирования хранилища.
-- Чем отличается VARCHAR от TEXT? -- VARCHAR(n) ограничивает длину строки. TEXT — без ограничения. В PostgreSQL производительность одинаковая. VARCHAR полезен для валидации (не хранить email длиннее 100 символов).
Потренируйтесь решать задачи — откройте тренажёр с 1500+ вопросами для подготовки к собеседованиям аналитиков.
FAQ
CREATE TABLE vs CREATE TEMP TABLE — в чём разница?
CREATE TABLE создаёт постоянную таблицу, которая остаётся после завершения сессии. CREATE TEMP TABLE — временную, которая живёт только до конца сессии и не видна другим пользователям.
Как скопировать структуру таблицы без данных?
CREATE TABLE new_table (LIKE old_table INCLUDING ALL) — скопирует столбцы, типы, ограничения, индексы. Без INCLUDING ALL — только столбцы и типы.
Нужно ли аналитику знать нормализацию?
Да. Понимание нормальных форм помогает проектировать схемы без аномалий и писать правильные JOIN. На собеседованиях часто просят спроектировать схему для магазина, блога или сервиса.
Как тренироваться
Задачи на CREATE TABLE, DDL и проектирование схемы — в тренажёре Карьерник. Больше вопросов по всем темам — в разделе с примерами.