Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Wie halte ich NULL auseinander?

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von Hahnematz, 18 November 2013.

  1. Hahnematz

    Hahnematz Neuer Benutzer

    Hallo,
    ich befinde mich gerade in meiner Ausbildung und bin heute in einer Übung auf ein für mich interessantes Problem gestoßen, was ich im nachhinein daheim probiert habe, aber leider nicht selbst gelöst bekam.

    Und zwar folgender Umstand:

    Ich habe eine Tabelle der Form: GUID(PK) | ZeigerGUID | Datum | Wert
    Datentypen der Spalten: uniqueid. not null | uniqueid. not null | datetime not null | varchar(50) null
    In dieser Tabelle wird gespeichert, welcher Prozess (ZeigerGUID) zu welchem Datum, welchen Wert hat.

    Nun hätte ich gerne den Wert zu einem bestimmten Datum. Die Abfrage hierbei ist folglich:

    SELECT Wert
    FROM Tabelle
    WHERE ZeigerGUID=IrgendEinProzess AND Datum=Datumswert

    Dieses Weise ich einer Variablen @Wert zu. Und hier beginnt mein Problem:
    Die Variable @Wert kann den Wert NULL erhalten, wenn dies entweder in der Wertspalte am angegebenen Datum so steht, oder es zu einem bestimmten Datum erst gar keine Einträge gibt. Wie unterscheidet man nun gekonnt ob das nun ein genulltes Wertfeld war oder eine Abfrage ohne Ergebnisse?

    Eine Variante die grob funktionierte, mich aber in keinster Weise zufriedenstellte, war ein
    SELECT Count(*)
    FROM Tabelle
    WHERE ZeigerGUID=IrgendEinProzess AND Datum=Datumswert
    einer weiteren Variablen zu zuweisen und dann zu entscheiden: bei 0 wars die Abfrage, bei 1 der Wert. Doch irgendwie wirkt diese Lösung unsauber.

    Da ich mich verbessern möchte, habt ihr hier vielleicht einen Rat oder Stupser in eine bessere Richtung für mich?

    Mit freundlichem Gruße
    der Hahnematz
     
  2. akretschmer

    akretschmer Datenbank-Guru

    De Ansatz ist schon okay. Je nach Applikation, mit der du das machst, hast Du aber auch eine Info, wie groß das Resultset ist.

    Code:
    test=*# select * from hahnematz ;
     id | zeiger | val
    ----+--------+-----
      1 |  2 |  3
      |  |  4
      3 |  3 |  4
      5 |  5 |
    (4 rows)
    
    Time: 0,149 ms
    test=*# select val from hahnematz where id = 5 and zeiger = 5;
     val
    -----
    
    (1 row)
    
    Time: 0,201 ms
    test=*# select val from hahnematz where id = 5 and zeiger = 6;
     val
    -----
    (0 rows)
    
    Time: 0,191 ms
    
    Beacht ein den 2 letzten Abfragen die Aussage über die Anzahl Rows.
     
  3. Hahnematz

    Hahnematz Neuer Benutzer

    Ich hab jetzt noch ein wenig versucht das gezeigte nach zu stellen, aber dieses *# ist mir bisher gänzlich unbekannt und ich finde leider auch nichts darüber. Was hat es damit auf sich?

    Mit freundlichem Gruße
    der Hahnematz
     
  4. akretschmer

    akretschmer Datenbank-Guru

    Ich mußte erst mal überlegen, was Du meinst ;-)

    Das ist der Prompt der Datenbank. Dahinter kann man seine SQL-Befehle schreiben.

    Code:
    psql test
    Timing is on.
    psql (9.3.0)
    Type "help" for help.
    
    test=# select now();
      now
    -------------------------------
     2013-11-19 07:56:18.828318+01
    (1 row)
    
    Time: 68,608 ms
    test=*#
    
    Ich hab den bei mir noch ge-pimpt: =# bedeutet: nicht in einer Transaktion, =*#: ich bin in einer Transaktion, ich habe AUTOCOMMIT=OFF in meiner Konfiguration.
     
  5. Hubertus

    Hubertus Fleissiger Benutzer

    Die Abfrage

    SELECT Wert
    FROM Tabelle
    WHERE ZeigerGUID=IrgendEinProzess AND Datum=Datumswert

    liefert den Returncode "NOTFOUND", wenn die Abfrage ohne Ergebnis ist. Ansonsten liefert sie den "Wert" (dieser kann auch NULL sein).
     
    Zuletzt bearbeitet: 19 November 2013
  6. ukulele

    ukulele Datenbank-Guru

    Also um mal auf das Problem einzugehen, zwischen NULL und NULL kann man zunächst mal nicht unterscheiden. Natürlich gibts einige Wege das mit Abfragen zu lösen, ich versuche mich mal an alternativen Varianten. Was Sinn macht muss man dann im jeweiligen Anwendungsfall entscheiden.
    Code:
    IF EXISTS (    SELECT    1
                FROM    Tabelle
                WHERE    ZeigerGUID=IrgendEinProzess AND Datum=Datumswert
    BEGIN
        DECLARE    @Wert UNIQUEIDENTIFIER
        SET        @Wert = (    SELECT    Wert
                            FROM    Tabelle
                            WHERE    ZeigerGUID=IrgendEinProzess AND Datum=Datumswert )
    END
    ELSE
    BEGIN
        SELECT    'Fehler' AS Fehler
    END
    EXISTS ist gut um das Vorhandensein von Daten zu prüfen. Ist natürlich mindestens eine weitere Abfrage.
    Code:
    DECLARE    @Wert UNIQUEIDENTIFIER,
            @isnull BIT
    
    SELECT    @Wert = Wert,
            @isnull = 1
    FROM    Tabelle
    WHERE    ZeigerGUID=IrgendEinProzess AND Datum=Datumswert
    In diesem Fall hätten wir eine Variable @isnull die auf 1 steht wenn der Wert aus der Tabelle NULL ist. Wenn es keinen Wert in der Tabelle gibt müssten eigentlich beide Variablen NULL sein.

    Dann gäbe es auch noch isnull() als Funktion mit der man einen standard Wert vergeben könnte, das hilft dir aber nicht beim Unterscheiden.
     
  7. Hahnematz

    Hahnematz Neuer Benutzer

    Vielen Dank für eure Hilfe, das hat mich echt weiter gebracht :)
    Da es auch mit EXISTS, wie von ukulele gezeigt, zu einer weiteren Abfrage kommt habe ich mir meinen ersten Ansatz nochmal hergenommen und in eine Bedingung verpackt die mir erfolgreich alle 3 Zustände liefert (Wert/NULL-Wert/leereErgebnismenge). Selbiges auch mit EXISTS probiert und funktioniert auch wie gewollt.

    Vielen Dank nochmals, ihr seid Spitze! :)

    Mit freundlichem Gruße
    der Hahnematz
     
  8. ukulele

    ukulele Datenbank-Guru

    Poste mal bitte noch deine Variante, bin neugirig :)
     
  9. Hahnematz

    Hahnematz Neuer Benutzer

    Das ist die Abfrag für die Unterscheidung ob es nun ein NULL-Wert ist oder keine Ergebnismenge zurückgegeben wurde.
    Da drum herum liegt nurnoch die Abfrage für @Wert NOT NULL weil das meine normale Routine ist :)

    Code:
    @Wert = (SELECT Wert FROM Tabelle WHERE ZeigerGUID=IrgendEinProzess AND Datum=Datumswert)
    
    IF (@Wert IS NULL AND EXSISTS(SELECT Wert FROM TABELLE WHERE ZeigerGUID=IrgendEinProzess AND Datum=Datumswert))
    -- Wert ist NULL aber der Datensatz existiert
    ELSE
    -- leere Ergebnismenge
    Falls noch Anregungen vorhanden sind bin ich ganz Ohr!

    Mit freundlichem Gruße
    der Hahnematz
     
  10. ukulele

    ukulele Datenbank-Guru

    Nein eigentlich gut ;)
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden