Projekty i praktyki zabezpieczające przed błędnymi zerowymi wpisami z bazy danych

9

Jedna część mojego programu pobiera dane z wielu tabel i kolumn w mojej bazie danych w celu przetworzenia. Niektóre kolumny mogą być null, ale w bieżącym kontekście przetwarzania jest to błąd.

To „teoretycznie” nie powinno się zdarzyć, więc jeśli tak, wskazuje to na złe dane lub błąd w kodzie. Błędy mają różne poziomy ważności, w zależności od tego, które pole jest null; tj. w przypadku niektórych pól przetwarzanie powinno zostać zatrzymane, a ktoś powiadomiony, w innych przypadkach przetwarzanie powinno być kontynuowane i po prostu powiadomić kogoś.

Czy istnieją jakieś dobre zasady architektury lub projektowania, które pozwolą obsłużyć rzadkie, ale możliwe nullwpisy?

Rozwiązania powinny być możliwe do wdrożenia w Javie, ale nie użyłem tagu, ponieważ uważam, że problem jest w pewnym stopniu zależny od języka.


Kilka myśli, które miałem:

Używanie NOT NULL

Najłatwiej byłoby użyć ograniczenia NOT NULL w bazie danych.

Ale co jeśli oryginalne wstawienie danych jest ważniejsze niż ten późniejszy etap przetwarzania? Więc jeśli wstawka wstawi nulldo tabeli (albo z powodu błędów, albo może z jakiegoś ważnego powodu), nie chciałbym, żeby wstawka uległa awarii. Powiedzmy, że wiele innych części programu zależy od wstawionych danych, ale nie od tej konkretnej kolumny. Wolę więc zaryzykować błąd w bieżącym kroku przetwarzania zamiast kroku wstawiania. Dlatego nie chcę używać ograniczenia NOT NULL.

Naiwnie w zależności od NullPointerException

Mógłbym po prostu użyć danych tak, jakbym oczekiwał, że będą one zawsze tam istnieć (i tak powinno być naprawdę), i złapać powstałe NPE na odpowiednim poziomie (np. Tak, aby przetwarzanie bieżącego wpisu zostało zatrzymane, ale nie cały postęp przetwarzania ). Jest to zasada „szybko zawieść” i często ją preferuję. Jeśli to błąd, to dostaję zalogowany NPE.

Ale potem tracę zdolność rozróżniania różnych rodzajów brakujących danych. Np. W przypadku niektórych brakujących danych mógłbym je pominąć, ale w przypadku innych przetwarzanie powinno zostać zatrzymane, a administrator powiadomiony.

Sprawdzanie nullprzed każdym dostępem i zgłaszanie niestandardowych wyjątków

Niestandardowe wyjątki pozwoliłyby mi zdecydować o właściwej akcji na podstawie wyjątku, więc wydaje się, że to właściwy sposób.

Ale co jeśli zapomnę gdzieś to sprawdzić? Następnie zaśmiecam mój kod zerowymi kontrolami, których nigdy lub rzadko się spodziewamy (a więc zdecydowanie nie są częścią logiki biznesowej).

Jeśli wybiorę tę drogę, jakie wzorce najlepiej pasują do tego podejścia?


Wszelkie uwagi i komentarze dotyczące moich podejść są mile widziane. Także lepsze rozwiązania dowolnego rodzaju (wzorce, zasady, lepsza architektura mojego kodu lub modeli itp.).

Edytować:

Jest jeszcze jedno ograniczenie, polegające na tym, że używam ORM do mapowania DB do obiektu trwałości, więc sprawdzanie wartości null na tym poziomie nie działałoby (ponieważ te same obiekty są używane w częściach, w których null nie wyrządza żadnej szkody) . Dodałem to, ponieważ w dotychczasowych odpowiedziach zarówno wspomniano tę opcję.

jhyot
źródło
5
„Niektóre kolumny mogą mieć wartość NULL, ale w obecnym kontekście przetwarzania jest to błąd.… W przypadku wstawienia wstawienia wartości NULL do tabeli nie chciałbym, aby wstawka uległa awarii.” Te dwa wymagania są sprzeczny. Nie można znaleźć rozwiązania, dopóki nie rozluźnisz jednego z dwóch warunków.
Kilian Foth,
@KilianFoth Cóż, moja relaksacja polega na tym, że błąd w kontekście „bieżącego przetwarzania” jest mniej poważny niż podczas wstawiania. Dlatego akceptuję rzadkie błędy przetwarzania, ale chcę mieć solidną, solidną konstrukcję do ich obsługi. Dlatego NOT NULL, które w innym przypadku byłyby dobrym rozwiązaniem, nie jest tutaj możliwe.
jhyot
1
Jeśli zaczniesz akceptować tak wiele błędów, autorzy tych błędów nigdy ich nie poprawią. Jeśli ich niechlujne instrukcje wstawiania się powiodą, jaką motywację mają kiedykolwiek, aby to naprawić? Czy uważasz, że solidne nie zawodzi, ale akceptuje złe dane?
Tulains Córdova
@ user61852 Wyraźnie nie akceptuję błędów, ale chcę je obsługiwać z wdziękiem. Połknięcie zerowych wskaźników nie wchodzi w rachubę. A co jeśli moja część jest naprawdę obiektywnie (zgodnie z definicją firmy) mniej ważna niż wiele innych części, które wymagają wstawienia, ale nie wymagają ustawienia tego konkretnego pola? Wstawki pochodzą nie od wpisu użytkownika, w którym mógłbym zmusić ich do dodania wartości, ale z innego kodu, w którym pominięcie jest najprawdopodobniej błędem (ale nie jest wystarczająco ważne, aby złamać wstawkę).
jhyot
1
Oznaczenie ich jako NIE NULL w bazie danych byłoby najlepszym rozwiązaniem, jeśli kolumna ma wartość zerową, wówczas kod będzie musiał obsłużyć przypadek, gdy jest, nawet jeśli nie jest to oczekiwane, ponieważ mechanizm przechowywania na to pozwala.
Jon Raynor

Odpowiedzi:

9

Umieściłbym kontrole zerowe w kodzie mapowania, w którym budujesz swój obiekt z zestawu wyników. To umieszcza sprawdzanie w jednym miejscu i nie pozwoli kodowi przejść do połowy przetwarzania rekordu przed popełnieniem błędu. W zależności od tego, jak działa przepływ aplikacji, możesz chcieć wykonać mapowanie wszystkich wyników jako etap wstępnego przetwarzania zamiast mapowania i przetwarzania każdego rekordu pojedynczo.

Jeśli używasz ORM, będziesz musiał wykonać wszystkie kontrole zerowe przed przetworzeniem każdego rekordu. Polecam do recordIsValid(recordData)metody -type, w ten sposób można (ponownie) zachować wszystkie wartości null kontroli oraz inne logiki sprawdzania w jednym miejscu. Na pewno nie przeplułbym kontroli zerowej z resztą logiki przetwarzania.

TMN
źródło
Dziękuję, to dobry wgląd! Rzeczywiście używam ORM, więc kontrole na tym poziomie nie będą działać. Ale mam też pewne mapowanie na rzeczywiste obiekty domeny z obiektów trwałości. Sprawdzę, czy możliwe byłoby mapowanie i sprawdzanie poprawności na etapie wstępnego przetwarzania.
jhyot
A jeśli zmienisz ORM, co wtedy? Lepiej bronić tego u źródła (patrz odpowiedź Doc Browna).
Robbie Dee,
@RobbieDee: Nie powinno mieć znaczenia. Jeśli musisz przepisać kod odwzorowania, oznacza to, że istnieją albo kontrole zerowe i modyfikujesz je w ramach przepisywania, albo masz oddzielną metodę, która wykonuje kontrole zerowe na obiektach biznesowych, więc nie ma potrzeby przepisywania. I jak sugeruje Doc Brown, czasem ważne jest, aby zauważyć, że brakuje danych, zamiast nadpisywać ten fakt wartością domyślną.
TMN
Powinno to nastąpić dalej w przepływie ETL. W ten sposób nadal ryzykujesz powieleniem wysiłku.
Robbie Dee
6

