Mittwoch, 2. Dezember 2009

NULL in SQL-Datenbanken vermeiden

Warum sollte ich NULL in meiner Datenbank vermeiden?
Joe Celko sagte es am besten: "NULL verwechseln Menschen..." (Für Smarties, ISBN 1558605762 SQL). McGoveran und Datum hinzufügen: "NULL... sind weit mehr Probleme als Sie es Wert sind, und vermieden werden sollten; Sie sehr seltsam und inkonsistente Verhalten angezeigt und können eine reiche Quelle der Fehler und Verwirrung sein." (Handbuch, Sybase und SQLServer, ISBN 020155710X).

Meine Gefühl. Natürlich erwarte ich nicht Sie überzeugen durch blinkt ein paar Zitate aus seriösen Autoren. Sprechen wir für eine Minute, über was genau NULL tun, die diese Art der Reaktion verursachen. Das erste Problem ist, dass die Definition der NULL "Unbekannt". Also ist ein Problem ermitteln, ob ein Wert ist (nicht) gleich einem anderen Wert, wenn eine oder beide Werte NULL sind. Dies tröpfelt herunter, um viele Probleme für eine Datenbank-Engine und alle dazugehörigen Anwendungen. Die folgende Liste beschreibt einige dieser Probleme: Sie sind je nach Kompatibilitätsgrad und ANSI-Einstellungen unterschiedlich interpretiert; Z. B. betrachten zwei Werte, X und y, die beide NULL sind. Da die Definition der NULL unbekannt ist, dann Sie können nicht behaupten X = y. Allerdings kann mit der ANSI-ANSI_NULLs festlegen, dies unterschiedlich sein. Wenn diese Einstellung FALSE, ist X = y... jedoch, wenn TRUE, X > y. Verwechslung, keine?


die Speicher-Engine zu tun hat zusätzliche Verarbeitung für jede Zeile um zu bestimmen, wenn die nullwertfähige Spalte in der Tat NULL – ist diese zusätzliche bit Performance-Auswirkungen haben kann; Sie produzieren seltsam Ergebnisse beim Verwenden von Berechnungen, Vergleiche, sortieren und gruppieren; Sie Probleme mit Aggregaten und Joins, wie z. B. verschiedene Antworten für Count(*) vs. Count(Spaltenname) erstellen; Sie produzieren unvorhersehbare Ergebnissen in Statistiken Berechnungen, besonders WITH ROLLUP und WITH CUBE; Anwendungen müssen zusätzliche Logik zur Einfügen hinzufügen und Abrufen von Ergebnissen, die können oder darf nicht NULL-Werte enthalten; Sie verursachen unvorhersehbare Ergebnissen mit NOT EXISTS und NOT IN Unterabfragen (SQL arbeiten, rückwärts, bestimmt werden, dass NULL-Spalten gehören oder nicht zum Ergebnis gehören festlegen, in der Regel aus den falschen Gründen); keine Sprache, die embedded SQL unterstützt verfügt über systemeigene Unterstützung für NULL-SQL-Werte.
Hier sind einige konkrete Beispiele:

COUNT(state) USE PUBS GO SELECT FROM Verlage SELECT COUNT(pub_name) FROM

Verlage warum der Unterschied in Zählung führt? Sie würde * denken *, dass die Anzahl der eine identische Rowcount unabhängig von den Inhalt der Spalte geben würde. Es wird oft empfohlen, dass "*" vermieden werden, da es ineffizient ist (verursachen einen zusätzlichen Aufruf der Syscolumns-Tabelle)--aber in diesem Fall, wenn Sie in ihre Spalten NULL-Werte zulassen Sie Ihre Anzahl Grundlage laufen Gefahr, wird eine Spalte enthält... NULL zu eine ungenaue Zählung. Zum Glück ist der Motor wesentlich effizienter bei der Verarbeitung SELECT COUNT(*), als es SELECT Verarbeitung ist *.

