PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

IS NOT NULL test per un record non restituisce TRUE quando è impostata la variabile

Vedo due possibili ragioni, perché...

Nessuno di questi aumenti compare nel registro dei miei messaggi

Non registrato

Innanzitutto, un NOTICE normalmente non viene scritto nel registro del database con le impostazioni predefinite. Cito il manuale qui:

log_min_messages (enum )

Controlla quali livelli di messaggio vengono scritti nel registro del server. I valori validi sono DEBUG5 , DEBUG4 , DEBUG3 , DEBUG2 , DEBUG1 , INFO , NOTICE , NOTICE , ERROR , LOG , FATAL e PANIC . (...)
L'impostazione predefinita è AVVISO . Nota che LOG ha un rango diverso qui rispetto a client_min_messages .

Enfasi in grassetto mio. Nota anche la diversa impostazione predefinita (NOTICE ) per client_min_messages (elemento precedente nel manuale).

Test non valido

In secondo luogo, considera come viene valutata un'espressione di riga. Un test row_variable IS NULL restituisce TRUE if (e solo se) ogni singolo elemento è NULL . Dato il seguente esempio:

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

Entrambi le espressioni restituiscono FALSE . In altre parole, una variabile di riga (o record) (1, NULL) non è né NULL , né NOT NULL . Pertanto, entrambi i test falliscono.

-> SQLfiddle con maggiori dettagli.

Maggiori dettagli, spiegazioni, link e una possibile applicazione per questo comportamento in un CHECK vincolo in questa risposta correlata:
NON vincolo NULL su un insieme di colonne

Puoi anche assegnare una variabile di record con NULL (rec := NULL ), che fa sì che ogni elemento sia NULL - se il tipo è un tipo di riga noto. In caso contrario, abbiamo a che fare con un record anonimo e la struttura non è definita e non puoi accedere agli elementi per cominciare. Ma non è il caso di un rowtype come nel tuo esempio (che è sempre noto).

Soluzione:FOUND

Qual è il modo corretto per verificare se hai ricevuto una riga da un SELECT * INTO ?

Devi considerare che la riga potrebbe essere NULL, anche se assegnata. La query potrebbe benissimo aver restituito una serie di valori NULL (se la definizione della tabella nella query consente valori NULL). Tale test sarebbe inaffidabile in base alla progettazione.

C'è un approccio semplice e sicuro. Usa GET DIAGNOSTICS ... o (ove applicabile) la variabile speciale 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;

Dettagli nel manuale.