Wygląda na to, że wstawienie wartości null jest błędem, ale boisz się wymusić ten błąd podczas wstawiania, ponieważ nie chcesz stracić danych. Jeśli jednak pole nie powinno być puste, ale jest, tracisz dane . Dlatego najlepszym rozwiązaniem jest upewnienie się, że pola zerowe nie zostaną błędnie zapisane.

W tym celu należy wymusić poprawność danych w jednym wiarygodnym, stałym repozytorium tych danych, bazie danych. Zrób to, dodając ograniczenia zerowe. Wówczas kod może się nie powieść, ale awarie te natychmiast powiadamiają o błędach, co pozwala naprawić problemy, które już powodują utratę danych. Teraz, gdy możesz łatwo zidentyfikować błędy, przetestuj kod i przetestuj go dwa razy. Będziesz w stanie poprawić błędy prowadzące do utraty danych, a proces znacznie uprościć przetwarzanie danych, ponieważ nie musisz się martwić o wartości zerowe.

Przywróć Monikę
źródło
2
Dziękuję za odpowiedź. Zgadzam się, że twoje rozwiązanie jest właściwym sposobem, aby to zrobić, a ty sformułowałeś to zwięźle. Ograniczenia poza moim wpływem mogą utrudnić lub uniemożliwić (np. Niedostępne zasoby do testowania lub umożliwienia automatycznego testowania istniejącego kodu), ale zdecydowanie powinienem dokładnie sprawdzić, czy to rozwiązanie może działać, zanim wypróbuję inne sposoby. W moim pierwotnym myśleniu być może zbyt szybko założyłem, że nie mogę rozwiązać problemu u źródła.
jhyot
@jhyot Dobra. To frustrujące, gdy nie możesz robić rzeczy w czysty sposób. Mam nadzieję, że moja odpowiedź jest co najmniej przydatna dla innych, którzy mają podobne problemy, ale którzy są w stanie zaatakować główną przyczynę zamiast posprzątać bałagan po fakcie.
Przywróć Monikę
5

W odniesieniu do tego zdania w pytaniu:

To „teoretycznie” nie powinno się zdarzyć, więc jeśli tak, wskazuje to na złe dane lub błąd w kodzie.

Zawsze doceniałem ten cytat (dzięki uprzejmości tego artykułu ):

To zabawne, gdy początkujący programiści uważają, że ich głównym zadaniem jest zapobieganie awariom programów. Wyobrażam sobie, że ten spektakularny argument niepowodzenia nie byłby tak atrakcyjny dla takiego programisty. Bardziej doświadczeni programiści zdają sobie sprawę, że poprawny kod jest świetny, kod, który ulega awarii, może wymagać ulepszenia, ale niepoprawny kod, który nie ulega awarii, jest okropnym koszmarem.

Zasadniczo: brzmi to tak, jakbyś popierał Prawo Postela , „bądź konserwatywny w tym, co wysyłasz, bądź liberalny w tym, co akceptujesz”. Chociaż świetna w teorii, w praktyce ta „zasada niezawodności” prowadzi do oprogramowania, które nie jest niezawodne , przynajmniej w dłuższej perspektywie - a czasem także w krótkim okresie. (Porównaj artykuł Erica Allmana The Resustness Principle Reconspled , który jest bardzo dokładnym podejściem do tematu, aczkolwiek głównie skupiony na przypadkach użycia protokołu sieciowego).

Jeśli masz programy, które nieprawidłowo wstawiają dane do bazy danych, programy te są zepsute i muszą zostać naprawione . Zgłaszanie problemu pozwala tylko gorzej się pogłębiać; jest to odpowiednik inżynierii oprogramowania umożliwiający uzależnionemu kontynuowanie uzależnienia.

Pragmatycznie rzecz biorąc, czasami trzeba włączyć „zepsute” zachowanie, aby przynajmniej tymczasowo kontynuować, szczególnie w ramach płynnego przejścia od stanu rozluźnionego, zepsutego do stanu ścisłego, poprawnego. W takim przypadku chcesz znaleźć sposób, aby umożliwić nieprawidłowe wstawianie, ale nadal pozwól, aby „kanoniczny” magazyn danych zawsze był w poprawnym stanie . Można to zrobić na różne sposoby:

  • Użyj wyzwalacza bazy danych, aby przekonwertować zniekształcone wstawki na prawidłowe wstawienia, np. Poprzez zastąpienie brakujących / pustych wartości domyślnymi
  • Niech nieprawidłowe programy wstawią się do osobnej tabeli bazy danych, która może być „niepoprawna”, i mają osobny zaplanowany proces lub inny mechanizm, który przenosi poprawione dane z tej tabeli do kanonicznego magazynu danych
  • Użyj filtrowania po stronie zapytania (np. Widok), aby upewnić się, że dane pobrane z bazy danych są zawsze w poprawnym stanie, nawet jeśli dane w spoczynku nie są

Jednym ze sposobów uniknięcia tych wszystkich problemów jest wstawienie kontrolowanej warstwy API między programami, które wydają zapisy, a rzeczywistą bazą danych.

Wygląda na to, że częścią problemu jest to, że nie znasz nawet wszystkich miejsc, które generują nieprawidłowe zapisy - lub że jest ich po prostu zbyt wiele, abyś mógł je zaktualizować. Jest to przerażający stan, ale nigdy nie powinno się pozwolić, by powstało.

Gdy tylko pojawi się więcej niż kilka systemów, które mogą modyfikować dane w kanonicznym magazynie danych produkcyjnych, będziesz miał kłopoty: nie ma sposobu, aby centralnie utrzymywać cokolwiek na temat tej bazy danych. Lepiej byłoby pozwolić na jak najmniejszą liczbę procesów do wydawania zapisów i używać ich jako „strażników”, którzy mogą przetwarzać dane przed wstawieniem, jeśli to konieczne. Dokładny mechanizm tego zależy od konkretnej architektury.

Daniel Pryden
źródło
„Jeśli masz programy, które nieprawidłowo wstawiają dane do bazy danych, programy te są zepsute i muszą zostać naprawione”. to również świetnie w teorii, ale w rzeczywistości wciąż będą dodawać rekordy, podczas gdy jakaś komisja nadal debatuje nad tym, czy użyć „NA”, czy „None”.
JeffO
@JeffO: Żadna komisja nie powinna zastanawiać się, czy zapisać w bazie danych „NA”, „None”, NULL lub coś innego. Interesariusze non-techniczne mają swój udział w tym, co dane pochodzą z bazy danych i jak jest używany, ale nie w reprezentacji wewnętrznej.
Daniel Pryden
@DanielPryden: W mojej ostatniej pracy mieliśmy Radę ds. Przeglądu Architektury (wraz z podkomitetem DBA), która oceniałaby zmiany techniczne między domenami. Bardzo techniczne, ale spotykali się tylko co dwa tygodnie, a jeśli nie podasz im wystarczająco dużo szczegółów, odłożą decyzję, dopóki nie zrobisz ... na następnym spotkaniu. Większość nietrywialnych zmian systemowych, które nie polegały na dodaniu funkcjonalności za pomocą nowego kodu, rutynowo zajmowałaby około miesiąca.
TMN
@DanielPryden - Siedziałem na spotkaniach z wyższym kierownictwem debatując nad etykietami pól tekstowych. Można argumentować, że nie ma to nic wspólnego z tym, co chcesz nazwać w aplikacji lub bazie danych, ale tak jest.
JeffO
W odpowiedzi na komentarze dotyczące uzyskiwania dodatkowych zatwierdzeń dla zmian tego rodzaju: mój punkt widzenia na temat „nieprawidłowości” zakłada, że ​​dopuszczalne wartości są już gdzieś udokumentowane - dlatego OP twierdzi, że te wartości należy uznać za błąd. Jeśli schemat bazy danych jest określony, aby umożliwić wartość, to ta wartość nie jest błędem. Chodzi o to, że jeśli masz dane, które nie pasują do twojego schematu, wtedy coś jest zepsute: Twoim priorytetem powinno być dopasowanie danych i schematu. W zależności od zespołu może to obejmować zmianę danych, schematu lub obu tych elementów.
Daniel Pryden
2

