Антипаттерны SQL Server

Время чтения - 10 мин.Дата публикации 03.04.2026

Создано через GLM-5 на основе репозитория boralp/sql-anti-patterns (который является кратким справочником по книге Билла Карвина "SQL Antipatterns"), вот список основных антипаттернов с кратким описанием на русском языке:

Логическое проектирование базы данных

  1. Jaywalking (Нарушение разметки / Списки через запятую)

    • Суть: Хранение нескольких значений в одном поле через разделитель (например, 1,5,19).
    • Проблема: Невозможно эффективно индексировать, сложно искать и обеспечивать целостность данных.
    • Как правильно: Создать отдельную (зависимую) таблицу для хранения этих значений и связать её с основной через отношение "один-ко-многим" (таблица пересечений / Junction Table).
  2. Naive Trees (Наивные деревья)

    • Суть: Использование списка смежности (хранение parent_id в каждой строке) для работы с древовидными структурами.
    • Проблема: Сложность и рекурсивность запросов для получения полного поддерева.
    • Как правильно: Использовать альтернативные методы, например, Closure Table (таблица замыканий) или Nested Sets (вложенные множества), которые позволяют получать целые поддеревья одним запросом без рекурсии.
  3. ID Required (Лишние ID)

    • Суть: Использование суррогатных ключей (например, AUTO_INCREMENT) везде, даже там, где есть естественный ключ (Natural Key).
    • Проблема: Дублирование ключей, лишняя индексация и потенциальная рассинхронизация данных.
    • Как правильно: Использовать естественные ключи (например, ISO код страны или email пользователя) в качестве первичного ключа, если они уникальны, стабильны и не слишком длинны.
  4. Keyless Entry (Отсутствие ключей)

    • Суть: Создание таблиц без первичного ключа (Primary Key).
    • Проблема: Появление дубликатов строк, невозможность надежно идентифицировать запись.
    • Как правильно: Всегда определять Primary Key для каждой таблицы.
  5. See No Evil (Не вижу зла)

    • Суть: Отказ от использования внешних ключей (Foreign Keys) и ограничений целостности на уровне БД.
    • Проблема: Потеря связи между таблицами, появление «сиротских» записей.
    • Как правильно: Декларировать внешние ключи в схеме базы данных, чтобы СУБД гарантировала ссылочную целостность.
  6. Metadata Tribbles (Трибблы метаданных / EAV)

    • Суть: Использование паттерна Entity-Attribute-Value (три колонки: сущность, атрибут, значение) для хранения разнородных данных.
    • Проблема: Сложные запросы, потеря типов данных, невозможность использовать ограничения SQL.
    • Как правильно: Использовать классическое моделирование (Class Table Inheritance) — создавать отдельные таблицы для подтипов сущностей или специфические колонки для атрибутов.
  7. Polymorphic Associations (Полиморфные ассоциации)

    • Суть: Создание колонки commentable_id и commentable_type, чтобы ссылаться на разные таблицы.
    • Проблема: Невозможно объявить настоящий внешний ключ, сложность JOIN'ов.
    • Как правильно: Создавать отдельные таблицы связей для каждого типа целевой сущности (обратные связи) или использовать общую родительскую таблицу (Supertype/Subtype).
  8. Multicolumn Attributes (Многоколоночные атрибуты)

    • Суть: Создание нескольких колонок для одного атрибута (например, phone1, phone2, phone3).
    • Проблема: Сложность поиска, пустые значения (NULLs), фиксированный лимит количества.
    • Как правильно: Выносить атрибут в дочернюю таблицу (One-to-Many), где каждой строке соответствует одно значение.
 

