Desain dan praktik untuk melindungi dari entri nol yang salah dari database

9

Salah satu bagian dari program saya mengambil data dari banyak tabel dan kolom dalam database saya untuk diproses. Beberapa kolom mungkin null, tetapi dalam konteks pemrosesan saat ini yang merupakan kesalahan.

Ini seharusnya "secara teoritis" tidak terjadi, jadi jika itu mengarah ke data yang buruk atau bug dalam kode. Kesalahan memiliki keparahan berbeda, tergantung bidang mana yang null; yaitu untuk beberapa bidang pemrosesan harus dihentikan dan seseorang memberi tahu, untuk yang lain pemrosesan harus diizinkan untuk melanjutkan dan hanya memberi tahu seseorang.

Apakah ada prinsip arsitektur atau desain yang baik untuk menangani nullentri yang jarang tetapi mungkin ?

Solusi harus dimungkinkan untuk diterapkan dengan Java tetapi saya tidak menggunakan tag karena saya pikir masalahnya agak agnostik bahasa.


Beberapa pemikiran yang saya miliki:

Menggunakan NOT NULL

Paling mudah adalah dengan menggunakan batasan NOT NULL dalam database.

Tetapi bagaimana jika memasukkan data asli lebih penting daripada langkah pemrosesan nanti? Jadi kalau-kalau insert akan dimasukkan nullke dalam tabel (baik karena bug atau mungkin bahkan beberapa alasan yang valid), saya tidak ingin insert gagal. Katakanlah banyak bagian program bergantung pada data yang dimasukkan, tetapi tidak pada kolom khusus ini. Jadi saya lebih suka mengambil risiko kesalahan pada langkah pemrosesan saat ini daripada langkah memasukkan. Itu sebabnya saya tidak ingin menggunakan batasan NOT NULL.

Secara naif tergantung pada NullPointerException

Saya hanya bisa menggunakan data seolah-olah saya berharap untuk selalu ada di sana (dan itu harus benar-benar terjadi), dan menangkap NPE yang dihasilkan pada tingkat yang sesuai (misalnya sehingga pemrosesan entri saat ini berhenti tetapi tidak seluruh proses pemrosesan berlangsung ). Ini adalah prinsip "gagal puasa" dan saya sering lebih suka. Jika itu bug, setidaknya saya mendapatkan NPE yang dicatat.

Tetapi kemudian saya kehilangan kemampuan untuk membedakan berbagai jenis data yang hilang. Misalnya untuk beberapa data yang hilang saya bisa meninggalkannya, tetapi untuk yang lain pemrosesan harus dihentikan dan admin diberitahu.

Memeriksa nullsebelum setiap akses dan melemparkan pengecualian khusus

Pengecualian khusus akan membuat saya memutuskan tindakan yang benar berdasarkan pengecualian, jadi ini sepertinya cara yang harus dilakukan.

Tetapi bagaimana jika saya lupa memeriksanya di suatu tempat? Juga saya kemudian mengacaukan kode saya dengan cek nol yang tidak pernah atau jarang diharapkan (dan tentunya bukan bagian dari aliran logika bisnis).

Jika saya memilih jalan seperti ini, pola apa yang paling cocok untuk pendekatan ini?


Setiap pemikiran dan komentar tentang pendekatan saya disambut. Juga solusi apa pun yang lebih baik (pola, prinsip, arsitektur kode atau model saya yang lebih baik, dll.).

Edit:

Ada kendala lain, dalam hal itu saya menggunakan ORM untuk melakukan pemetaan dari DB ke objek kegigihan, sehingga melakukan pemeriksaan nol pada tingkat itu tidak akan berfungsi (karena objek yang sama digunakan di bagian di mana nol tidak membahayakan) . Saya menambahkan ini karena jawaban yang diberikan sejauh ini sama-sama menyebutkan opsi ini.