Czy istnieją jakieś dobre zasady architektury lub projektowania do obsługi rzadkich, ale możliwych zerowych pozycji?

Prosta odpowiedź - tak.

ETL

Wykonaj wstępne przetwarzanie, aby upewnić się, że dane mają wystarczającą jakość, aby przejść do bazy danych. Wszystko w pliku upuszczenia należy zgłosić z powrotem, a wszelkie czyste dane można załadować do bazy danych.

Jako ktoś, kto był zarówno kłusownikiem (deweloperem), jak i opiekunem gry (DBA), wiem z gorzkiego doświadczenia, że ​​strony trzecie po prostu nie rozwiążą problemów z danymi, chyba że będą do tego zmuszone. Ciągłe pochylanie się do tyłu i masowanie danych przez zestaw stanowi niebezpieczny precedens.

Mart / Repository

W tym scenariuszu nieprzetworzone dane są wypychane do bazy danych repozytorium, a następnie zdezynfekowana wersja jest wypychana do bazy danych mart, do której aplikacje mają dostęp.

Wartości domyślne

Jeśli możesz zastosować rozsądne wartości domyślne do kolumn, powinieneś, choć może to wymagać trochę pracy, jeśli jest to istniejąca baza danych.

Niepowodzenie wcześnie

Kuszące jest po prostu rozwiązywanie problemów z danymi w bramie do aplikacji, pakietu raportów, interfejsu itp. Zdecydowanie odradzam poleganie wyłącznie na tym. Jeśli podłączysz jakiś inny widget do bazy danych, potencjalnie znów będziesz mieć do czynienia z tymi samymi problemami. Rozwiąż problemy z jakością danych.

Robbie Dee
źródło
+1 To właśnie zrobiłbym, zbierz wszystkie dane i utwórz prawidłowy zestaw danych do przetworzenia przez aplikację.
Kwebble
1

Ilekroć twój przypadek użycia pozwala bezpiecznie zastąpić NULL dobrą wartością domyślną, możesz wykonać konwersję w instrukcjach SELECTSql za pomocą ISNULLlub COALESCE. Więc zamiast

 SELECT MyColumn FROM MyTable

można pisać

 SELECT ISNULL(MyColumn,DefaultValueForMyColumn) FROM MyTable

Oczywiście będzie to działać tylko wtedy, gdy ORM pozwala bezpośrednio manipulować instrukcjami select lub zapewniać zmienne szablony do generowania. Należy upewnić się, że żadne „rzeczywiste” błędy nie są maskowane w ten sposób, więc zastosuj je tylko wtedy, gdy zastąpienie domyślną wartością jest dokładnie tym, czego chcesz w przypadku wartości NULL.

Jeśli jesteś w stanie zmienić bazę danych i schemat, a twój system db obsługuje to, możesz rozważyć dodanie klauzuli wartości domyślnej do konkretnych kolumn, zgodnie z sugestią @RobbieDee. Będzie to jednak wymagać modyfikacji istniejących danych w bazie danych w celu usunięcia wcześniej wstawionych wartości NULL, a następnie usunie możliwość rozróżnienia prawidłowych i niekompletnych danych importu.

