PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Der IS NOT NULL-Test für einen Datensatz gibt nicht TRUE zurück, wenn die Variable gesetzt ist

Ich sehe zwei mögliche Gründe, warum ...

Keine dieser Erhöhungen erscheint in meinem Nachrichtenprotokoll

Nicht angemeldet

Zuerst ein NOTICE wird normalerweise nicht mit Standardeinstellungen in das Datenbankprotokoll geschrieben. Ich zitiere das Handbuch hier:

log_min_messages (enum )

Steuert, welche Nachrichtenebenen in das Serverprotokoll geschrieben werden. Gültige Werte sind DEBUG5 , DEBUG4 , DEBUG3 , DEBUG2 , DEBUG1 , INFO , NOTICE , WARNING , ERROR , LOG , FATAL , und PANIC . (...)
Der Standardwert ist WARNUNG . Beachten Sie, dass LOG hat hier einen anderen Rang als in client_min_messages .

Fette Hervorhebung von mir. Beachten Sie auch die abweichende Voreinstellung (NOTICE ) für client_min_messages (vorheriger Punkt im Handbuch).

Ungültiger Test

Überlegen Sie zweitens, wie ein Zeilenausdruck ausgewertet wird. Ein Test row_variable IS NULL gibt TRUE zurück wenn (und nur wenn) jedes einzelne Element ist NULL . Gegeben das folgende Beispiel:

SELECT (1, NULL) IS NULL AS a     -- FALSE
      ,(1, NULL) IS NOT NULL AS b -- also FALSE

Beides Ausdrücke geben FALSE zurück . Mit anderen Worten, eine Zeilen- (oder Datensatz-) Variable (1, NULL) ist weder NULL , noch ist es NOT NULL . Daher schlagen beide Tests fehl.

-> SQLfiddle mit mehr Details.

Weitere Details, Erklärungen, Links und eine mögliche Anwendung für dieses Verhalten in einem CHECK Einschränkung in dieser verwandten Antwort:
NOT NULL-Einschränkung über eine Reihe von Spalten

Sie können sogar eine Datensatzvariable mit NULL zuweisen (rec := NULL ), was dazu führt, dass jedes Element NULL ist – wenn der Typ ein bekannter Zeilentyp ist. Andernfalls haben wir es mit einem anonymen Datensatz zu tun und die Struktur ist undefiniert und Sie können zunächst nicht auf Elemente zugreifen. Aber das ist bei einem rowtype nicht der Fall wie in deinem (immer bekannten) Beispiel.

Lösung:FOUND

Was ist der richtige Weg, um zu testen, ob Sie eine Zeile von einem SELECT * INTO erhalten haben ?

Sie müssen bedenken, dass die Zeile NULL sein könnte, auch wenn sie zugewiesen wurde. Die Abfrage hätte sehr wohl eine Reihe von NULL-Werten zurückgeben können (wenn die Tabellendefinition in Ihrer Abfrage NULL-Werte zulässt). Ein solcher Test wäre konstruktionsbedingt unzuverlässig.

Es gibt einen einfachen und sicheren Ansatz. Verwenden Sie GET DIAGNOSTICS ... oder (wo zutreffend) die spezielle Variable FOUND :

SELECT * FROM my_table WHERE owner_id = 6 INTO my_var;

IF NOT FOUND THEN
   RAISE NOTICE 'Query did not return a row!';
END IF;

Details im Handbuch.