jhyot
sumber
5
"Beberapa kolom mungkin nol, tetapi dalam konteks pemrosesan saat ini yang merupakan kesalahan... Jika insert akan memasukkan null ke dalam tabel, saya tidak ingin insert gagal." Kedua persyaratan tersebut adalah kontradiktif. Tidak mungkin menemukan solusi sampai Anda rileks dengan salah satu dari kedua kondisi tersebut.
Kilian Foth
@KilianFoth Nah, relaksasi saya adalah bahwa kesalahan dalam konteks "pemrosesan saat ini" kurang parah daripada saat memasukkan. Jadi saya menerima kesalahan pemrosesan yang jarang terjadi, tetapi saya ingin memiliki desain yang bagus dan kuat untuk mengatasinya. Itu sebabnya BUKAN NULL, yang seharusnya menjadi solusi yang baik, tidak dimungkinkan di sini.
jhyot
1
Jika Anda menerima begitu banyak kesalahan, pencetus kesalahan itu tidak akan pernah memperbaikinya. Jika pernyataan sisipan berantakan mereka berhasil, insentif apa yang pernah mereka miliki untuk memperbaikinya? Apakah Anda menganggap kuat tidak gagal tetapi menerima data buruk?
Tulains Córdova
@ user61852 Saya secara eksplisit tidak menerima kesalahan tetapi ingin menanganinya dengan anggun. Menelan null pointer tidak mungkin dilakukan. Juga, bagaimana jika bagian saya benar-benar obyektif (seperti yang didefinisikan oleh bisnis) kurang penting daripada banyak bagian lain yang membutuhkan sisipan untuk berhasil tetapi tidak mengharuskan bidang khusus ini diatur? Sisipan tidak berasal dari entri pengguna di mana saya bisa memaksa mereka untuk menambahkan nilai, tetapi dari kode lain di mana kelalaian kemungkinan besar adalah bug (tetapi tidak cukup penting untuk memecahkan insert).
jhyot
1
Menandai mereka sebagai NOT NULL dalam database akan menjadi solusi terbaik, jika sebuah kolom dapat dibatalkan, maka kodenya perlu menangani case ketika itu, bahkan jika itu tidak diharapkan karena mekanisme penyimpanan memungkinkannya.
Jon Raynor

Jawaban:

9

Saya akan meletakkan cek nol dalam kode pemetaan Anda, tempat Anda membangun objek dari hasil yang ditetapkan. Itu menempatkan pemeriksaan di satu tempat, dan tidak akan memungkinkan kode Anda untuk setengah jalan memproses catatan sebelum memukul kesalahan. Bergantung pada bagaimana alur aplikasi Anda bekerja, Anda mungkin ingin melakukan pemetaan semua hasil sebagai langkah pra-pemrosesan alih-alih memetakan dan memproses setiap catatan satu per satu.

Jika Anda menggunakan ORM maka Anda harus melakukan semua pemeriksaan nol sebelum memproses setiap catatan. Saya akan merekomendasikan recordIsValid(recordData)metode -type, dengan begitu Anda dapat (lagi) menyimpan semua logika pemeriksaan-nol dan validasi lainnya di satu tempat. Saya pasti tidak akan mencampurkan cek nol dengan sisa logika pemrosesan Anda.

TMN
sumber
Terima kasih, itu wawasan yang bagus! Saya memang menggunakan ORM, jadi pemeriksaan pada level itu tidak akan berfungsi. Tetapi saya juga memiliki beberapa pemetaan untuk objek domain nyata dari objek kegigihan. Saya akan memeriksa apakah melakukan pemetaan dan memvalidasi dalam langkah preprocessing mungkin dilakukan.
jhyot
Dan jika Anda mengganti ORM Anda, lalu bagaimana? Lebih baik mempertahankan ini pada sumbernya (lihat jawaban Doc Brown).
Robbie Dee
@RobbieDee: Tidak masalah. Jika Anda harus menulis ulang kode pemetaan maka cek nol ada di sana dan Anda memodifikasinya sebagai bagian dari penulisan ulang, atau Anda punya metode terpisah yang melakukan pemeriksaan nol pada objek bisnis Anda, jadi tidak perlu menulis ulang. Dan seperti yang disiratkan Doc Brown, kadang-kadang penting untuk memperhatikan bahwa data hilang alih-alih menutupi fakta itu dengan nilai default.
TMN
Itu harus terjadi lebih lanjut dalam aliran ETL. Anda masih berisiko melakukan duplikasi dengan cara ini.
Robbie Dee
6