Z własnego doświadczenia wiem, że używanie ISNULL może zadziwiająco dobrze - w przeszłości musiałem zachować starszą aplikację, w której pierwotni twórcy zapomnieli dodać ograniczenia NOT NULL do wielu kolumn i nie mogliśmy łatwo dodać tych ograniczeń później z pewnych powodów. Ale w 99% wszystkich przypadków 0 jako domyślny dla kolumn liczbowych i pusty ciąg jako domyślny dla kolumn tekstowych był w pełni akceptowalny.

Doktor Brown
źródło
Podczas gdy to działa, możesz skończyć z koniecznością duplikowania kodu obronnego dla każdego WYBORU. O wiele lepszym podejściem jest zdefiniowanie domyślnej wartości dla kolumny po wstawieniu wartości NULL, chociaż może to nie być możliwe / pożądane z różnych powodów.
Robbie Dee,
@RobbieDee: dzięki za tę uwagę, odpowiednio zmieniłem swoją odpowiedź. Jeśli jednak jest to „o wiele lepsze”, można się zastanawiać. Gdy kod CRUD jest w jednym miejscu, zduplikowany kod obronny może nie stanowić większego problemu. A jeśli tak nie jest, wcześniej jest już pewne kopiowanie kodu.
Doc Brown,
Proste operacje CRUD są oczywiście idealne. Ale w prawdziwym świecie systemy często mają skomplikowane widoki interfejsu użytkownika, generowane przez użytkownika kreatory danych, raporty itp. Ale, jak zauważyłeś, wartości domyślne muszą być dostępne od podstaw lub przynajmniej wymagają trochę wstępnej konwersji. To, co opisałeś, może być lepsze w rozwoju terenów poprzemysłowych.
Robbie Dee
Najlepsza odpowiedź. Nowe aplikacje zwykle dodają nowe dane, które mogą być poza twoją kontrolą. Błędne wartości NULL zwykle pochodzą z importu starszych danych do przeprojektowanych baz danych. Ograniczenia są w tym celu wyłączone, aby umożliwić jego ukończenie w ciągu kilku godzin zamiast kilku dni. „Wielka awaria” często pojawia się, gdy DBA próbują ponownie włączyć ograniczenia. Ponieważ nigdy nie było to planowane, zarząd często dręczy się w tygodniach pracy często wymaganych do naprawy złych danych, więc pozostaje. Wszystkie aplikacje powinny z wdziękiem obsługiwać wartości NULL, wstawiając wartości domyślne i raportując lub prosząc o brakujące dane w przeciwnym razie.
DocSalvager
1

OP zakłada odpowiedź, która łączy reguły biznesowe ze szczegółami technicznymi bazy danych.

To „teoretycznie” nie powinno się zdarzyć, więc jeśli tak, wskazuje to na złe dane lub błąd w kodzie. Błędy mają różne stopnie ważności, w zależności od tego, które pole ma wartość null; tj. w przypadku niektórych pól przetwarzanie powinno zostać zatrzymane, a ktoś powiadomiony, w innych przypadkach przetwarzanie powinno być kontynuowane i po prostu powiadomić kogoś.

To są wszystkie reguły biznesowe. Reguły biznesowe nie dbają o sam w sobie zero. Mimo wszystko wie, że baza danych może mieć wartość null, 9999, „BOO!” ... To tylko kolejna wartość. To, że w RDBMS null ma interesujące właściwości, a unikalne zastosowania są dyskusyjne.

Liczy się tylko to, co oznacza „nieważność” dla danych obiektów biznesowych ...

Czy istnieją jakieś dobre zasady architektury lub projektowania do obsługi rzadkich, ale możliwych zerowych pozycji?

