TGViewer
Python for Devs Python for Devs @python_for_devs · 801 subscribers
Post #43 438
🔧 Целостность данных JSON-колонок в PostgreSQL

JSON всё чаще используют в реляционных базах данных — он позволяет хранить гибкие структуры и избавляет от избыточных связей между таблицами. Но вместе с удобством появляется риск: данные могут потерять предсказуемость.

Если не контролировать содержимое JSON-колонок, туда легко попадут неожиданные значения: числа вместо строк, объекты вместо массивов. В итоге приложение может «сломаться» на ровном месте.

В MySQL проверка JSON поддерживается из коробки. В PostgreSQL для этого есть расширение, которое позволяет валидировать данные по JSON-схеме прямо на уровне БД.

Пример: у нас есть таблица products с колонкой attributes, где хранятся характеристики товара.


CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
attributes JSON NOT NULL DEFAULT '{}'
);


Мы ожидаем, что поле tags внутри этого JSON будет массивом строк. Однако без строгой проверки на уровне базы данных нет гарантии, что кто-то не запишет туда числа, объекты или вообще что-то неподходящее.

Чтобы сохранить гибкость JSON и одновременно обеспечить строгую структуру данных, можно использовать валидацию JSON-схемы на уровне базы данных. Для этого нужно добавить constraint, который автоматически проверит соответствие содержимого JSON определенной схеме при каждой операции вставки или обновления.

Пример для PostgreSQL:


ALTER TABLE products ADD CONSTRAINT data_is_valid CHECK(
validate_json_schema(
'{
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": { "type": "string" }
}
},
"additionalProperties": false
}',
attributes
)
);


Теперь, попытка вставить данные с невалидным значение для tags приведёт к ошибке:


INSERT INTO products (..., attributes) VALUES
(..., '{}'), -- Пустой объект, допускается
(..., '{"tags": []}'), -- Пустой массив строк
(..., '{"tags": ["test"]}'); -- Массив со строкой
-- Результат: Операция успешна

INSERT INTO products (..., attributes) VALUES
(..., '{"tags": [2]}'); -- Массив с числом вместо строки
-- Ошибка: Нарушен constraint
  • 👍 6
  • 🔥 5
  • ❤ 2
More from @python_for_devs
  1. Sep 30, 2026Тут больше не будет новостей, статей и постов про Python. Python-разработчику сейчас важне…
  2. Jan 23, 2026⚰️ 2025 год для Flask прошёл почти без движений За год вышло всего два патч-релиза к верси…
  3. Jan 16, 2026В новой статье разбираем попытку превратить Python в формат распространения уровня «один б…
  4. Jan 13, 2026🔥 Anthropic инвестируют $1.5 млн в Python — и делают ставку на безопасность open source A…
  5. Jan 12, 2026⚡️ DuckDB разрушает мифы: 1 ТБ данных — за секунды, без Spark Принято считать, что терабай…
  6. Dec 29, 2025🎄 Итоги года 4Devs 2025 На прошлой неделе Habr опубликовал итоги года — и наш проект попа…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →