Mengapa kendala diterapkan dalam database daripada kode?


21

Mengapa kendala diterapkan dalam Database? Apakah tidak akan lebih fleksibel untuk memasukkannya ke dalam kode?

Saya membaca buku pemula tentang mengimplementasikan database, jadi saya meminta ini sebagai pemula. Katakanlah saya telah mendesain database, termasuk model entitas ini:

 entity type    |   sub-types
----------------+--------------------------------------------
   Person       |   Employee, Student,       ...
   Student      |   Graduate, Undergraduate, ...
   Employee     |   Teacher,  Administrator, ...

Kendala saat ini:

  1. Orang yang terdaftar pada sistem hanya dapat menjadi Siswa atau Karyawan.
  2. Entitas pribadi memerlukan keunikan bilangan sosial, yang kami anggap setiap orang hanya memiliki satu nomor unik (alias, kunci utama yang cukup bagus ). (lihat # 1)

Kemudian kami memutuskan untuk menghapus nomor 1: Jika suatu hari perguruan tinggi memutuskan bahwa Teacher( Employeesub-tipe) dapat juga Student, mengambil kursus di waktu luang mereka, jauh lebih sulit untuk mengubah desain basis data yang dapat memiliki ribuan, jutaan, miliaran, zillions entri daripada hanya mengubah logika dalam kode: hanya bagian yang tidak memungkinkan seseorang didaftarkan baik sebagai siswa dan karyawan.

(Ini sangat mustahil tetapi saya tidak bisa memikirkan hal lain saat ini. Rupanya itu mungkin).

Mengapa kita peduli dengan aturan bisnis dalam desain database daripada dalam kode?

# 1: Sebuah catatan 7 tahun kemudian, contoh kehidupan nyata:
Saya telah melihat pemerintah di mana karena kesalahan, SSN yang dikeluarkan digandakan: banyak orang, SSN yang sama. Mereka yang merancang DB asli pasti membuat kesalahan dengan tidak menerapkan kendala keunikan ini dalam database. (dan kemudian bug dalam aplikasi asli? beberapa aplikasi menggunakan database bersama dan tidak menyetujui tempat untuk meletakkan, memeriksa dan menegakkan batasan? ...).
Bug ini akan terus hidup dalam sistem dan semua sistem yang dikembangkan setelah itu bergantung pada database sistem asli itu, selama bertahun-tahun yang akan datang. Membaca jawaban di sini saya belajar menerapkan semua kendala, sebanyak mungkin dari mereka, dengan bijak (tidak secara membabi buta) dalam database untuk mewakili dunia fisik nyata di luar sana sebaik yang saya bisa.


2
Sebagian besar kami peduli dengan aturan bisnis yang ditegakkan dan apa cara terbaik untuk itu.
ypercubeᵀᴹ

3
Anda sebenarnya memberikan contoh yang sangat buruk tentang batasan apa yang digunakan, karena fleksibilitas entitas Anda, dan perluasan basis data, sebagian besar ditentukan oleh normalisasi. Karena itu, kendala adalah perlindungan terakhir terhadap data korup yang pernah masuk ke dalam database, bahkan jika aplikasi disadap, bahkan jika aplikasi baru dikembangkan, bahkan jika API eksternal ditambahkan, bahkan jika seseorang mengedit DB secara langsung. Kendala menjaga database, di atas itu logika bisnis juga harus melakukan hal-hal sendiri sebelum mencoba mengakses DB.
Niels Keurentjes

3
Sebenarnya, sebagai mahasiswa pascasarjana saya dianggap sebagai Mahasiswa, Karyawan, dan Guru. Jadi contoh Anda tidak terlalu mustahil.
Winston Ewert

4
Anda seharusnya tidak pernah mendasarkan desain database pada objek dalam aplikasi Anda. Anda biasanya akan merancang ini sebagai orang, kemudian memiliki tabel terkait untuk menentukan peran orang tersebut. Maka masalahnya tidak muncul karena Anda memiliki tabel realted untuk peran sehingga orang dapat memiliki beberapa peran. Jika Anda ingin hanya memiliki satu orang peran, maka Anda membatasi tabel sehingga peopleID itu unik. Ketika Anda ingin mengubah itu menghapus kendala.
HLGEM

Objek <-> Pemetaan relasional adalah seni.
Thorbjørn Ravn Andersen

Jawaban:


34

Beberapa kendala paling baik ditegakkan dalam database, dan beberapa yang terbaik ditegakkan dalam aplikasi.

Kendala yang paling baik ditegakkan dalam database biasanya ada karena mereka mendasar bagi struktur model data, seperti batasan kunci asing untuk memastikan bahwa suatu produk memiliki valid category_id.

Kendala yang ditegakkan dalam suatu aplikasi mungkin tidak mendasar bagi model data, seperti semua produk FooBar harus berwarna biru - tetapi kemudian seseorang mungkin memutuskan bahwa FooBars juga bisa berwarna kuning. Ini adalah logika aplikasi yang tidak benar-benar perlu ada dalam database, meskipun Anda bisa membuat colourstabel terpisah dan database dapat meminta referensi produk entri yang valid dari tabel itu. TETAPI keputusan bahwa satu-satunya catatan yang coloursmemiliki nilai masihblue akan datang dari suatu tempat di luar basis data.

Pertimbangkan apa yang akan terjadi jika Anda tidak memiliki kendala dalam database, dan mengharuskan mereka untuk semua diberlakukan dalam aplikasi. Apa yang akan terjadi jika Anda memiliki lebih dari satu aplikasi yang perlu bekerja dengan data? Seperti apa data Anda jika aplikasi yang berbeda memutuskan untuk memberlakukan berbagai kendala secara berbeda?

Contoh Anda menunjukkan situasi di mana mungkin lebih bermanfaat untuk memiliki kendala dalam aplikasi daripada dalam database, tetapi mungkin ada masalah mendasar dengan model data awal yang terlalu ketat dan tidak fleksibel?


Jadi menurut jawaban ini, Aturan <a person hanya dapat ada di tabel subtipe Student atau hanya di tabel subtype Employee> harus diterapkan dalam kode, Dan Database memiliki <Subtipe Student / Employee harus valid orang> kendala. Apakah saya benar? (Itu contoh buku). Terima kasih.
hkoosha

2
@loolooyyyy: Ya, saya pikir itu benar. Jika database menegakkan aturan pertama (bahwa seseorang hanya dapat menjadi siswa atau karyawan) maka situasi yang Anda jelaskan (di mana seorang karyawan ingin mendaftar untuk suatu kelas) tidak mungkin karena: orang tersebut tidak dapat keduanya, dan itu bukan bahkan mungkin untuk membuat catatan "orang" kedua karena mereka tidak dapat membagikan Nomor Jaminan Sosial yang mungkin dikeluarkan dari pihak ketiga (seperti pemerintah). Tentu saja, model data yang terlalu membatasi ini mungkin berfungsi untuk beberapa kasus ...
FrustratedWithFormsDesigner

2
@loolooyyyy: Cara lain untuk menggunakan model data asli dan masih membiarkan guru menjadi siswa mungkin dengan memiliki tabel lain yang disebut teachers_as_studentssubtipe lain Studentsdan memiliki kunci asing yang merujuk Teachers, dan kunci primer yang dihasilkan sistem , bukan Sosial Nomor keamanan. Dengan cara ini, "siswa" sebenarnya adalah alias untuk seorang guru sehingga guru masih bisa mendaftar untuk mengambil kelas. Sulit untuk mengatakan dengan pasti seberapa baik ini akan bekerja tanpa melihat seluruh model data.
FrustratedWithFormsDesigner

2
Saya menurunkan ini. Tidak ada waktu ketika kendala paling baik diterapkan dalam aplikasi saja. Nada dari jawaban ini tertimbang tidak tepat.
Evan Carroll

3
@FrustratedWithFormsDesigner tentu saja, itu sebenarnya adalah anak poster untuk batasan kunci asing. Asumsikan Anda memiliki tiga klien dari versi yang berbeda / membangun titik akses db, apa yang akan Anda lakukan ketika Anda menghentikan pengiriman produk berwarna merah? Di mana Anda akan menyimpan daftar kemungkinan kombinasi warna? Petunjuk: Saya punya tempat tersentralisasi untuk Anda. Dan jika Anda membuat tabel color_products, dan color, Anda mungkin akan dapat membuat drop down tambahan dengan lebih mudah - sebagian besar IDE / schema loader, mendukung fkeys berikut.
Evan Carroll

35

Karena:

  1. Saya ingin semua data dalam database tunduk pada batasan yang sama, bukan hanya data baru yang tunduk pada batasan dalam versi kode yang berjalan hari ini.
  2. Saya ingin batasan deklaratif, bukan batasan program.
  3. Data dalam database sering hidup lebih lama dari kode yang ditulis untuk berinteraksi dengannya hari ini. Dan data itu - bukan kode - adalah aset organisasi.
  4. Kode saya menjadi jauh lebih sederhana ketika saya tahu bahwa semua data tunduk pada batasan yang ketat. Saya tidak lagi harus mempertimbangkan kasus khusus yang saya tahu bahwa database menjamin tidak mungkin.

Hanya beberapa alasan yang penting bagi saya.


4
Semi-terkait dengan (1) dan (3): bug dalam kode aplikasi dapat diperbaiki, bug dalam data Anda seringkali tidak dapat diperbaiki.
mu terlalu pendek

17

Data kemungkinan akan lama hidup lebih lama dari kode aplikasi. Jika aturan sangat penting untuk data yang berguna dari waktu ke waktu (seperti batasan kunci asing yang membantu menjaga integritas data), aturan itu harus ada dalam database. Kalau tidak, Anda berisiko kehilangan kendala dalam aplikasi baru yang mengenai database. Tidak hanya beberapa aplikasi memukul basis data (Termasuk beberapa yang mungkin tidak menyadari ada aturan data penting) tetapi beberapa dari mereka seperti impor data atau aplikasi pelaporan mungkin tidak dapat menggunakan lapisan data yang diatur dalam aplikasi entri data utama. Sejujurnya, kemungkinan ada bug dalam kendala jauh lebih tinggi dalam kode aplikasi dalam pengalaman saya.

Menurut pendapat pribadi saya (berdasarkan lebih dari 30 tahun berurusan dengan data dan pengalaman dengan ratusan basis data yang berbeda yang digunakan untuk berbagai tujuan) siapa pun yang tidak menempatkan kendala dalam basis data di mana mereka berada pada akhirnya akan memiliki data yang buruk. Terkadang data yang buruk sampai tidak dapat digunakan lagi. Ini terutama berlaku di mana Anda memiliki data keuangan / peraturan yang perlu memenuhi kriteria tertentu untuk diaudit.


17

Sebagian besar kendala integritas referensial yang diterapkan di luar basis data dapat dikalahkan, jadi jika Anda ingin data Anda memiliki integritas yang terjamin setiap saat, maka Anda harus menerapkan batasan dalam basis data. Berhenti penuh, itu saja.

Kendala tingkat aplikasi biasanya dikalahkan meskipun database membaca mekanisme konsistensi, dimana sesi tidak dapat melihat data sesi lain sampai berkomitmen.

Misalnya, dua sesi dapat mencoba memasukkan nilai yang sama ke dalam kolom yang dimaksudkan untuk menjadi unik. Mereka berdua dapat memeriksa pada saat yang sama bahwa nilainya belum ada, keduanya dapat memasukkan nilainya, dan keduanya dapat melakukan komit. Kendala unik yang diterapkan dalam database tidak akan membiarkan ini terjadi.

Omong-omong, ini bukan hal yang asing bagi para perancang bahasa aplikasi. Baca bagian 3.10 keunikan dalam Panduan Ruby on Rails: Validasi Rekaman Aktif dan Callback

Pembantu ini memvalidasi bahwa nilai atribut unik tepat sebelum objek disimpan. Itu tidak membuat batasan keunikan dalam database, sehingga mungkin terjadi bahwa dua koneksi database yang berbeda membuat dua catatan dengan nilai yang sama untuk kolom yang Anda ingin menjadi unik. Untuk menghindarinya, Anda harus membuat indeks unik di basis data Anda.


16

Manfaat kendala yang ditegakkan oleh database:

Kesederhanaan - Mendeklarasikan kendala secara signifikan lebih sederhana daripada mendeklarasikan kendala dan menulis kode yang akan menegakkan deklarasi itu.

Akurasi - Kode yang tidak Anda tulis tidak akan pernah memiliki bug yang Anda buat. Vendor database menghabiskan waktu memastikan kode kendala mereka akurat, jadi Anda tidak perlu melakukannya.

Kecepatan - Aplikasi Anda tidak akan pernah memiliki distribusi lebih dari basis data yang digunakannya. Vendor basis data menghabiskan waktu memastikan kode kendala mereka efisien, jadi Anda tidak perlu melakukannya. Basis data itu sendiri juga memiliki akses lebih cepat ke data daripada yang bisa dilakukan oleh suatu aplikasi terlepas dari seberapa efisiennya.

Penggunaan kembali - Anda dapat mulai dengan satu aplikasi pada satu platform, tetapi mungkin tidak tetap seperti itu. Bagaimana jika Anda perlu mengakses data dari OS yang berbeda, perangkat keras yang berbeda, atau dari antarmuka suara? Dengan memiliki kendala dalam database, kode ini tidak harus ditulis ulang untuk platform baru dan tidak pernah harus di-debug untuk akurasi atau profil untuk kecepatan.

Kelengkapan - Aplikasi memberlakukan batasan saat data dimasukkan ke dalam basis data dan akan membutuhkan upaya tambahan untuk memverifikasi data yang lebih tua akurat atau untuk memanipulasi data yang sudah ada dalam basis data.

Panjang Umur - Platform database Anda kemungkinan akan hidup lebih lama dari aplikasi tertentu.


11

Mengapa kendala diterapkan di server? Karena Anda tidak dapat memaksa orang jahat untuk menggunakan klien Anda.

Untuk memperjelas, jika Anda hanya melakukan pemrosesan aturan bisnis dalam aplikasi klien Anda maka seseorang yang menggunakan alat lain dapat terhubung ke server database dan melakukan apa pun yang mereka inginkan tanpa dibatasi oleh aturan bisnis Anda dan pemeriksaan integritas. Menghentikan siapa pun dari menggunakan alat sewenang-wenang di mana pun di jaringan sangat sulit.

Jika Anda melakukan pemeriksaan integritas pada server database maka setiap upaya untuk mengakses data, apa pun alatnya, akan dibatasi oleh aturan Anda.


10

Beberapa jawaban bagus di sini, dan dengan risiko mengulang pemikiran lain:

  • SSN belum tentu unik. Heck, SSN bahkan tidak selalu dikenal, dan dalam beberapa kasus tidak ada (belum). SSN dapat digunakan kembali dan tidak semua karyawan atau siswa mungkin pernah memiliki SSN. Ini merupakan bagian dari pertanyaan tetapi menunjukkan bahwa, di mana pun Anda menegakkan kendala, Anda perlu memahami model data dan domain dengan cukup teliti untuk membuat keputusan tentang aturan bisnis.
  • Secara pribadi saya lebih suka kendala sedekat mungkin dengan data. Alasan yang sangat sederhana adalah bahwa tidak semua orang akan menggunakan kode aplikasi untuk mengubah data dalam database. Jika Anda menerapkan aturan bisnis Anda di tingkat aplikasi dan saya menjalankan UPDATEpernyataan langsung terhadap basis data, bagaimana aplikasi Anda mencegah perubahan yang tidak valid? Masalah lain dengan aturan bisnis dalam aplikasi adalah bahwa kompilasi / penempatan ulang bisa sulit, terutama untuk aplikasi terdistribusi di mana dimungkinkan bahwa tidak semua orang akan mendapatkan pembaruan pada saat yang sama. Dan akhirnya, mengubah aturan bisnis dalam aplikasi sama sekali tidak tentang data yang sudah ada yang melanggar aturan baru - jika Anda menambahkan kendala baru ke data, Anda perlu memperbaiki data.
  • Anda mungkin dapat membenarkan beberapa, pemeriksaan yang berlebihan di berbagai tingkatan. Ini semua tergantung pada fleksibilitas metodologi penyebaran, seberapa besar kemungkinan perubahan itu, dan seberapa sulit untuk menyinkronkan perubahan aturan bisnis dalam database dan lapisan lainnya. Argumen yang menarik untuk mengulangi pemeriksaan pada lapisan aplikasi adalah bahwa Anda berpotensi mencegah round-trip ke database hanya untuk gagal kendala di sana (tergantung pada sifat kendala dan apakah itu bergantung pada data yang ada). Tetapi jika saya harus memilih satu atau yang lain saya akan memasukkannya ke dalam database karena alasan di atas.

Dalam kasus yang Anda sebutkan secara eksplisit, di mana Anda tiba-tiba mengizinkan sesuatu yang sebelumnya tidak diizinkan, ini sebenarnya bukan masalah - Anda menghilangkan kendala apa pun yang memaksanya, terlepas dari di mana itu ada. Dalam kasus sebaliknya, di mana tiba-tiba guru tidak lagi diizinkan menjadi siswa, Anda berpotensi memiliki banyak data untuk dibersihkan, lagi terlepas dari mana kendala yang ada sebelumnya.


9
  1. Basis data dapat memeriksa kendala secara efektif. Lebih baik daripada kode.

  2. Batasan integritas membantu basis data untuk menemukan rencana pelaksanaan yang efektif

  3. Aplikasi melihat tampilan yang konsisten, oleh karena itu hampir tidak dapat menjamin keunikan. Sementara database juga bisa melihat data yang tidak berkomitmen.


8

Jawaban singkat ... untuk menjaga integritas data (yaitu akurasi dan validitas).

Pengecualian ...
Jika database hanya menyimpan data aplikasi tunggal untuk pengguna tunggal, seperti di sebagian besar database Sqlite, mungkin tidak memerlukan kendala. Bahkan, mereka biasanya tidak, sehingga menjaga waktu akses begitu cepat sehingga tidak terukur.

Untuk yang lainnya ...
Database selalu melayani dua tuan yang saya sebut editor dan pengguna .

Editor sebagian besar memasukkan data ke dalam basis data dan mengambil data satu atau sejumlah kecil catatan sekaligus. Perhatian utama mereka adalah akses yang cepat dan akurat ke semua data terkait dan penyimpanan perubahan yang cepat dan andal.

Sebagian besar pengguna mengambil data dan paling peduli dengan akses cepat ke informasi akurat yang tidak diragukan lagi. Mereka sering membutuhkan berbagai hitungan, agregasi dan daftar yang digunakan untuk menghasilkan tumpukan tebal kertas greenbar kertas ikonik tetapi biasanya berakhir di halaman web hari ini.

Proyek pengembangan basis data hampir selalu dimulai atas perintah Pengguna , tetapi desainnya didorong oleh kebutuhan entri data dan catatan waktu. Editor pada . Dengan demikian, pengembang yang tidak berpengalaman sering merespons kebutuhan mendesak akan kecepatan (terutama pengembangan ) dengan tidak menempatkan kendala dalam database.

Jika satu dan hanya satu aplikasi yang akan digunakan untuk membuat perubahan pada data untuk seluruh umur database, dan aplikasi itu dikembangkan oleh satu atau sejumlah kecil individu yang terkoordinasi dengan baik, maka itu mungkin masuk akal untuk mengandalkan aplikasi untuk memastikan integritas data.

Namun, sebanyak kita berpura-pura dapat memprediksi masa depan, kita tidak bisa.

Upaya menghasilkan basis data apa pun terlalu berharga untuk dibuang begitu saja. Seperti rumah, basis data akan diperluas, diubah, dan direnovasi berkali-kali. Bahkan ketika itu sepenuhnya diganti, semua data akan dimigrasi ke database baru sambil mempertahankan semua aturan dan hubungan bisnis yang lama.

Kendala menerapkan aturan-aturan dan hubungan-hubungan dalam bentuk singkat, deklaratif dalam mesin database itu sendiri di mana mereka mudah diakses. Tanpa mereka, pengembang selanjutnya harus menuangkan melalui program aplikasi untuk merekayasa balik aturan tersebut. Semoga berhasil!

Ini, by-the-way, persis apa yang harus dilakukan oleh programmer mainframe COBOL karena database besar itu sering dibuat sebelum kita memiliki mesin dan kendala relasional. Bahkan jika bermigrasi ke sistem modern seperti DB2 IBM, kendala terkadang tidak sepenuhnya diterapkan karena logika aturan lama, yang mungkin terkandung dalam serangkaian program "kumpulan" COBOL, mungkin berbelit-belit sehingga tidak praktis untuk dikonversi. Alih-alih, alat otomatis dapat digunakan untuk mengubah COBOL lama menjadi versi yang lebih baru dengan antarmuka ke mesin relasional baru dan dengan sedikit penyesuaian, integritas data dipertahankan ... sampai aplikasi baru ditulis yang secara halus merusak segalanya dan perusahaan diseret. ke pengadilan untuk, katakanlah, menyita ribuan pemilik rumah yang seharusnya tidak mereka miliki.


7

Selain komentar lain ...

Jika / ketika Anda memiliki database di mana setiap tabel yang diberikan dapat diperbarui oleh satu atau lebih aplikasi atau jalur kode maka menempatkan batasan yang sesuai dalam database berarti bahwa aplikasi Anda tidak akan menduplikasi kode kendala "sama". Ini menguntungkan Anda dengan menyederhanakan pemeliharaan (mengurangi jumlah tempat untuk berubah jika / ketika ada perubahan model data) dan memastikan bahwa kendala diterapkan secara konsisten terlepas dari aplikasi yang memperbarui data.


5

Secara pribadi, saya pikir lebih mudah untuk membuat dan mengubah kendala daripada membuat pemicu, misalnya, yang akan menjadi salah satu cara untuk menegakkan aturan bisnis Anda menggunakan kode sumber.

Pemicu juga cenderung lebih mudah dibawa-bawa, karena biasanya ditulis dalam bahasa khusus vendor, seperti PL / SQL.

Tetapi jika kendala tidak memenuhi kebutuhan Anda, Anda selalu dapat menggunakan pemicu untuk menegakkan aturan bisnis Anda.


5
Pemicu juga tidak menjamin integritas, karena masalah konsistensi baca.
David Aldridge

3

Mereka harus selalu diterapkan dalam database terlebih dahulu karena,

  1. Basis data memastikan integritas di antara klien yang berbeda. Anda dapat memiliki klien yang berbeda pada platform yang berbeda mengakses database. Kendala dalam database tidak berisiko masalah integritas ketika Anda membuat klien baru. Ini menghemat Anda dari keharusan untuk T / A kendala Anda dalam hal penulisan ulang atau titik akses tambahan.
  2. Basis data memiliki DSL untuk membangun kendala: SQL DDL!
  3. Basis data menyediakan akses ke kendala-kendala tersebut dalam katalog sistem sehingga ORM yang tepat atau "schema loader" dapat membaca kendala-kendala itu dan membawanya ke dalam aplikasi Anda. Misalnya, jika database Anda menentukan bahwa Anda memiliki varchar(5)tipe, ada kemungkinan besar Anda dapat menemukan skema memuat ORM untuk bahasa spesifik Anda yang memetakan jenis bahasa ke tipe skema, dan merakit sendiri kendala ukuran. DBIx for Perl is one such schema loader; di sini ada satu lagi untuk Kerangka Entitas . Kemampuan loader ini berbeda-beda, tetapi apa pun yang mereka dapat berikan adalah awal yang baik untuk memastikan integritas dalam aplikasi tanpa perjalanan ke database.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.