Tak.

  • Umieść reguły biznesowe w klasach.
  • Transliteracja powinna znajdować się w odpowiedniej warstwie kodu oddzielającej klasy biznesowe i magazyn danych. Jeśli nie możesz umieścić go w kodzie ORM, przynajmniej nie umieszczaj go w bazie danych.
  • Niech baza danych będzie głupia, jak to możliwe, bez reguł biznesowych. Gryzą cię nawet nieszkodliwe rzeczy, takie jak domyślna wartość . Byłem tam
  • Sprawdź poprawność danych przechodzących do bazy danych i pochodzących z niej. I oczywiście odbywa się to w / w kontekście obiektów biznesowych.

Zgłaszanie wyjątku przy pobieraniu danych nie ma sensu.

Pytanie brzmi: „czy powinienem przechowywać„ złe ”dane? To zależy:

  • Można użyć złych danych - nigdy nie zapisuj nieprawidłowych obiektów ani kompozytów obiektów. Skomplikowane relacje danych / relacji biznesowych w każdym miejscu. Użytkownicy mogą wykonywać dowolne funkcje w dowolnym momencie, prawdopodobnie używając tego podmiotu biznesowego w wielu kontekstach. Wpływ (jeśli w ogóle) złych danych w momencie ich zapisywania nie jest znany, ponieważ jest wysoce zależny od przyszłego wykorzystania. Nie ma jednolitego / pojedynczego procesu tych danych.
  • Nie można postępować, jeśli występują złe dane - Zezwalaj na zapisywanie złych danych. Jednak następny krok w procesie nie może być kontynuowany, dopóki wszystko nie będzie poprawne. Na przykład robienie podatków dochodowych. Po pobraniu z bazy danych oprogramowanie wskazuje błędy i nie można go przesłać do urzędu skarbowego bez sprawdzenia poprawności.
radarbob
źródło
0

Istnieje wiele sposobów obsługi wartości zerowych, więc przejdziemy od warstwy bazy danych do warstwy aplikacji.


Warstwa bazy danych

Możesz zabronić zerowania ; chociaż tutaj jest to niepraktyczne.

Możesz skonfigurować domyślne dla poszczególnych kolumn:

  • Wymaga to, że kolumna być nieobecny z insert, więc nie obejmuje wyraźne wprowadzenie zerowej
  • zapobiega wykrywaniu z wierszy, w których insertbłędnie pominięto tę kolumnę

Możesz skonfigurować wyzwalacz , aby po wstawieniu brakujące wartości były automatycznie obliczane:

  • wymaga obecności niezbędnych informacji do wykonania tego obliczenia
  • spowolni insert

Warstwa zapytania

Możesz pominąć wiersze, w których występuje niedogodność null:

  • upraszcza główną logikę
  • zapobiega wykrywaniu „złych wierszy”, dlatego w celu ich sprawdzenia potrzebny byłby inny proces
  • wymaga instrumentowania każdego zapytania

Możesz podać wartość domyślną w zapytaniu:

  • upraszcza główną logikę
  • zapobiega wykrywaniu „złych wierszy”, dlatego w celu ich sprawdzenia potrzebny byłby inny proces
  • wymaga instrumentowania każdego zapytania

Uwaga: instrumentowanie każdego zapytania niekoniecznie stanowi problem, jeśli masz jakiś automatyczny sposób ich generowania.


Warstwa aplikacji

Możesz wstępnie sprawdzić tabelę pod kątem zabronionych null:

  • upraszcza główną logikę
  • poprawia czas do awarii
  • wymaga zachowania spójności kontroli wstępnej i logiki aplikacji

Możesz przerwać przetwarzanie, gdy napotkasz zabronione null:

  • pozwala uniknąć powielania wiedzy o tym, które kolumny mogą być, nulla które nie
  • wciąż jest stosunkowo prosty (tylko czek + zwrot / rzut)
  • wymaga wznowienia procesu (jeśli już wysłałeś e-mail, nie chcesz wysyłać go dwa razy lub sto razy!)

