Поддержите SQLtest: Помогите покрыть расходы на сервер в этом месяце в размере $100, чтобы все уроки и SQL-площадка оставались онлайн. Поддержите проект →
SQL код скопирован в буфер обмена

Урок 9.1 · Время чтения: ~9 мин

Оператор CREATE TABLE в SQL создаёт новую таблицу: её столбцы, их типы данных и правила, которым должны соответствовать данные. В этом уроке вы научитесь описывать столбцы, выбирать типы данных и использовать основные ограничения: PRIMARY KEY, NOT NULL, UNIQUE, DEFAULT, CHECK и FOREIGN KEY.

SQL CREATE TABLE: описание таблицы

До сих пор вы работали с уже существующими таблицами. CREATE TABLE относится к языку определения данных (DDL) — командам, которые задают структуру базы данных, а не сами данные. Хорошо спроектированная таблица хранит данные компактно, отклоняет недопустимые значения и поддерживает согласованность связей между таблицами.

Примеры используют синтаксис MySQL и MariaDB. Учебные базы данных на SQLtest доступны только для чтения, поэтому практикуйте эти операторы в песочнице на базе без учебных данных.

SQL CREATE TABLE: имена столбцов с типами данных, первичный ключ с AUTO_INCREMENT, ограничения NOT NULL, UNIQUE, DEFAULT и CHECK и внешний ключ на другую таблицу

Синтаксис CREATE TABLE

CREATE TABLE table_name (
    column1 data_type constraints,
    column2 data_type constraints,
    table_constraints
);

У каждого столбца есть имя, тип данных и при необходимости ограничения и параметры. Ограничения, затрагивающие несколько столбцов, например составной первичный ключ, записываются после столбцов.


Первая таблица

CREATE TABLE students (
    student_id INT,
    first_name VARCHAR(50),
    last_name VARCHAR(50),
    birth_date DATE,
    created_at TIMESTAMP
);

Результат: пустая таблица students с пятью столбцами.

Эта таблица работает, но принимает что угодно: повторяющиеся id, студентов без имени. Ограничения это исправляют.


Выбор типов данных

Тип данныхХранитПример
INT, BIGINTЦелые числаid, количества
DECIMAL(p, s)Точные числа с s знаками после запятойденьги: DECIMAL(10, 2)
VARCHAR(n)Текст длиной до n символовимена, email
TEXTДлинный текстописания
DATEКалендарная датадата рождения
DATETIME, TIMESTAMPДата и времявремя создания
BOOLEANИстина или ложь (TINYINT(1) в MySQL)флаги

Выбирайте самый узкий тип, который подходит данным: это экономит место и отсекает неверные значения. Храните деньги в DECIMAL, а не в FLOAT, который не может точно представить многие десятичные дроби. Подробнее — в уроке о типах данных.


Первичный ключ и AUTO_INCREMENT

Первичный ключ идентифицирует каждую строку: его значения уникальны и никогда не равны NULL. Суррогатный ключ обычно генерирует сама база данных с помощью AUTO_INCREMENT:

CREATE TABLE students (
    student_id INT AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL
);

INSERT INTO students (first_name, last_name)
VALUES ('ANNA', 'LEE'), ('MARK', 'STONE');

SELECT * FROM students;

Результат: два студента со значениями student_id 1 и 2, сгенерированными автоматически.

Другие СУБД генерируют ключи иначе: PostgreSQL использует GENERATED ALWAYS AS IDENTITY или SERIAL, SQL Server — IDENTITY(1, 1).


NOT NULL, UNIQUE и DEFAULT

