Двенадцать правил Кодда
Где применяют новичку двенадцать правил
В теоретических основах мы уже встретили Эдгара Кодда — автора реляционной модели (1970), и идею реляционной полноты. В 1985–1986 годах он дополнил теорию двенадцатью правилами: это практический чек-лист, по которому можно понять, строится ли продукт на реляционной модели по сути, или слово «реляционный» в брошюре — лишь маркетинг.
Важно сразу: PostgreSQL, MySQL, Oracle редко совпадают с правилами буквально на 12 из 12. Правила — компас при выборе СУБД и проектировании API. Они отвечают на вопросы вроде:
- почему данные лежат в таблицах, а метаданные — в каталоге, который тоже можно запросить SQL;
- зачем нужен
NULLи почемуNULL = NULLведёт себя странно; - почему приложение пишет
SELECT … FROM users, а DBA может перенести таблицу на другой диск без правки кода; - почему нельзя «починить» базу, копируя папку с файлами PostgreSQL в проводнике.
Если вы только начинаете путь в SQL — прочитайте сначала Знакомство с базами данных и Реляционную модель. Здесь мы связываем теорию с тем, что вы увидите в information_schema, VIEW и миграциях.
Мини-глоссарий перед правилами
| Термин | Простыми словами |
|---|---|
| Отношение (relation) | Таблица: строки — кортежи, столбцы — атрибуты с типом. |
| Каталог (catalog) | «Паспорт» БД: список таблиц, столбцов, ключей, прав — хранится внутри СУБД и читается запросами. |
Представление (VIEW) | Сохранённый запрос с именем; для приложения выглядит как таблица. |
| Реляционная полнота | Язык (SQL) умеет выразить все основные операции над таблицами: выбор, соединение, проекция, объединение и т.д. |
| Независимость | Приложение опирается на имена таблиц и столбцов; способ хранения на диске может меняться «под капотом». |
| Целостность | Правила «так нельзя»: дубликат ключа, заказ без клиента, отрицательный остаток — СУБД отклонит операцию. |
Нулевое правило — фундамент
Формулировка Кодда (смысл): всё, что СУБД делает с сохранёнными данными, должно выполняться реляционными средствами — таблицами, операциями над отношениями, каталогом.
Если совсем просто: база — это не «папка с Excel и куча скриптов вокруг». Единственный официальный способ прочитать и изменить данные — язык запросов (SQL) и механизмы СУБД (транзакции, ограничения). Файлы на диске (base/, .mdf) — внутренняя кухня; пользователь и приложение с ними не работают напрямую.
На практике:
| Действие | Соответствует правилу 0? |
|---|---|
INSERT INTO orders … через JDBC / ORM | ✓ |
Отчёт в BI по SELECT к PostgreSQL | ✓ |
Скрипт правит байты в каталоге base/ на диске | ✗ (см. правило 12) |
| «Главные» заказы в JSON на диске, в SQL только справочник | ✗ (другая модель хранения) |
Двенадцать правил — обзорная таблица
Нумерация и формулировки близки к классическому изложению Кодда (иногда правило 0 не считают, тогда остаётся ровно двенадцать «нумерованных» требований к продукту).
| № | Название (кратко) | Что требует Кодд |
|---|---|---|
| 1 | Информационное | Вся информация в БД представлена только как значения в таблицах (отношениях). |
| 2 | Гарантированный доступ | Любое значение логически доступно по имени таблицы + первичный ключ + имя столбца. |
| 3 | Обработка NULL | NULL поддерживается единообразно во всех операциях и типах, где это уместно. |
| 4 | Активный каталог | Описание БД (метаданные) хранится в реляционном каталоге и доступно через язык запросов, как обычные данные. |
| 5 | Реляционно полный язык | Есть язык (SQL), на котором можно выразить все операции реляционной алгебры (реляционная полнота). |
| 6 | Обновляемые представления | Все представления, которые теоретически можно обновлять, система должно уметь обновлять. |
| 7 | Высокоуровневые операции | INSERT / UPDATE / DELETE применимы к целому отношению (набору строк), а не только к одной строке за раз на уровне языка. |
| 8 | Физическая независимость | Изменение способа хранения на диске не ломает приложения (индексы, партиции, перенос файлов). |
| 9 | Логическая независимость | Изменение логической схемы (новые столбцы, таблицы) не ломает приложения, если контракт сохранён (часто через VIEW). |
| 10 | Независимость целостности | Ограничения целостности задаются в каталоге и могут меняться без перекомпиляции приложений. |
| 11 | Независимость распределения | При распределённой БД приложение не «знает», на каком узле лежат данные. |
| 12 | Неподрыв | Низкоуровневый доступ не должен позволять обойти ограничения целостности и правила СУБД. |
Дальше — по каждому правилу с пояснением и комментарием «как в жизни».
Правило 1. Информационное
Идея: в реляционной БД нет «специальных» мест для метаданных, настроек и бизнес-фактов на разных принципах — всё сводится к отношениям.
Пример нарушения духа правила: хранить заказы в MongoDB, а «справочник статусов» только в конфиге приложения — это уже другая модель (не единое реляционное хранилище).
В SQL: таблицы orders, users, плюс каталог information_schema — всё в одной парадигме.
Правило 2. Гарантированный доступ
Идея: чтобы получить, например, email пользователя с id = 42, достаточно знать три вещи:
- имя таблицы (отношения) —
users; - значение первичного ключа —
42; - имя столбца —
email.
Номер страницы на диске, смещение в файле, «третья строка снизу в файле» — не входят в контракт.
Разбор запроса по частям:
SELECT email -- (3) какой атрибут нужен
FROM users -- (1) из какого отношения
WHERE id = 42; -- (2) по какому ключу ищем строку
SELECT— «верни столбец»;FROM— «из таблицы»;WHERE id = 42— «строка, у которой первичный ключ равен 42».
Оптимизатор может пойти через индекс по id или прочитать всю таблицу — смысл для программиста тот же (правило 8: физика скрыта).
Составной ключ: в таблице order_items ключ (order_id, line_no). Тогда доступ — по паре:
SELECT product_id
FROM order_items
WHERE order_id = 1001 AND line_no = 3;
Одного order_id недостаточно: в заказе много строк.
Правило 3. Систематическая обработка NULL
Идея: в реальной жизни поле бывает пустым по смыслу: отчество не указали, дата выхода на пенсию ещё не наступила. Кодд требует, чтобы СУБД обрабатывала такое значение одинаково во всех операциях — не «как получится».
NULL — это не ноль и не пустая строка ''. Это специальная метка «значение отсутствует или неизвестно».
Разбор выражений (трёхзначная логика):
| Выражение | Результат | Почему |
|---|---|---|
NULL = NULL | не TRUE | Сравнить «неизвестное» с «неизвестным» нельзя утвердить |
5 = NULL | UNKNOWN | То же |
email IS NULL | TRUE или FALSE | Единственный правильный способ проверить «пусто» |
COUNT(*) по таблице | считает все строки | NULL в ячейке строку не убирает |
COUNT(email) | без NULL в email | Пустые email не входят в счётчик |
-- Ошибка новичка:
SELECT * FROM users WHERE middle_name = NULL; -- всегда пустой результат
-- Правильно:
SELECT * FROM users WHERE middle_name IS NULL;
Подробнее: Реляционная модель.
На проектировании: иногда вместо «магического» NULL вводят отдельную таблицу или флаг has_middle_name — это инженерный выбор, а не отмена правила 3.
Правило 4. Активный каталог
Идея: описание базы (какие есть таблицы, столбцы, типы, ключи) хранится в самой базе в виде обычных таблиц — активный каталог. Его можно прочитать тем же SQL, что и заказы с клиентами.
Пример — «паспорт» таблицы users:
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'users';
Каждая строка результата — один столбец: имя, тип (integer, text), можно ли NULL.
Зачем это вам:
- IDE и DBeaver строят дерево таблиц из каталога;
- Flyway / Liquibase сравнивают желаемую схему с фактической;
- ORM (Hibernate, SQLAlchemy) при старте может сверить модель с БД.
В PostgreSQL: information_schema (стандарт SQL), pg_catalog (внутренние таблицы PG) — Словарь данных и каталоги.
Правило 5. Реляционно полный язык
Идея: один язык (SQL) выражает выборку, соединение, проекцию, объединение, разность — всё, что даёт реляционная алгебра.
Оговорка: SQL исторически допускал дубликаты строк в результате (как мультимножество), тогда как чистое отношение — множество. Современный SELECT DISTINCT и осознанная работа с ключами возвращают дисциплину.
Правило 6. Обновляемые представления
Идея: VIEW — сохранённый запрос с именем. Кодд требует: если представление логически можно обновить (однозначно понятно, какая строка базовой таблицы меняется), СУБД должна это уметь.
Простое обновляемое представление (одна таблица):
CREATE VIEW active_users AS
SELECT id, email FROM users WHERE deleted_at IS NULL;
UPDATE active_users SET email = 'new@example.com' WHERE id = 42;
-- PostgreSQL перенаправит UPDATE в таблицу users
Скорее всего read-only (движок не знает, какую строку orders трогать):
CREATE VIEW revenue_by_customer AS
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id;
-- UPDATE revenue_by_customer SET total = 0 -- бессмысленно для СУБД
Признаки «сложного» view: JOIN нескольких таблиц, GROUP BY, DISTINCT, выражения в SELECT без однозначной обратной проекции. В PostgreSQL смотрите information_schema.views и документацию по updatable views; альтернатива — INSTEAD OF триггер или обновление через API к базовым таблицам.
Правило 7. Высокоуровневые вставка, изменение, удаление
Идея: операции задаются на уровне отношения — одной командой затрагивается множество строк, а не отдельный байт в файле.
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
DELETE FROM sessions WHERE expires_at < NOW();
СУБД сама найдёт затронутые строки, проверит ограничения, запишет WAL. Это связано с транзакциями: одна команда может затронуть тысячи строк атомарно.
Правило 8. Физическая независимость
Идея: меняется как данные лежат на диске — не меняется что видит приложение в SQL.
| Меняет DBA «под капотом» | Меняет ли код приложения? |
|---|---|
| Таблица переехала на SSD | Нет |
Добавили индекс CREATE INDEX … | Нет (тот же SELECT) |
| Партиционирование по месяцам | Нет |
Сменили shared_buffers в конфиге | Нет |
Приложение по-прежнему шлёт SELECT email FROM users WHERE id = 42. Оптимизатор сам решит: идти по индексу или сканировать таблицу.
Связь с энциклопедией: страницы, буферный пул, физическое хранение.
Когда независимость ослабляют осознанно: хинты плана (/*+ IndexScan */), жёсткая привязка к партиции — редкий инженерный компромисс.
Правило 9. Логическая независимость
Идея: меняется структура таблиц (новые столбцы, разбиение сущности) — старые программы продолжают работать через стабильный интерфейс: VIEW, API, промежуточный слой.
| Уровень | Правило 8 (физика) | Правило 9 (логика) |
|---|---|---|
| Что меняется | Диск, индексы, партиции | Имена таблиц/столбцов, нормализация |
| Кто чаще меняет | DBA | Архитектор, разработчик (миграции) |
| Типичный приём | CREATE INDEX | CREATE VIEW users_legacy AS … |
Пример: таблицу users разделили на users + user_profiles, но VIEW users_legacy отдаёт прежний набор столбцов — см. роль БД в организации (Expand–Contract).
Связь с проектированием: Проектирование баз данных.
Правило 10. Независимость целостности
Идея: PRIMARY KEY, FOREIGN KEY, CHECK, UNIQUE хранятся в каталоге, а не размазаны по коду на Python/Java.
Выгода: одно место правды — СУБД отклонит «битую» вставку даже из консоли DBA или скрипта миграции. Синтаксис: Ограничения в SQL.
Правило 11. Независимость распределения
Идея: при шардировании или репликах клиент обращается к логической БД; маршрутизация на узлы — задача middleware или СУБД.
Современность: PostgreSQL с Citus, Oracle RAC, распределённый SQL (CockroachDB, Spanner) — разные степени выполнения. Для одного сервера правило выполняется тривиально.
Правило 12. Неподрыв (nonsubversion)
Идея: если есть низкоуровневый API (файлы данных, процедуры обхода движка), он не должен позволять нарушить ограничения, которые SQL соблюдает.
Почему это важно: именно поэтому «починим БД, скопировав .mdf руками» — путь с риском потери целостности. Администрирование через поддерживаемые утилиты (pg_dump, RMAN, BACKUP DATABASE) сохраняет контракт СУБД.
SQL и «чистая» модель — где учебник расходится с жизнью
Кодд описывал отношения как множества — без дубликатов строк. SQL с самого начала работал с мультимножествами (bag): SELECT без DISTINCT может вернуть одинаковые строки несколько раз. Это не «ломает» реляционность полностью, но объясняет, почему в production принято:
- явно проектировать первичные ключи;
- использовать
DISTINCT, когда нужна уникальность результата; - не полагаться на «случайный» порядок строк без
ORDER BY.
NULL — второй вечный спор. Правило 3 требует системной семантики; в SQL она есть (трёхзначная логика), но NULL перегружен: «неизвестно», «не применимо», «ещё не заполнили». На проектировании иногда заменяют nullable поля отдельными таблицами или явными флагами — это уже инженерный компромисс, не отмена правила.
| Тема | Идеал Кодда | Практика SQL |
|---|---|---|
| Дубликаты строк | Нет | Допустимы без DISTINCT |
| Порядок строк | Не определён | ORDER BY обязателен для стабильного UI |
NULL | Единая семантика | Мощно, но требует дисциплины |
| Вложенные таблицы | Не в 1НФ | JSON/массивы в PostgreSQL — осознанное расширение |
Правила Кодда помогают задавать вопросы при выборе СУБД и проектировании API, а не требуют буквального «SQL = чистая математика».
Разбор на примере — правила 2, 6 и 9 в одном сценарии
Представим таблицы users и orders (упрощённо).
Правило 2 (гарантированный доступ). Запрос email пользователя 42:
SELECT email FROM users WHERE id = 42;
Логический путь: отношение users → ключ 42 → атрибут email. Оптимизатор может идти через индекс по id, но смысл запроса не меняется — это и есть независимость от физики (правило 8).
Правило 9 (логическая независимость). Бизнес просит разделить ФИО на first_name и last_name, но старый микросервис ещё ждёт столбец full_name:
CREATE VIEW users_legacy AS
SELECT id,
first_name || ' ' || last_name AS full_name,
email
FROM users;
Старый код читает users_legacy; новый — напрямую users. После отключения всех клиентов view удаляют — классический Expand–Contract, описанный в роли БД в организации.
Правило 6 (обновляемые представления). View только с колонками из одной таблицы users без агрегации — в PostgreSQL часто updatable. View с JOIN users и orders и SUM(amount) — для автообновления не подходит; отчёт остаётся read-only или обновляется через хранимую процедуру / API.
Насколько «реляционны» PostgreSQL, MySQL, SQL Server?
| Правило | Типичная оценка для зрелой РСУБД |
|---|---|
| 1–5, 7–10 | Выполняются в повседневной работе через SQL |
| 6 | Частично: не все VIEW обновляемы |
| 11 | Зависит от топологии (один узел — да; шард без прозрачности — нет) |
| 12 | Нарушается при прямом вмешательстве в файлы данных |
Ни один продукт обычно не сертифицируют «на 12 из 12» — правила Кодда остаются ориентиром для архитекторов и тендеров.
Связь с тем, что вы уже прошли
- Отношения и ключи — Реляционная модель
- Каталог — 105
- Целостность — 444
- Физика и WAL — 4, Восстановление после сбоя
Контрольные вопросы
- Чем правило 8 (физическая) отличается от правила 9 (логическая) независимости?
- Почему правило 4 делает
information_schemaчастью реляционной модели? - Приведите пример
VIEW, которое, скорее всего, нельзя обновлять (правило 6). - Как правило 12 связано с запретом «чинить» PostgreSQL копированием каталога данных вручную?
- Почему отсутствие
DISTINCTв SQL не отменяет реляционную модель, но влияет на проектирование? - Назовите два способа смягчить проблему «перегруженного»
NULLна этапе схемы.
См. также
- Теоретические основы реляционных данных
- Роль базы данных в организации
- Знакомство с базами данных
- Транзакции и изоляция
- Восстановление после сбоя
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). База данных и СУБД, схемы данных, реляционная и нереляционная модели — вводная глава с разбором терминов relation и relationship. ERD (Entity-Relationship Diagram) — это визуальное представление структуры базы данных. Диаграмма сущность-связь показывает сущности, их атрибуты и отношения между ними. Data governance - роли, правила и процессы, чтобы данные были учтены, защищены и использовались согласованно в организации. Совокупность программных и лингвистических средств, обеспечивающих управление созданием и использованием баз данных. База данных - это ящик с данными, который лежит в архиве - хранилище. СУБД как программный комплекс - хранение, извлечение и изменение данных с гарантиями целостности и безопасности в реляционной модели. Зачем компании централизуют данные, жизненный цикл модели от требований до эксплуатации, роли людей и человеческий фактор в среде БД. Параллельные транзакции — блокировки, MVCC, упорядочение по меткам времени и оптимистичный контроль; когда какой подход выбирать. WAL, контрольные точки, redo и undo — как СУБД переживает обрыв питания и чем это отличается от резервного копирования администратора. Краткие итоги раздела «Основы баз данных». Чек-лист раздела Основы баз данных — вопросы для самопроверки в энциклопедии Вселенная IT.Знакомство с базами данных
Entity Relationship
Управление данными - Data Governance
Системы управления базами данных (СУБД)
Внутреннее устройство баз данных
Теоретические основы реляционных данных
Роль базы данных в организации
Конкурентный доступ к данным
Восстановление после сбоя
Итоги
Чек-лист самопроверки