Kedengarannya seperti memasukkan nol adalah kesalahan tetapi Anda takut untuk menegakkan kesalahan ini pada penyisipan karena Anda tidak ingin kehilangan data. Namun, jika suatu bidang tidak boleh nol tetapi, Anda kehilangan data . Oleh karena itu solusi terbaik adalah memastikan bahwa bidang nol tidak salah disimpan.

Untuk tujuan ini, tegakkan bahwa data tersebut benar dalam repositori permanen yang otoritatif untuk data tersebut, yaitu database. Lakukan dengan menambahkan kendala bukan nol. Maka kode Anda mungkin gagal tetapi kegagalan ini segera memberi tahu Anda tentang bug, memungkinkan Anda untuk memperbaiki masalah yang sudah menyebabkan Anda kehilangan data. Sekarang Anda dapat dengan mudah mengidentifikasi bug, menguji kode Anda dan mengujinya dua kali. Anda dapat memperbaiki bug yang menyebabkan hilangnya data dan dalam prosesnya, sangat menyederhanakan pemrosesan data di bagian hilir karena Anda tidak perlu khawatir tentang nol.

Pasang kembali Monica
sumber
2
Terima kasih atas jawabannya. Saya setuju bahwa solusi Anda adalah cara yang tepat untuk melakukannya, dan Anda mengucapkannya dengan singkat. Kendala di luar pengaruh saya mungkin membuatnya sulit atau tidak mungkin (misalnya sumber daya yang tidak tersedia untuk pengujian atau untuk membuat kode yang ada secara otomatis dapat diuji), tetapi saya harus memeriksa ulang apakah solusi ini dapat bekerja sebelum mencoba cara lain. Dalam pemikiran awal saya, saya mungkin berasumsi terlalu cepat sehingga saya tidak dapat memperbaiki masalah di sumbernya.
jhyot
@ jhyot Oke. Ini membuat frustrasi ketika Anda tidak dapat melakukan hal-hal dengan cara yang bersih. Semoga jawaban saya setidaknya bermanfaat bagi orang lain yang memiliki masalah serupa tetapi yang mampu menyerang akar penyebabnya daripada membersihkan kekacauan setelah fakta.
Pasang kembali Monica
5

Sehubungan dengan kalimat ini dalam pertanyaan:

Ini seharusnya "secara teoritis" tidak terjadi, jadi jika itu mengarah ke data yang buruk atau bug dalam kode.

Saya selalu menghargai kutipan ini (milik artikel ini ):

Saya merasa lucu ketika programmer pemula percaya pekerjaan utama mereka adalah mencegah program dari crash. Saya membayangkan argumen kegagalan yang spektakuler ini tidak akan begitu menarik bagi seorang programmer. Pemrogram yang lebih berpengalaman menyadari bahwa kode yang benar itu hebat, kode yang crash dapat menggunakan peningkatan, tetapi kode yang salah yang tidak crash adalah mimpi buruk yang mengerikan.

Pada dasarnya: sepertinya Anda mendukung Hukum Postel , "jadilah konservatif dalam apa yang Anda kirim, jadilah liberal dalam apa yang Anda terima". Meskipun hebat dalam teori, dalam praktiknya "prinsip kekokohan" ini mengarah pada perangkat lunak yang tidak kuat , setidaknya dalam jangka panjang - dan kadang-kadang juga dalam jangka pendek. (Bandingkan kertas Eric Allman, The Robustness Principle Reconsidered , yang merupakan perawatan yang sangat teliti terhadap subjek, walaupun sebagian besar berfokus pada kasus penggunaan protokol jaringan.)

Jika Anda memiliki program yang salah memasukkan data ke dalam basis data Anda, program-program itu rusak dan perlu diperbaiki . Mengatasi masalah hanya akan membuatnya semakin buruk; ini adalah rekayasa perangkat lunak yang setara dengan memungkinkan seorang pecandu untuk melanjutkan kecanduan mereka.