Физическое проектирование

  1. Phantom Files (Фантомные файлы)

    • Суть: Хранение больших бинарных данных (картинки, PDF) прямо в базе данных.
    • Проблема: Резкое увеличение размера БД, замедление бэкапов и передача тяжелых данных при простых запросах.
    • Как правильно: Хранить файлы в файловой системе или объектном хранилище (S3), а в базе данных хранить только путь или идентификатор файла.
  2. 31 Flavors (31 вкус / Чрезмерное использование ENUM)

    • Суть: Использование типа ENUM для статусов, которые часто меняются.
    • Проблема: Для добавления значения требуется дорогая операция ALTER TABLE.
    • Как правильно: Использовать справочник (Lookup Table) — отдельную таблицу со списком значений и ссылаться на неё по внешнему ключу.
  3. The Black Box (Черный ящик)

    • Суть: Использование универсальных типов (например, VARCHAR(255) для всего).
    • Проблема: Неэффективное использование памяти, отсутствие валидации типа.
    • Как правильно: Использовать наиболее подходящий тип данных (INT, DECIMAL, DATE, VARCHAR(50) и т.д.) для максимальной производительности и валидации.
  4. Read-Only Columns (Колонки только для чтения)

    • Суть: Хранение вычисляемых значений (например, итоговой суммы) как обычных колонок.
    • Проблема: Риск устаревания данных, необходимость триггеров для обновления.
    • Как правильно: Вычислять значение "на лету" в запросе SELECT (сгенерированные колонки / Generated Columns или представление / View).
  5. 12.01.2009 (Даты как строки)

    • Суть: Хранение дат в текстовом формате.
    • Проблема: Сложность сортировки и выборки по диапазону, невозможность использования функций дат.
    • Как правильно: Использовать нативные типы данных: DATE, DATETIME, TIMESTAMP.
 

Запросы

  1. Poor Man's Search Engine (Поисковик для бедных)

    • Суть: Использование LIKE '%text%' для поиска.
    • Проблема: Полное сканирование таблицы, не работает с индексами.
    • Как правильно: Использовать встроенные инструменты полнотекстового поиска (Full-Text Search, например, MATCH ... AGAINST в MySQL) или внешние поисковые движки (Elasticsearch).
  2. Random Selection (Случайная выборка)

    • Суть: Использование ORDER BY RAND() для получения случайной строки.
    • Проблема: СУБД генерирует случайное число для каждой строки, убивая производительность.
    • Как правильно: Выбрать случайное число на уровне приложения и запросить строку с ID, большим этого числа (например, WHERE id > ? ORDER BY id LIMIT 1), либо предварительно вычислить количество строк и выбрать случайный смещение (OFFSET).
  3. Spaghetti Query (Запрос-спагетти)

    • Суть: Написание огромных монструозных запросов.
    • Проблема: Невозможность оптимизации и поддержки.
    • Как правильно: Разбивать сложную логику на несколько простых запросов, использовать временные таблицы, представления (Views) или курсоры (в хранимых процедурах).
 

Разработка приложений

  1. Password Anti-pattern (Парольный антипаттерн)

    • Суть: Хранение паролей в открытом виде.
    • Проблема: При утечке БД пароли станут известны злоумышленникам.
    • Как правильно: Хранить только хеш пароля с использованием "соли" и стойких алгоритмов (bcrypt, Argon2, scrypt).
  2. SQL Injection (SQL-инъекция)

    • Суть: Сборка SQL-запросов строковой конкатенацией.
    • Проблема: Злоумышленник может исполнить произвольный SQL-код.
    • Как правильно: Использовать параметризованные запросы (Prepared Statements) и ORM-библиотеки.
Насколько полезной была статья?

Что еще посмотреть по SQL Server

Как кешировать в SQL результаты сложных операций

Как искать зависимости объектов в SQL Server

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

Формирование сложного JSON объекта через SELECT в SQL Server

Как вставить данные в таблицу БД из таблицы на другом сервере

Использование CPU в SQL Server Express Edition

Как форматировать код sql в sql server management studio

Альтернатива множественному Replace

Разбор строки на части и занесение в табличную переменную

Из строки в таблицу. Функция split

Как оптимизировать массовые операции Update/delete

Как избежать дедлоков

Дополнительный заработок для разработчиков на T-SQL

Прямая работа с заказчиками как ИП или самозанятый. Нужно знать только SQL и HTML.
Falcon Space - платформа для создания сайтов с личными кабинетами
В 2-3 раза экономнее и быстрее, чем заказная разработка
Более гибкая, чем коробочные решения и облачные сервисы
Используйте готовые решения и изменяйте под свои потребности
Запрос расчета стоимости веб-проекта на базе Falcon Space
Если видео Youtube плохо грузится, то попробуйте найти видео в ВК видео на канале Falcon Space
Сайт использует Cookie, Яндекс Метрику. Используя сайт, вы соглашаетесь с правилами сайта. См. Правила конфиденциальности и Правила использования сайта OK