CREATE TABLE employees (
    employee_id INT AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    hire_date DATE NOT NULL,
    salary DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
  • NOT NULL: у столбца обязательно должно быть значение.
  • UNIQUE: у двух строк не может быть одинаковых значений. Значения NULL разрешены и не считаются дубликатами.
  • DEFAULT: значение, которое используется, если INSERT его не передал.
-- Ошибка: Column 'hire_date' cannot be null
INSERT INTO employees (first_name, last_name, hire_date)
VALUES ('JOHN', 'DOE', NULL);

Ограничения CHECK

CHECK задаёт условие, которому должна удовлетворять каждая строка:

CREATE TABLE products (
    product_id INT AUTO_INCREMENT PRIMARY KEY,
    product_name VARCHAR(100) NOT NULL,
    price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
    discount_pct INT DEFAULT 0 CHECK (discount_pct BETWEEN 0 AND 90)
);

-- Ошибка: Check constraint 'products_chk_1' is violated
INSERT INTO products (product_name, price) VALUES ('Broken', -5);

MySQL проверяет CHECK начиная с версии 8.0.16, MariaDB — с 10.2; более старые версии MySQL принимали синтаксис, но игнорировали условие.


Внешние ключи

Внешний ключ связывает столбец с первичным ключом другой таблицы. После этого база данных отклоняет значения, которых нет в связанной таблице:

CREATE TABLE departments (
    department_id INT AUTO_INCREMENT PRIMARY KEY,
    department_name VARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE staff (
    staff_id INT AUTO_INCREMENT PRIMARY KEY,
    full_name VARCHAR(100) NOT NULL,
    department_id INT NOT NULL,
    FOREIGN KEY (department_id) REFERENCES departments (department_id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

INSERT INTO departments (department_name) VALUES ('Sales');
INSERT INTO staff (full_name, department_id) VALUES ('ANNA LEE', 1);

-- Ошибка: a foreign key constraint fails (отдела 99 не существует)
INSERT INTO staff (full_name, department_id) VALUES ('MARK STONE', 99);

ON DELETE определяет, что происходит с дочерними строками, когда удаляется строка, на которую они ссылаются:

ВариантКогда удаляется родительская строка
RESTRICT / NO ACTIONУдаление отклоняется, пока есть дочерние строки (по умолчанию)
CASCADEДочерние строки тоже удаляются
SET NULLДочернему столбцу присваивается NULL

ON UPDATE работает так же при изменении значения ключа. В Sakila большинство внешних ключей заданы с ON DELETE RESTRICT, поэтому в уроке 8.3 не получилось удалить клиента, у которого есть аренды.


IF NOT EXISTS

Создание уже существующей таблицы — это ошибка. IF NOT EXISTS вместо этого пропускает создание, что удобно в скриптах, которые запускаются несколько раз:

CREATE TABLE IF NOT EXISTS departments (
    department_id INT AUTO_INCREMENT PRIMARY KEY,
    department_name VARCHAR(100) NOT NULL
);

Учтите, что структуры при этом не сравниваются: если таблица с таким именем уже есть, но с другими столбцами, она останется как есть.


Кодировка текста

Для текстовых столбцов MySQL и MariaDB позволяют задать кодировку и правило сравнения (collation):

CREATE TABLE customers (
    customer_id INT AUTO_INCREMENT PRIMARY KEY,
    full_name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
) DEFAULT CHARSET = utf8mb4;

utf8mb4 хранит любые символы Unicode, включая эмодзи; collation определяет, как строки сравниваются и сортируются. Начиная с MySQL 8.0, utf8mb4 используется по умолчанию.


Ключевые выводы:

  • CREATE TABLE задаёт столбцы, типы данных и ограничения; новая таблица пуста.
  • Выбирайте точные типы данных; для денег используйте DECIMAL.
  • PRIMARY KEY идентифицирует строки; AUTO_INCREMENT генерирует значения ключа.
  • NOT NULL, UNIQUE, DEFAULT и CHECK поддерживают корректность данных.
  • FOREIGN KEY связывает таблицы; ON DELETE определяет судьбу дочерних строк.
  • IF NOT EXISTS избавляет от ошибки, если таблица уже существует.

Часто задаваемые вопросы

Как создать таблицу с первичным ключом в SQL?

Добавьте PRIMARY KEY к ключевому столбцу: CREATE TABLE students (student_id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL);. Для ключа из нескольких столбцов напишите PRIMARY KEY (col1, col2) после списка столбцов.

Чем PRIMARY KEY отличается от UNIQUE?

Оба запрещают дубликаты. Первичный ключ в таблице только один, и его столбцы не могут быть NULL. Ограничений UNIQUE может быть много, и они допускают значения NULL.

Как добавить внешний ключ в CREATE TABLE?

Напишите FOREIGN KEY (column) REFERENCES other_table (key_column) после столбцов, при необходимости с действиями ON DELETE и ON UPDATE. Столбец, на который ссылается ключ, должен быть первичным ключом или уникальным.

Попробуйте решить следующие задачи, чтобы закрепить материал этого урока.

  1. Создайте таблицу отделов
  2. Таблица статистики пингвинов
  3. Создание таблицы пингвинов