Namun, secara pragmatis, kadang-kadang Anda memang perlu mengaktifkan perilaku "rusak" untuk melanjutkan, setidaknya untuk sementara, terutama sebagai bagian dari transisi yang mulus dari kondisi longgar, rusak ke kondisi ketat dan benar. Dalam hal ini, Anda ingin menemukan cara untuk memungkinkan penyisipan yang salah berhasil, tetapi masih memungkinkan penyimpanan data "kanonik" selalu dalam keadaan yang benar . Ada berbagai cara untuk melakukan ini:

  • Gunakan pemicu basis data untuk mengubah sisipan yang salah bentuk menjadi sisipan yang benar, misalnya dengan mengganti nilai yang hilang / nol dengan default
  • Mintalah program yang salah memasukkan ke dalam tabel database terpisah yang diizinkan menjadi "salah", dan memiliki proses terjadwal terpisah atau mekanisme lain yang memindahkan data terkoreksi dari tabel itu ke dalam penyimpanan data kanonik
  • Gunakan pemfilteran sisi permintaan (mis. Tampilan) untuk memastikan bahwa data yang diambil dari basis data selalu dalam kondisi yang benar, bahkan jika data saat ini tidak

Salah satu cara untuk menghindari semua masalah ini adalah dengan menyisipkan lapisan API yang Anda kontrol antara program yang menulis dan database aktual.

Kedengarannya seperti bagian dari masalah Anda adalah bahwa Anda bahkan tidak tahu semua tempat yang menghasilkan tulisan salah - atau ada terlalu banyak dari mereka untuk Anda perbarui. Itu adalah kondisi yang menakutkan, tetapi seharusnya tidak boleh dibiarkan muncul.

Segera setelah Anda mendapatkan lebih dari beberapa sistem yang diizinkan untuk mengubah data di toko data produksi kanonik Anda akan berada dalam masalah: tidak ada cara untuk secara terpusat mengelola apa pun tentang database itu. Lebih baik membiarkan proses sesedikit mungkin untuk mengeluarkan menulis, dan menggunakannya sebagai "penjaga gerbang" yang dapat memproses data sebelum memasukkan sebagaimana diperlukan. Mekanisme yang tepat untuk ini sangat tergantung pada arsitektur spesifik Anda.

Daniel Pryden
sumber
"Jika Anda memiliki program yang salah memasukkan data ke dalam basis data Anda, program itu rusak dan perlu diperbaiki." itu bagus dalam teori juga, tetapi kenyataannya adalah mereka masih akan menambahkan catatan sementara beberapa komite terus memperdebatkan apakah akan menggunakan "NA" atau "Tidak ada".
JeffO
@ JeffO: Tidak ada panitia yang harus berdebat apakah akan menyimpan "NA", "None", NULL, atau sesuatu yang lain dalam database. Stakeholder non-teknis memiliki kepentingan dalam data apa yang keluar dari database dan bagaimana data itu digunakan, tetapi tidak dalam representasi internal.
Daniel Pryden
@DanielPryden: Di pekerjaan terakhir saya, kami memiliki Architecture Review Board (dengan sub-komite DBA) yang akan meninjau perubahan teknis lintas domain. Sangat teknis, tetapi mereka hanya bertemu setiap dua minggu dan jika Anda tidak memberikan detail yang cukup untuk mereka, mereka akan menunda keputusan sampai Anda melakukannya ... pada pertemuan berikutnya. Sebagian besar perubahan sistem non-sepele yang tidak terdiri dari penambahan fungsionalitas melalui kode baru secara rutin akan memakan waktu sekitar sebulan.
TMN
@DanielPryden - Saya telah duduk dalam rapat dengan manajemen tingkat tinggi berdebat tentang label kotak teks. Anda bisa berpendapat bahwa ini tidak ada hubungannya dengan apa yang akan Anda beri nama dalam aplikasi atau database, tetapi itu benar.
JeffO
Menanggapi komentar tentang mendapatkan persetujuan tambahan untuk perubahan semacam ini: poin saya tentang nilai-nilai yang "salah" mengandaikan bahwa nilai-nilai yang diperbolehkan sudah didokumentasikan di suatu tempat - itulah mengapa OP mengatakan bahwa nilai-nilai ini harus dianggap sebagai bug. Jika skema database ditentukan untuk memungkinkan suatu nilai, maka nilai itu bukan bug. Intinya adalah bahwa jika Anda memiliki data yang tidak cocok dengan skema Anda, maka ada sesuatu yang rusak: prioritas Anda harus membuat data dan skema cocok. Bergantung pada tim, itu mungkin melibatkan perubahan data, skema, atau keduanya.
Daniel Pryden
2

