Я використовую PostgreSQL, але я вважаю, що більшість верхніх точок повинні мати деякі подібні можливості, і, тим більше, що рішення для них можуть надихати рішення для мене, тому не враховуйте цей PostgreSQL.
Я знаю, що я не перший, хто намагається вирішити цю проблему, тому вважаю, що тут варто запитати, але я намагаюся оцінити витрати на моделювання даних бухгалтерського обліку таким чином, щоб кожна транзакція була в основному збалансована. Дані бухгалтерського обліку є лише додатками. Загальне обмеження (написане псевдокодом) може виглядати приблизно так:
CREATE TABLE journal_entry (
id bigserial not null unique, --artificial candidate key
journal_type_id int references journal_type(id),
reference text, -- source document identifier, unique per journal
date_posted date not null,
PRIMARY KEY (journal_type_id, reference)
);
CREATE TABLE journal_line (
entry_id bigint references journal_entry(id),
account_id int not null references account(id),
amount numeric not null,
line_id bigserial not null unique,
CHECK ((sum(amount) over (partition by entry_id) = 0) -- this won't work
);
Очевидно, таке обмеження перевірки ніколи не спрацює. Він працює на рядок і може перевіряти весь db. Тож воно завжди буде провалюватися і буде повільно це робити.
Тож моє запитання - який найкращий спосіб моделювати це обмеження? Я в основному розглядав дві ідеї до цих пір. Цікаво, чи це єдині, чи хтось має кращий спосіб (окрім того, щоб залишити його на рівні додатків чи збережених програм).
- Я міг би запозичити сторінку із світового поняття бухгалтерського обліку про різницю між книгою оригіналу та книгою остаточного запису (загальний журнал проти загальної книги). У зв'язку з цим я міг би моделювати це як масив журнальних рядків, приєднаних до запису журналу, примусово застосовувати обмеження на масив (у термінах PostgreSQL виберіть суму (сума) = 0 від unnest (je.line_items). Тригер може розширитись і збережіть їх у таблиці рядків-позицій, де окремі обмеження стовпців можна легше застосувати, і де індекси тощо можуть бути кориснішими. Це напрямок, на який я схиляюся.
- Я міг би спробувати кодувати тригер обмеження, який би примусив це застосовувати кожну транзакцію з думкою про те, що сума серії 0 завжди буде дорівнює 0.
Я зважую їх проти поточного підходу до застосування логіки у збереженій процедурі. Вартість складності зважується на думку про те, що математичне доведення обмежень перевершує одиничні тести. Основним недоліком №1 вище є те, що типи як кортежі є однією з тих областей у PostgreSQL, де людина стикається з непослідовною поведінкою та зміною припущень регулярно, тому я навіть сподіваюся, що поведінка в цій області може змінитися з часом. Розробити майбутню безпечну версію не так просто.
Чи існують інші способи вирішення цієї проблеми, які дозволять масштабувати до мільйонів записів у кожній таблиці? Я щось пропускаю? Чи є компроміс, який я пропустив?
У відповідь на точку Крейга щодо версій, як мінімум, це доведеться працювати на PostgreSQL 9.2 і вище (можливо, 9.1 і вище, але, мабуть, ми можемо піти з прямим 9.2).