Hier ist ein weiteres Beispiel für stärker einbezogen. Angenommen, Sie sind ein Stats-Programm ausführen, und jemand hat Dinge manuell eingeben. Was geschieht, wenn wissen Sie Sie nicht die Adid und/oder Siteid Wenn Sie geben Sie die Daten ein, und Sie sind Rollups dagegen durchführen? Wenn Sie es vor, WITH ROLLUP-Gruppen durch die GROUP BY-Spalten nicht verwendet haben, fügt dann Hauptzeilen. Sie fügt hinzu Flags jede Spalte Wenn Sie auf eine Hauptzeile, so dass Sie WHICH Hauptzeile identifizieren können, es ist. Erraten, was das Flag ist? NULL. Also probieren Sie diesen Code:

USE Pubs GO CREATE TABLE FakeStats (Id INT IDENTITY NOT NULL, Adid INT, Siteid INT, Hitcount INT) INSERT fakeStats(adid,siteid,hitcount) 1,1,40 SELECT INSERT SELECT 1,1,20 fakeStats(adid,siteid,hitcount) fakeStats(adid,siteid,hitcount) 1,2,30 SELECT INSERT fakeStats(adid,siteid,hitcount) 1,3,40 SELECT INSERT fakeStats(adid,siteid,hitcount) 2,1,40 SELECT INSERT fakeStats(adid,siteid,hitcount) 2,2,60 SELECT INSERT fakeStats(adid,siteid,hitcount) 2,2,20 SELECT INSERT fakeStats(adid,siteid,hitcount) 2,2,30 SELECT INSERT fakeStats(adid,siteid,hitcount) 2,3,10 SELECT INSERT SELECT adid,siteid,SUM(hitcount) FROM FakeStats GROUP BY Adid, Siteid WITH ROLLUP

Sie sehen, dass die Ergebnisse die Hauptzeilen mit NULL-Flags eindeutig identifizieren. Leider, wenn Sie NULL haben * in die Daten *, wird dies sehr schwierig, automatisch zu verarbeiten. Führen Sie beispielsweise, dies jetzt:
UPDATE FakeStats SET Adid = NULL WHERE Id = 4 UPDATE FakeStats SET Siteid = NULL WHERE Id = 6 SELECT adid,siteid,SUM(hitcount) FROM FakeStats GROUP BY Adid, Siteid WITH ROLLUP

Siehe den Unterschied? Welche Zeilen sind jetzt die Hauptzeilen? Leicht genug, um herauszufinden, wenn Sie haben einen kleinen Satz zur Folge und die Zeit um aus dem Chaos zu begradigen. Jedoch, wenn Sie ein System, die automatisch haben (oder auf Anforderung) erstellt Berichte gegen ein Datawarehouse, ich denke, Sie sehen können, wie NULL-Werte bis einige Straßensperrungen umgesetzt werden.

Manchmal NULL-Werte sind unvermeidbar – da die Informationen einfach ist nicht vorhanden, oder es ist noch nicht bekannt. Zwei solche Beispiele: Birthdates und Mitte Initialen. Gelegentlich kommen Sie über Szenarien, in denen Sie haben unvollständigen Informationen von einem Benutzer, und daher können Sie wählen, ob es warten oder entscheiden, dass die Informationen nicht zur Ergänzung der Daten erforderlich ist – in diesem Fall NULL erlaubt werden sollte. (Für eine Person ohne Initiale des zweiten Vornamens, könnten Sie NULL umgehen, indem Sie verwenden eine leere Zeichenfolge (''). Hoffentlich, Geburtsdatum ist ein Teil Ihres primären Schlüssels nicht, und dadurch können Sie um NULL zu speichern, bis Sie die zusätzliche Informationen erhalten.)

Mein Vorschlag besteht darin, einen Standardwert in jedem Fall zu verwenden, die macht Sinn, und deklarieren Sie alle solche Spalten ausdrücklich als NOT NULL. Der Standardwert in DDL-für die Erstellung von Spalte, ist mindestens in SQL Server NULL, wenn Sie nicht angeben. Die beiden folgenden Anweisungen erstellen eine identische paar von Tabellen: CREATE TABLE-foo1 (Id INT) GO CREATE TABLE foo2 (Id INT NULL), das Standardverhalten ändern zwischen Servern, Datenbanken und sogar zwischen Hinrichtungen in derselben Sitzung, so spielen Sie es sicher und immer explizit deklarieren NULL oder NOT NULL.

Keine Kommentare:

Kommentar veröffentlichen

 
Nereides.Rss.Feeds | Delphi lernen, Delphi Kurs