" Apakah ada prinsip arsitektur atau desain yang bagus untuk menangani entri nol yang jarang tetapi mungkin? "

Jawaban sederhana - ya.

ETL

Lakukan beberapa pemrosesan di muka untuk memastikan data berkualitas cukup untuk masuk ke database. Apa pun yang ada di file drop harus dilaporkan kembali dan data bersih apa pun dapat dimuat ke dalam basis data.

Sebagai seseorang yang telah menjadi pemburu (dev) dan penjaga permainan (DBA), saya tahu dari pengalaman pahit bahwa pihak ke-3 tidak akan menyelesaikan masalah data mereka kecuali jika dipaksa. Terus-menerus membungkuk ke belakang dan memijat data melalui set preseden yang berbahaya.

Mart / Repositori

Dalam skenario ini, data mentah didorong ke dalam repositori DB dan kemudian versi yang disanitasi didorong ke DB mart yang kemudian diakses oleh aplikasi.

Nilai dasar

Jika Anda dapat menerapkan nilai default yang masuk akal ke kolom maka Anda harus melakukannya meskipun ini dapat melibatkan beberapa pekerjaan jika ini adalah database yang ada.

Gagal lebih awal

Sangat menggoda untuk hanya mengatasi masalah data di gateway ke aplikasi, laporan suite, antarmuka dll. Saya sangat menyarankan Anda untuk tidak hanya mengandalkan ini. Jika Anda menghubungkan beberapa widget lain ke DB, Anda berpotensi menghadapi masalah yang sama lagi. Mengatasi masalah kualitas data.

Robbie Dee
sumber
+1 Inilah yang akan saya lakukan, mengumpulkan semua data dan membuat set data yang valid untuk diproses oleh aplikasi Anda.
Kwebble
1

Kapan pun kasus penggunaan Anda memungkinkan untuk mengganti NULL dengan aman dengan nilai default yang baik, Anda dapat melakukan konversi dalam SELECTpernyataan Sql menggunakan ISNULLatau COALESCE. Jadi, bukannya

 SELECT MyColumn FROM MyTable

orang bisa menulis

 SELECT ISNULL(MyColumn,DefaultValueForMyColumn) FROM MyTable

Tentu saja, itu hanya akan berfungsi ketika ORM memungkinkan untuk memanipulasi pernyataan pilih secara langsung, atau menyediakan templat yang dapat diubah untuk generasi. Orang harus memastikan bahwa tidak ada kesalahan "nyata" yang ditutup-tutupi dengan cara ini, jadi terapkan hanya jika mengganti dengan nilai default persis seperti yang Anda inginkan jika NULL.

Jika Anda dapat mengubah database dan skema, dan sistem db Anda mendukung ini, Anda dapat mempertimbangkan untuk menambahkan klausa nilai default ke kolom tertentu, seperti yang disarankan oleh @RobbieDee. Namun, ini juga akan perlu untuk memodifikasi data yang ada di database untuk menghapus nilai NULL yang dimasukkan sebelumnya, dan itu akan menghapus kemampuan untuk membedakan antara data impor yang benar dan tidak lengkap sesudahnya.

Dari pengalaman saya sendiri, saya tahu bahwa menggunakan ISNULL dapat bekerja dengan sangat baik - di masa lalu saya harus memelihara aplikasi warisan di mana para pengembang asli lupa menambahkan batasan NOT NULL ke banyak kolom, dan kami tidak dapat dengan mudah menambahkan kendala itu nanti untuk beberapa alasan. Tetapi dalam 99% dari semua kasus, 0 sebagai default untuk kolom angka dan string kosong sebagai default untuk kolom teks sepenuhnya dapat diterima.