Możesz pominąć wiersz, gdy napotkasz zabronione null:

  • pozwala uniknąć powielania wiedzy o tym, które kolumny mogą być, nulla które nie
  • wciąż jest stosunkowo prosty (tylko czek + zwrot / rzut)
  • nie wymaga wznowienia procesu

Możesz wysłać powiadomienie, gdy napotkasz zakaz null, pojedynczo lub partią, co jest uzupełnieniem innych sposobów przedstawionych powyżej. Najważniejsze jest jednak „co wtedy?”, W szczególności, jeśli oczekujesz, że wiersz zostanie załatany i potrzebujesz ponownego przetworzenia, być może będziesz musiał upewnić się, że masz jakiś sposób na odróżnienie już przetworzonych wierszy od wierszy wymagających jest ponownie przetwarzany.


Biorąc pod uwagę twoją sytuację, poradziłbym sobie z sytuacją w aplikacji i połączyłem albo:

  • przerwać i powiadomić
  • pomiń i powiadom

Chciałbym po prostu pominąć, jeśli to możliwe, aby w jakiś sposób zagwarantować odrobinę postępu, szczególnie jeśli przetwarzanie może zająć trochę czasu.

Jeśli nie trzeba ponownie przetwarzać pominiętych wierszy, wystarczy je zarejestrować, a wiadomość e-mail wysłana na końcu procesu z liczbą pominiętych wierszy będzie trafnym powiadomieniem.

W przeciwnym razie użyłbym tabeli bocznej, aby wiersze zostały naprawione (i ponownie przetworzone). Ten boczny stolik może być albo prostym odniesieniem (bez klucza obcego), albo pełnoprawną kopią: ta ostatnia, nawet jeśli jest droższa, jest konieczna, jeśli nie masz czasu, aby się zająć, nullzanim będziesz musiał wyczyścić główne dane.

Matthieu M.
źródło
-1

Wartości zerowe mogą być obsługiwane w tłumaczeniu lub mapowaniu typów baz danych na typy językowe. Na przykład w języku C #, oto ogólna metoda, która obsługuje dla ciebie dowolny typ:

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;
        }

Lub, jeśli chcesz wykonać akcję ...

 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;
        }

A następnie w odwzorowaniu, w tym przypadku na obiekt typu „Próbka”, obsłużymy null dla dowolnej kolumny:

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])
                );
        }
    }

Na koniec wszystkie klasy odwzorowań mogą być generowane automatycznie na podstawie zapytania SQL lub powiązanych tabel, analizując typy danych SQL i tłumacząc je na typy danych specyficzne dla języka. To właśnie wiele ORM robi dla Ciebie automatycznie. Należy pamiętać, że niektóre typy baz danych mogą nie mieć bezpośredniego mapowania (geo-przestrzenne kolumny itp.) I mogą wymagać specjalnej obsługi.

Jon Raynor
źródło
Jeśli ktoś chce opublikować równoważną wersję Java, byłoby świetnie ...
Jon Raynor,
Myślę, że przykładowy kod jest doskonale zrozumiały również dla programistów Java. W mojej sytuacji mam już ORM, więc nie trzeba go wdrażać. Ale twoja odpowiedź dotyczy tylko wartości domyślnych dla wartości zerowych, podczas gdy w moim przypadku o wiele ważniejszym przypadkiem jest wykrycie wartości zerowej i uruchomienie akcji (np. Poinformowanie administratora o błędnych danych).
jhyot
Achhh, zaktualizuję swoją odpowiedź na tej podstawie.
Jon Raynor
Twój edytowany kod ma teraz jedną domyślną akcję dla dowolnej wartości pustej (tj. Jest całkowicie ogólny). Jest to bardzo podobne do mojej drugiej opcji w pierwotnym pytaniu, tj. Po prostu wyzeruj i złap gdzieś. Ale jak tam powiedziano, muszę rozróżnić działania, na podstawie których brakuje wartości.
jhyot