5. Проектирование схемы БД для клиентов, счетов и платежей
Условие задачи:
Необходимо спроектировать реляционную схему базы данных для трех сущностей:
- клиенты
- счета
- платежи
Нужно определить:
- какие поля должны быть у каждой сущности
- какие первичные и внешние ключи нужны
- как связаны между собой клиенты, счета и платежи
Ожидается, что:
- один клиент может иметь несколько счетов
- каждый счет принадлежит одному клиенту
- платежи должны быть связаны со счетами
- по схеме должно быть понятно, откуда списываются и куда зачисляются деньги, если это предусмотрено логикой
Нужно составить структуру таблиц и описать связи между ними.
Спойлеры к решению
Подсказки
- Между
clientsиaccountsсвязь один ко многим: один клиент может иметь несколько счетов. - В таблице
accountsнужен внешний ключclient_id, который ссылается наclients.id. - Платеж лучше связать сразу с двумя счетами:
from_account_idиto_account_id. from_account_idпоказывает, откуда списываются деньги.to_account_idпоказывает, куда зачисляются деньги.- Для суммы платежа лучше использовать
NUMERIC, а неFLOAT. - Для платежа желательно добавить ограничение
amount > 0. - Чтобы нельзя было перевести деньги с одного счёта на тот же самый счёт, можно добавить
CHECK (from_account_id <> to_account_id).
Решение
CREATE TABLE clients (
id SERIAL PRIMARY KEY,
full_name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE,
phone VARCHAR(50),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
client_id INTEGER NOT NULL,
account_number VARCHAR(50) NOT NULL UNIQUE,
balance NUMERIC(14, 2) NOT NULL DEFAULT 0,
currency CHAR(3) NOT NULL DEFAULT 'RUB',
status VARCHAR(30) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_accounts_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE RESTRICT
);
CREATE TABLE payments (
id SERIAL PRIMARY KEY,
from_account_id INTEGER NOT NULL,
to_account_id INTEGER NOT NULL,
amount NUMERIC(14, 2) NOT NULL,
currency CHAR(3) NOT NULL DEFAULT 'RUB',
status VARCHAR(30) NOT NULL DEFAULT 'created',
purpose TEXT,
payment_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_payments_from_account
FOREIGN KEY (from_account_id)
REFERENCES accounts(id)
ON DELETE RESTRICT,
CONSTRAINT fk_payments_to_account
FOREIGN KEY (to_account_id)
REFERENCES accounts(id)
ON DELETE RESTRICT,
CONSTRAINT chk_payments_amount_positive
CHECK (amount > 0),
CONSTRAINT chk_payments_different_accounts
CHECK (from_account_id <> to_account_id)
);
Связи в этой схеме:
clients 1 ─── N accounts
accounts 1 ─── N payments через payments.from_account_id
accounts 1 ─── N payments через payments.to_account_id
Таблица clients хранит клиентов.
Таблица accounts хранит счета клиентов, каждый счёт принадлежит одному клиенту через поле client_id.
Таблица payments хранит платежи между счетами: поле from_account_id показывает счёт списания, а поле to_account_id показывает счёт зачисления.
Например, если клиент переводит деньги со своего счёта на счёт другого клиента, в payments сохраняется одна запись: от какого счёта ушли деньги, на какой счёт пришли деньги, сумма, валюта, дата и статус платежа.