Doc Brown
sumber
Sementara ini berhasil, Anda akhirnya harus menduplikasi kode pertahanan untuk setiap SELECT. Pendekatan yang jauh lebih baik adalah mendefinisikan nilai default untuk sebuah kolom ketika sebuah NULL dimasukkan walaupun ini mungkin tidak mungkin / diinginkan karena berbagai alasan.
Robbie Dee
@RobbieDee: terima kasih atas komentar itu, saya mengubah jawaban saya sesuai. Namun, jika ini "jauh lebih baik" masih bisa diperdebatkan. Ketika kode CRUD berada di satu tempat, duplikat kode defensif mungkin tidak terlalu menjadi masalah. Dan jika tidak, sudah ada beberapa duplikasi kode sebelumnya.
Doc Brown
Operasi CRUD sederhana tentu saja ideal. Tetapi di dunia nyata, sistem seringkali memiliki tampilan UI yang kompleks, penyihir data yang dihasilkan pengguna, laporan, dll. Tetapi seperti yang telah Anda tunjukkan, nilai default harus ada di sana dari bawah ke atas atau setidaknya memerlukan beberapa upaya konversi awal. Apa yang telah Anda jelaskan bisa lebih baik dalam pengembangan brownfield.
Robbie Dee
Jawaban Terbaik. Aplikasi baru biasanya menambahkan beberapa data baru yang mungkin berada di luar kendali Anda. NULL yang salah biasanya berasal dari pengimporan data lama ke dalam basis data yang didesain ulang. Batasan dimatikan untuk ini agar bisa menyelesaikan dalam beberapa jam, bukan beberapa hari. "Kegagalan besar" sering terjadi ketika DBA mencoba mengaktifkan kembali kendala. Karena tidak pernah direncanakan, manajemen sering menolak keras pada minggu-minggu kerja yang sering diperlukan untuk memperbaiki data yang buruk, sehingga tetap ada. Semua aplikasi harus dengan anggun menangani NULL dengan memasukkan default dan melaporkan atau meminta data yang hilang.
DocSalvager
1

OP berasumsi bahwa pasangan akan mengatur bisnis dengan rincian teknis basis data.

Ini seharusnya "secara teoritis" tidak terjadi, jadi jika itu mengarah ke data yang buruk atau bug dalam kode. Kesalahan memiliki keparahan berbeda, tergantung bidang mana yang nol; yaitu untuk beberapa bidang pemrosesan harus dihentikan dan seseorang memberi tahu, untuk yang lain pemrosesan harus diizinkan untuk melanjutkan dan hanya memberi tahu seseorang.

Ini semua aturan bisnis. Aturan bisnis tidak peduli dengan nol per-se. Yang diketahui database itu bisa saja nol, 9999, "BOO!" ... Ini hanyalah nilai lain. Bahwa, dalam RDBMS, null memiliki sifat yang menarik dan penggunaan unik diperdebatkan.

Satu-satunya hal yang penting adalah apa arti "null-ness" untuk objek bisnis yang diberikan ...

Apakah ada prinsip arsitektur atau desain yang baik untuk menangani entri nol yang jarang tetapi mungkin?

Iya.

  • Masukkan aturan bisnis di kelas.
  • Transliterasi harus dalam lapisan kode yang sesuai decoupling kelas bisnis dan penyimpanan data. Jika Anda tidak bisa memasukkannya ke dalam kode ORM setidaknya jangan memasukkannya ke dalam basis data.
  • Buat database sebodoh mungkin, tidak ada aturan bisnis di sini. Bahkan hal-hal yang tidak berbahaya seperti default nilai akan menggigit Anda . Pernah ke sana.
  • Validasi data yang masuk dan datang dari database. Dan tentu saja ini dilakukan dalam konteks objek bisnis.

Melempar pengecualian pada pengambilan data tidak masuk akal.

