PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Le test N'EST PAS NULL pour un enregistrement ne renvoie pas VRAI lorsque la variable est définie

Je vois deux raisons possibles, pourquoi...

Aucune de ces augmentations n'apparaît dans mon journal de messages

Non connecté

Tout d'abord, un NOTICE n'est normalement pas écrit dans le journal de la base de données avec les paramètres par défaut. Je cite le manuel ici :

log_min_messages (enum )

Contrôle les niveaux de message qui sont écrits dans le journal du serveur. Les valeurs valides sont DEBUG5 , DEBUG4 , DEBUG3 , DEBUG2 , DEBUG1 , INFO , NOTICE , WARNING , ERROR , LOG , FATAL , et PANIC . (...)
La valeur par défaut est AVERTISSEMENT . Notez que LOG a un rang différent ici que dans client_min_messages .

Bold emphase mienne. Notez également la valeur par défaut différente (NOTICE ) pour client_min_messages (élément précédent dans le manuel).

Test invalide

Deuxièmement, considérez comment une expression de ligne est évaluée. Un test row_variable IS NULL renvoie TRUE si (et seulement si) chaque élément est NULL . Soit l'exemple suivant :

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

Les deux les expressions renvoient FALSE . En d'autres termes, une variable de ligne (ou d'enregistrement) (1, NULL) n'est ni NULL , ni NOT NULL . Par conséquent, vos deux tests échouent.

-> SQLfiddle avec plus de détails.

Plus de détails, d'explications, de liens et une application possible pour ce comportement dans un CHECK contrainte dans cette réponse connexe :
Contrainte NOT NULL sur un ensemble de colonnes

Vous pouvez même affecter une variable d'enregistrement avec NULL (rec := NULL ), ce qui fait que chaque élément est NULL - si le type est un type de ligne bien connu. Sinon, nous avons affaire à un enregistrement anonyme et la structure n'est pas définie et vous ne pouvez pas accéder aux éléments pour commencer. Mais ce n'est pas le cas avec un rowtype comme dans ton exemple (qui est toujours bien connu).

Solution :FOUND

Quelle est la bonne façon de tester si vous avez reçu une ligne d'un SELECT * INTO ?

Vous devez considérer que la ligne peut être NULL, même si elle a été affectée. La requête aurait très bien pu renvoyer un tas de valeurs NULL (si la définition de table dans votre requête autorise les valeurs NULL). Un tel test ne serait pas fiable de par sa conception.

Il existe une approche simple et sécurisée. Utilisez GET DIAGNOSTICS ... ou (le cas échéant) la variable spéciale 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;

Détails dans le manuel.