Saya menggunakan PostgreSQL tapi saya pikir sebagian besar top-end db harus memiliki beberapa kemampuan yang serupa, dan terlebih lagi, solusi bagi mereka dapat menginspirasi solusi bagi saya, jadi jangan pertimbangkan PostgreSQL khusus ini.
Saya tahu saya bukan orang pertama yang mencoba menyelesaikan masalah ini, jadi saya pikir pantas untuk ditanyakan di sini, tetapi saya mencoba untuk mengevaluasi biaya pemodelan data akuntansi sehingga setiap transaksi seimbang secara fundamental. Data akuntansi hanya ditambahkan. Batasan keseluruhan (ditulis dalam pseudo-code) di sini mungkin terlihat kira-kira seperti:
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
);
Jelas kendala pemeriksaan seperti itu tidak akan pernah berhasil. Ini beroperasi per baris dan mungkin memeriksa seluruh db. Jadi itu akan selalu gagal dan lambat melakukannya.
Jadi pertanyaan saya adalah apa cara terbaik untuk memodelkan batasan ini? Saya pada dasarnya telah melihat dua ide sejauh ini. Ingin tahu apakah ini satu-satunya, atau jika seseorang memiliki cara yang lebih baik (selain menyerahkannya ke tingkat aplikasi atau proc yang disimpan).
- Saya bisa meminjam halaman dari konsep dunia akuntansi tentang perbedaan antara buku entri asli dan buku entri akhir (jurnal umum vs buku besar). Dalam hal ini saya bisa memodelkan ini sebagai array dari garis jurnal yang dilampirkan pada entri jurnal, menegakkan batasan pada array (dalam istilah PostgreSQL, pilih jumlah (jumlah) = 0 dari undest (je.line_items). Pemicu dapat berkembang dan simpan ini ke tabel item baris, di mana batasan kolom individu bisa lebih mudah ditegakkan, dan di mana indeks dll bisa lebih berguna. Ini adalah arah yang saya condongkan.
- Saya bisa mencoba kode pemicu kendala yang akan memberlakukan ini per transaksi dengan gagasan bahwa jumlah rangkaian 0 akan selalu 0.
Saya menimbang ini terhadap pendekatan saat ini menegakkan logika dalam prosedur tersimpan. Biaya kompleksitas ditimbang terhadap gagasan bahwa bukti matematika kendala lebih unggul daripada tes unit. Kelemahan utama # 1 di atas adalah bahwa tipe sebagai tupel adalah salah satu area di PostgreSQL di mana orang mengalami perilaku yang tidak konsisten dan perubahan asumsi secara teratur sehingga saya bahkan berharap perilaku di area ini dapat berubah seiring waktu. Merancang versi aman di masa depan tidaklah mudah.
Apakah ada cara lain untuk memecahkan masalah ini yang akan skala hingga jutaan catatan di setiap tabel? Apakah saya melewatkan sesuatu? Apakah ada tradeoff yang saya lewatkan?
Menanggapi poin Craig di bawah ini tentang versi, paling tidak, ini harus dijalankan pada PostgreSQL 9.2 dan lebih tinggi (mungkin 9,1 dan lebih tinggi, tetapi mungkin kita bisa langsung menggunakan 9.2).
sumber
DELETE
. Saya tidak akan tahu apa yang khas atau diperlukan dalam akuntansi - bukan bidang keahlian saya. Hanya mencoba memberikan solusi (IMO sangat efektif) untuk masalah yang dijelaskan.Solusi SQL Server berikut ini hanya menggunakan kendala. Saya menggunakan pendekatan serupa di banyak tempat di sistem saya.
sumber
dbo.
danGO
): sql-fiddleFK_Lines_PreviousLine
batasan kunci asing.