Pertanyaannya adalah "haruskah saya menyimpan data 'buruk'"? Tergantung:

  • Data buruk dapat digunakan - Jangan pernah menyimpan objek yang tidak valid, atau komposit objek. Data / hubungan bisnis yang kompleks di semua tempat. Pengguna dapat melakukan fungsi apa pun pada waktu tertentu, mungkin menggunakan entitas bisnis itu dalam sejumlah konteks. Efek (jika ada) data buruk, pada saat disimpan, tidak diketahui karena sangat bergantung pada penggunaan di masa mendatang. Tidak ada proses tunggal / tunggal dari data tersebut.
  • Tidak dapat maju jika ada data buruk - Mengizinkan penyimpanan data buruk. Namun langkah selanjutnya dalam suatu proses tidak dapat dilanjutkan sampai semuanya valid. Misalnya melakukan pajak penghasilan seseorang. Ketika diambil dari database, perangkat lunak menunjukkan kesalahan dan tidak dapat dikirimkan ke IRS tanpa memeriksa validitas.
radarbob
sumber
0

Ada banyak cara untuk menangani null, jadi kita akan beralih dari lapisan basis data ke lapisan aplikasi.


Lapisan basis data

Anda dapat melarang nulls ; meskipun di sini tidak praktis.

Anda dapat mengonfigurasi default berdasarkan per kolom:

  • itu mensyaratkan bahwa kolom absen dari insert, jadi tidak mencakup penyisipan null eksplisit
  • itu mencegah deteksi dari baris di mana insertkolom ini keliru

Anda dapat mengonfigurasi pemicu , sehingga saat penyisipan nilai yang hilang dihitung secara otomatis:

  • diperlukan informasi yang diperlukan untuk melakukan perhitungan ini
  • itu akan memperlambat insert

Lapisan permintaan

Anda dapat melewati baris di mana ketidaknyamanan nullhadir:

  • itu menyederhanakan logika utama
  • itu mencegah mendeteksi "baris buruk", jadi proses lain akan diperlukan untuk memeriksanya
  • itu mengharuskan setiap permintaan diinstrumentasi

Anda dapat memberikan nilai default dalam kueri:

  • itu menyederhanakan logika utama
  • itu mencegah mendeteksi "baris buruk", jadi proses lain akan diperlukan untuk memeriksanya
  • itu mengharuskan setiap permintaan diinstrumentasi

Catatan: menginstruksikan setiap kueri belum tentu menjadi masalah jika Anda memiliki cara otomatis untuk menghasilkannya.


Lapisan aplikasi

Anda dapat memeriksa terlebih dahulu tabel terlarang null:

  • itu menyederhanakan logika utama
  • itu meningkatkan waktu ke kegagalan
  • itu membutuhkan menjaga pra-cek dan logika aplikasi konsisten

Anda dapat mengganggu pemrosesan saat menemukan yang terlarang null:

  • itu menghindari menduplikasi pengetahuan kolom mana yang bisa nulldan mana yang tidak
  • itu masih relatif sederhana (hanya cek + pengembalian / lemparan)
  • itu mensyaratkan bahwa proses Anda dapat dilanjutkan kembali (jika Anda sudah mengirim e-mail, tidak ingin mengirimnya dua kali, atau seratus kali!)

Anda dapat melewati baris ketika menemukan yang terlarang null:

  • itu menghindari menduplikasi pengetahuan kolom mana yang bisa nulldan mana yang tidak
  • itu masih relatif sederhana (hanya cek + pengembalian / lemparan)
  • tidak mengharuskan proses Anda dilanjutkan

Anda dapat mengirim pemberitahuan ketika menemukan yang terlarang null, baik satu per satu atau secara batch, yang gratis untuk cara-cara lain yang disajikan di atas. Namun yang paling penting adalah "lalu apa?", Terutama, jika Anda berharap baris tersebut akan ditambal dan perlu diproses ulang, Anda mungkin perlu memastikan bahwa Anda memiliki beberapa cara untuk membedakan baris yang sudah diproses dari baris yang membutuhkan. sedang diproses ulang.


