This media is not supported in your browser
VIEW IN TELEGRAM
Материалы посвящены не написанию SQL-запросов, а архитектуре СУБД и внутренним механизмам обработки и хранения данных. Подробно рассматриваются физическая структура базы данных, системные каталоги, управление транзакциями, блокировки, WAL и др.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍9❤3🤝1
Проверяйте связи с учётом периода!
В PostgreSQL 18 связь может учитывать ещё и период его действия.
А теперь интересная часть:
Период скидки должен быть покрыт соответствующими периодами родительской таблицы. Причём покрытие может обеспечиваться несколькими соседними строками, а не обязательно одной.
Например, такую логику больше не обязательно проверять вручную перед записью:
🔥 В PostgreSQL 18
➡️ SQL Ready | #совет
В PostgreSQL 18 связь может учитывать ещё и период его действия.
WITHOUT OVERLAPS не даст создать пересекающиеся периоды для одного product_id. По сути PostgreSQL сам обеспечивает проверку пересечения диапазонов. А теперь интересная часть:
CREATE TABLE discounts (
product_id bigint,
valid_at daterange,
FOREIGN KEY (
product_id,
PERIOD valid_at
)
REFERENCES prices (
product_id,
PERIOD valid_at
)
);
Период скидки должен быть покрыт соответствующими периодами родительской таблицы. Причём покрытие может обеспечиваться несколькими соседними строками, а не обязательно одной.
Например, такую логику больше не обязательно проверять вручную перед записью:
INSERT INTO discounts
VALUES (
42,
'[2026-05-01,2026-05-15)'::daterange
);
PERIOD позволяет проверять временные связи обычным FOREIGN KEY — без триггеров и ручных проверок.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤9🔥6
Например, Replication повышает доступность и отказоустойчивость за счёт хранения копий данных на нескольких узлах, а Sharding позволяет горизонтально масштабировать систему, распределяя данные между независимыми шардами.
Эти паттерны помогают решать основные задачи распределённых систем: масштабирование, отказоустойчивость, распределение данных, асинхронное взаимодействие и согласованность.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍7🤝5❤3
Почему UNIQUE допускает несколько NULL в PostgreSQL!
Ограничение
Повторное определённое значение
При использовании
Особенно важно учитывать это поведение в составных ключах, где один из столбцов может быть неопределённым:
Одинаковые определённые значения
Начиная с PostgreSQL 15 это поведение можно изменить через
Теперь сохранить две строки с одной комбинацией
Та же семантика поддерживается уникальными индексами, поэтому правило можно выразить непосредственно на уровне индекса.
В такой таблице может существовать одна строка с
🔥
➡️ SQL Ready | #практика
Ограничение
UNIQUE гарантирует уникальность значений, но для NULL в PostgreSQL действует отдельная семантика. По умолчанию два NULL считаются различными при проверке уникальности, поэтому ограничение не запрещает несколько строк с неопределённым значением:CREATE TABLE users (
id BIGINT PRIMARY KEY,
email TEXT UNIQUE
);
Повторное определённое значение
email нарушит ограничение уникальности.INSERT INTO users (id, email)
VALUES (1, 'user@example.com');
INSERT INTO users (id, email)
VALUES (2, 'user@example.com');
При использовании
NULL те же правила не применяются: несколько строк успешно проходят проверку ограничения.INSERT INTO users (id, email)
VALUES
(3, NULL),
(4, NULL),
(5, NULL);
Особенно важно учитывать это поведение в составных ключах, где один из столбцов может быть неопределённым:
CREATE TABLE contacts (
id BIGINT PRIMARY KEY,
company_id BIGINT NOT NULL,
external_id TEXT,
UNIQUE (company_id, external_id)
);
Одинаковые определённые значения
(company_id, external_id) конфликтуют, но несколько комбинаций (10, NULL) по умолчанию допустимы:INSERT INTO contacts (id, company_id, external_id)
VALUES
(1, 10, NULL),
(2, 10, NULL);
Начиная с PostgreSQL 15 это поведение можно изменить через
NULLS NOT DISTINCT. В таком ограничении NULL считаются неразличимыми при проверке уникальности:CREATE TABLE contacts_strict (
id BIGINT PRIMARY KEY,
company_id BIGINT NOT NULL,
external_id TEXT,
UNIQUE NULLS NOT DISTINCT (company_id, external_id)
);
Теперь сохранить две строки с одной комбинацией
(10, NULL) нельзя: вторая вставка завершится нарушением уникальности.INSERT INTO contacts_strict (id, company_id, external_id)
VALUES (1, 10, NULL);
INSERT INTO contacts_strict (id, company_id, external_id)
VALUES (2, 10, NULL);
Та же семантика поддерживается уникальными индексами, поэтому правило можно выразить непосредственно на уровне индекса.
CREATE UNIQUE INDEX uq_contacts_company_external
ON contacts (company_id, external_id)
NULLS NOT DISTINCT;
NULLS NOT DISTINCT не эквивалентен NOT NULL. NOT NULL полностью запрещает отсутствие значения, тогда как NULLS NOT DISTINCT разрешает NULL, но включает его в контроль уникальности.CREATE TABLE identifiers (
id BIGINT PRIMARY KEY,
external_id TEXT,
UNIQUE NULLS NOT DISTINCT (external_id)
);
В такой таблице может существовать одна строка с
external_id IS NULL, но вторая аналогичная строка уже нарушит ограничение.UNIQUE в PostgreSQL по умолчанию допускает несколько NULL. Если отсутствие значения также должно быть уникальным состоянием, начиная с PostgreSQL 15 это можно явно зафиксировать через NULLS NOT DISTINCT.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6🤝5❤1
This media is not supported in your browser
VIEW IN TELEGRAM
Материал ведёт от первых SQL-запросов и проектирования схем до индексов, транзакций, оптимизации и работы с БД из Python через SQLAlchemy и Alembic. Особенно полезно, что SQLite и PostgreSQL изучаются параллельно: автор показывает различия между ними, типичные ошибки и ситуации, где выбор СУБД имеет значение.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤9🔥5🤝2😁1
Обновляйте несколько колонок одним подзапросом!
Вместо нескольких одинаковых подзапросов:
можно написать:
Особенно удобно, когда вычисления сложнее:
Не нужно дублировать условия и поддерживать несколько почти одинаковых подзапросов.
🔥
➡️ SQL Ready | #совет
Вместо нескольких одинаковых подзапросов:
UPDATE orders o
SET customer_name = (
SELECT name FROM customers WHERE id = o.customer_id
),
customer_email = (
SELECT email FROM customers WHERE id = o.customer_id
);
можно написать:
-- Один подзапрос сразу для нескольких колонок
UPDATE orders o
SET (customer_name, customer_email) = (
SELECT c.name, c.email
FROM customers c
WHERE c.id = o.customer_id
);
Особенно удобно, когда вычисления сложнее:
UPDATE accounts a
SET (last_payment_at, total_paid) = (
SELECT max(p.created_at),
sum(p.amount)
FROM payments p
WHERE p.account_id = a.id
);
Не нужно дублировать условия и поддерживать несколько почти одинаковых подзапросов.
SET (a, b, ...) = (SELECT ...) позволяет одним подзапросом вычислить сразу несколько новых значений строки и заметно сокращает повторяющийся SQL.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤7👍5🤝1
Получение первых N строк с FETCH FIRST, постраничная выборка с FETCH NEXT и OFFSET, включение строк с одинаковыми значениями сортировки через WITH TIES, ограничение результата в процентах с PERCENT, использование ROWNUM, а также нумерация и ранжирование с ROW_NUMBER() и DENSE_RANK(). Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍10❤6