Saya telah mencoba merancang database untuk pergi dengan konsep proyek dan bertemu dengan apa yang tampaknya seperti masalah yang diperdebatkan. Saya telah membaca beberapa artikel dan beberapa jawaban Stack Overflow yang menyatakan tidak pernah (atau hampir tidak pernah) menyimpan daftar ID atau sejenisnya di suatu bidang - semua data harus bersifat relasional, dll.
Namun, masalah yang saya hadapi adalah saya mencoba membuat pemberi tugas. Orang akan membuat tugas, menetapkannya ke beberapa orang, dan itu akan disimpan ke database.
Tentu saja, jika saya menyimpan tugas-tugas ini secara individual di "Person", saya harus memiliki lusinan kolom "TaskID" dan mengelola mikronya karena mungkin ada 0 hingga 100 tugas yang ditugaskan untuk satu orang, katakanlah.
Kemudian lagi, jika saya menyimpan tugas dalam tabel "Tugas", saya harus memiliki lusinan kolom "PersonID" dan mengelola mikro - masalah yang sama seperti sebelumnya.
Untuk masalah seperti ini, apakah boleh menyimpan daftar ID dalam satu bentuk atau yang lain atau apakah saya hanya tidak memikirkan cara lain ini dapat dicapai tanpa melanggar prinsip?
sumber
VARCHAR ARRAY
) untuk menyimpan daftar tag. Itu mungkin bukan bagaimana mereka akhirnya akan disimpan kemudian, tetapi daftar bisa sangat berguna selama tahap prototyping, ketika Anda tidak memiliki hal lain untuk ditunjukkan dan tidak ingin membangun seluruh skema database sebelum Anda bisa lakukan hal lain.Jawaban:
Kata kunci dan konsep kunci yang perlu Anda selidiki adalah normalisasi basis data .
Apa yang akan Anda lakukan, daripada menambahkan info tentang tugas ke orang atau tabel tugas, adalah Anda menambahkan tabel baru dengan info tugas itu, dengan hubungan yang relevan.
Contoh, Anda memiliki tabel berikut:
Orang:
Tugas:
Anda kemudian akan membuat tabel ketiga dengan Penugasan. Tabel ini akan memodelkan hubungan antara orang-orang dan tugas-tugas:
Kami kemudian akan memiliki batasan Kunci Asing, sehingga database akan menegakkan bahwa PersonId dan TaskIds harus menjadi ID yang valid untuk item asing tersebut. Untuk baris pertama, kita bisa melihat
PersonId is 1
, jadi Alfred , ditugaskanTaskId 3
, Memerah susu sapi .Apa yang seharusnya dapat Anda lihat di sini adalah bahwa Anda dapat memiliki sedikit atau banyak tugas per tugas atau per orang yang Anda inginkan. Dalam contoh ini, Yehezkiel tidak diberi tugas apa pun, dan Alfred ditugaskan 2. Jika Anda memiliki satu tugas dengan 100 orang, melakukan
SELECT PersonId from Assignments WHERE TaskId=<whatever>;
akan menghasilkan 100 baris, dengan berbagai Orang yang berbeda ditugaskan. Anda dapatWHERE
di PersonId untuk menemukan semua tugas yang diberikan kepada orang itu.Jika Anda ingin mengembalikan kueri yang mengganti ID dengan Nama dan tugas, maka Anda bisa mempelajari cara GABUNG tabel.
sumber
Anda mengajukan dua pertanyaan di sini.
Pertama, Anda bertanya apakah boleh menyimpan daftar yang diserialisasi dalam sebuah kolom. Ya, tidak apa-apa. Jika proyek Anda membutuhkannya. Contohnya mungkin bahan produk untuk halaman katalog, di mana Anda tidak ingin mencoba melacak setiap bahan secara individual.
Sayangnya pertanyaan kedua Anda menggambarkan skenario di mana Anda harus memilih pendekatan yang lebih relasional. Anda akan membutuhkan 3 tabel. Satu untuk orang-orang, satu untuk tugas-tugas, dan satu yang mempertahankan daftar tugas yang ditugaskan kepada orang-orang yang mana. Yang terakhir akan menjadi vertikal, satu baris per orang / kombinasi tugas, dengan kolom untuk kunci utama, id tugas, dan id orang.
sumber
Apa yang Anda gambarkan dikenal sebagai hubungan "banyak ke banyak", dalam kasus Anda antara
Person
danTask
. Ini biasanya diimplementasikan menggunakan tabel ketiga, kadang-kadang disebut tabel "tautan" atau "referensi silang". Sebagai contoh:sumber
task_id
terlebih dahulu, jika Anda mungkin melakukan kueri yang difilter berdasarkan tugas.Satu-satunya waktu Anda mungkin menyimpan lebih dari satu item data dalam satu bidang adalah ketika bidang itu hanya pernah digunakan sebagai entitas tunggal dan tidak pernah dianggap sebagai terdiri dari elemen-elemen yang lebih kecil. Contohnya mungkin gambar, disimpan dalam bidang BLOB. Itu terdiri dari banyak dan banyak elemen yang lebih kecil (byte) tetapi ini yang tidak berarti apa - apa untuk basis data dan hanya dapat digunakan bersama-sama (dan terlihat cantik bagi Pengguna Akhir).
Karena "daftar", menurut definisi, terdiri dari unsur-unsur yang lebih kecil (item), ini tidak terjadi di sini dan Anda harus menormalkan data.
Tidak. Anda akan memiliki beberapa baris dalam Tabel Persimpangan (alias Entitas Lemah) antara Orang dan Tugas. Database sangat bagus dalam bekerja dengan banyak baris; mereka sebenarnya sangat sampah bekerja dengan banyak kolom [berulang].
Contoh jelas bagus diberikan oleh whatsisname.
sumber
Mungkin sah di bidang pra-perhitungan tertentu.
Jika beberapa pertanyaan Anda mahal dan Anda memutuskan untuk pergi dengan bidang yang dihitung sebelumnya diperbarui secara otomatis menggunakan pemicu basis data, maka mungkin sah untuk menyimpan daftar di dalam kolom.
Misalnya, di UI Anda ingin menampilkan daftar ini menggunakan tampilan kisi, tempat setiap baris dapat membuka detail lengkap (dengan daftar lengkap) setelah mengklik dua kali:
Anda menjaga kolom kedua diperbarui oleh pemicu ketika klien mengunjungi artikel baru atau oleh tugas yang dijadwalkan.
Anda dapat membuat bidang seperti itu tersedia bahkan untuk pencarian (seperti teks biasa).
Untuk kasus seperti itu, menyimpan daftar adalah sah. Anda hanya perlu mempertimbangkan kemungkinan panjang bidang maksimum.
Juga, jika Anda menggunakan Microsoft Access, bidang multinilai yang ditawarkan adalah kasus penggunaan khusus lainnya. Mereka menangani daftar Anda di bidang secara otomatis.
Tetapi Anda selalu dapat kembali ke bentuk normalisasi standar yang ditunjukkan dalam jawaban lain.
Rangkuman: Bentuk normal dari basis data adalah model teoritis yang diperlukan untuk memahami aspek-aspek penting dari pemodelan data. Tetapi tentu saja normalisasi tidak memperhitungkan kinerja akun atau biaya lain untuk mengambil data. Ini di luar ruang lingkup model teoritis itu. Tetapi menyimpan daftar atau duplikat pra-dihitung (dan dikendalikan) sering diperlukan oleh implementasi praktis.
Sehubungan dengan hal di atas, dalam implementasi praktis, akankah kita lebih memilih kueri mengandalkan bentuk normal sempurna dan menjalankan 20 detik atau kueri yang setara mengandalkan nilai pra-perhitungan yang memakan waktu 0,08 detik? Tidak ada yang suka produk perangkat lunak mereka dituduh lamban.
sumber
Diberikan dua tabel; kami akan memanggil mereka Person dan Task, masing-masing dengan ID itu sendiri (PersonID, TaskID) ... ide dasarnya adalah membuat tabel ketiga untuk mengikat mereka bersama. Kami akan memanggil tabel ini PersonToTask. Minimal itu harus memiliki ID itu sendiri, serta dua lainnya. Jadi ketika datang untuk menugaskan seseorang untuk suatu tugas; Anda tidak perlu lagi MEMPERBARUI tabel Orang, Anda hanya perlu MEMASUKKAN baris baru ke dalam PersonToTaskTable. Dan pemeliharaan menjadi lebih mudah- perlu menghapus tugas hanya menjadi HAPUS berdasarkan TaskID, tidak ada lagi memperbarui tabel Person dan itu terkait parsing
Bagaimana dengan laporan sederhana atau siapa yang ditugaskan untuk suatu tugas?
Anda tentu saja bisa melakukan lebih banyak lagi; TimeReport dapat dilakukan jika Anda menambahkan bidang DateTime untuk TaskAssigned dan TaskCompleted. Semua terserah padamu
sumber
Ini dapat berfungsi jika mengatakan Anda memiliki kunci primer yang dapat dibaca manusia dan menginginkan daftar tugas # tanpa harus berurusan dengan sifat vertikal dari struktur tabel. yaitu lebih mudah untuk membaca tabel pertama.
Pertanyaannya kemudian adalah: apakah daftar tugas harus disimpan atau dihasilkan berdasarkan permintaan, yang sebagian besar akan tergantung pada persyaratan seperti: seberapa sering daftar tersebut diperlukan, seberapa akurat berapa banyak baris data yang ada, bagaimana data akan digunakan, dll. .. setelah itu menganalisis pertukaran untuk pengalaman pengguna dan persyaratan pertemuan harus dilakukan.
Misalnya membandingkan waktu yang diperlukan untuk mengingat 2 baris vs menjalankan kueri yang akan menghasilkan 2 baris. Jika perlu waktu lama dan pengguna tidak perlu daftar terbaru (* mengharapkan kurang dari 1 perubahan per hari) maka dapat disimpan.
Atau jika pengguna membutuhkan catatan historis tugas yang diberikan kepada mereka, masuk akal juga jika daftar itu disimpan. Jadi itu sangat tergantung pada apa yang Anda lakukan, tidak pernah mengatakan tidak pernah.
sumber
Anda mengambil apa yang seharusnya menjadi meja lain, mengubahnya 90 derajat dan memilihnya ke meja lain.
Ini seperti memiliki tabel pesanan di mana Anda memiliki itemProdcode1, itemQuantity1, itemPrice1 ... itemProdcode37, itemQuantity37, itemPrice37. Selain canggung untuk menangani secara pemrograman, Anda dapat menjamin bahwa besok seseorang ingin memesan 38 barang.
Saya hanya akan melakukannya dengan cara Anda jika 'daftar' tidak benar-benar daftar, yaitu di mana ia berdiri secara keseluruhan dan setiap item baris individu tidak merujuk pada entitas yang jelas dan independen. Dalam hal itu hanya memasukkan semuanya dalam beberapa tipe data yang cukup besar.
Jadi pesanan adalah daftar, Bill Of Material adalah daftar (atau daftar daftar, yang bahkan akan lebih dari mimpi buruk untuk menerapkan "ke samping"). Tetapi catatan / komentar dan puisi tidak.
sumber
Jika "tidak ok" maka cukup buruk bahwa setiap situs Wordpress pernah memiliki daftar di wp_usermeta dengan wp_capabilities dalam satu baris, daftar dismissed_wp_pointers dalam satu baris, dan yang lainnya ...
Bahkan dalam kasus seperti ini mungkin lebih baik untuk kecepatan karena Anda hampir selalu menginginkan daftarnya . Tetapi Wordpress tidak dikenal sebagai contoh sempurna dari praktik terbaik.
sumber