Mengingat situasi Anda, saya akan menangani situasi di aplikasi dan menggabungkan:

  • mengganggu dan memberi tahu
  • lewati dan beri tahu

Saya akan cenderung hanya melewatkan jika mungkin entah bagaimana menjamin sedikit kemajuan, terutama jika prosesnya bisa memakan waktu.

Jika Anda tidak perlu memproses ulang baris yang dilewati, maka cukup login saja sudah mencukupi dan email yang dikirim pada akhir proses dengan jumlah baris yang dilewati akan menjadi pemberitahuan yang tepat.

Kalau tidak, saya akan menggunakan tabel sisi untuk baris yang harus diperbaiki (dan diproses ulang). Tabel samping ini dapat berupa referensi sederhana (tanpa kunci asing) atau salinan lengkap: yang terakhir, bahkan jika lebih mahal, diperlukan jika Anda tidak punya waktu untuk mengatasi nullsebelum harus membersihkan data utama.

Matthieu M.
sumber
-1

Nulls dapat ditangani dalam terjemahan atau pemetaan tipe basis data ke tipe bahasa. Misalnya dalam C #, berikut adalah metode umum yang menangani null untuk Anda untuk semua jenis:

public static T Convert<T>(object obj)
        {
            if (obj == DBNull.Value)
            {
                return default(T);
            }

            return (T) obj;
        }

public static T Convert<T>(object obj, T defaultValue)
        {
            if (obj == DBNull.Value)
            {
                T t = defaultValue;
                return t;
            }

            return (T) obj;
        }

Atau, jika Anda ingin melakukan tindakan ...

 public static T Convert<T>(object obj, T defaultValue)
        {
            if (obj == DBNull.Value)
            {
                //Send an Alert, we might want pass in the name
                //of column or other details as well
                SendNullAlert();
                //Set it to default so we can keep processing
                T t = defaultValue;
                return t;
            }

            return (T) obj;
        }

Dan kemudian dalam pemetaan, dalam hal ini ke objek tipe "Sampel", kami akan menangani null untuk salah satu kolom:

public class SampleMapper : MapperBase<Sample>
    {
        private const string Id = "Id";
        private const string Name = "Name";
        private const string DataValue = "DataValue";
        private const string Created = "Created";

        protected override Sample Map(IDataRecord record)
        {
            return new Sample(
                Utility.Convert<Int64>(record[Id]),
                Utility.Convert<String>(record[Name]),
                Utility.Convert<Int32>(record[DataValue]),
                Utility.Convert<DateTime>(record[Created])
                );
        }
    }

Akhirnya, semua kelas pemetaan dapat secara otomatis dihasilkan berdasarkan query SQL atau tabel yang terlibat dengan melihat tipe data SQL dan menerjemahkannya ke tipe data spesifik bahasa. Inilah yang dilakukan banyak ORM untuk Anda secara otomatis. Perhatikan bahwa beberapa tipe basis data mungkin tidak memiliki pemetaan langsung (Geo-spatial colunms, dll.) Dan mungkin perlu penanganan khusus.

Jon Raynor
sumber
Jika seseorang ingin memposting versi Java yang setara yang akan menjadi luar biasa ...
Jon Raynor
Saya pikir kode contoh juga bisa dimengerti oleh pengembang Java. Dalam situasi saya, saya sudah memiliki ORM di tempat, jadi tidak perlu menerapkannya. Tetapi jawaban Anda hanya membahas nilai default untuk nol, sedangkan dalam kasus saya sebenarnya kasus yang jauh lebih penting adalah mendeteksi nol dan memicu tindakan (mis. Beri tahu admin tentang data yang salah).
jhyot
Ahhh, saya akan memperbarui jawaban saya berdasarkan ini.
Jon Raynor
Kode Anda yang diedit sekarang memiliki satu tindakan default untuk nilai nol apa pun (yaitu sepenuhnya generik). Itu sangat mirip dengan opsi ke-2 saya di pertanyaan asli, yaitu hanya melempar pada nol dan menangkapnya di suatu tempat. Tetapi seperti yang dinyatakan di sana saya perlu membedakan tindakan berdasarkan nilai mana yang hilang.
jhyot