web-dev-qa-db-fra.com

La valeur NULL provoque une ligne vide dans les résultats SELECT pour la concaténation de texte

J'ai une requête pour produire du texte pour créer du texte de VALEURS à mettre dans un fichier .sql pour insérer des lignes. J'obtiens une ligne vierge dans les résultats:

postgres=# SELECT '  (' || obj_id || ', ''' || obj_type || '''),' FROM il2.objects WHERE obj_id < 11 ORDER BY obj_id;
        ?column?         
-------------------------
   (1, 'ScienceDomain'),

   (3, 'PIs'),
   (10, 'Instrument'),
(4 rows)

Faire un select *, il est assez clair que cela est causé par le obj_type étant NULL pour obj_id 2:

postgres=# SELECT * FROM il2.objects WHERE obj_id < 11;
 obj_id |   obj_type    
--------+---------------
     10 | Instrument
      1 | ScienceDomain
      2 | 
      3 | PIs
(4 rows)

(confirmant que c'est NULL):

postgres=# SELECT * FROM il2.objects WHERE obj_type IS NULL;
 obj_id | obj_type 
--------+----------
      2 | 

Pourquoi le résultat du premier SELECT me donne-t-il une ligne vide?
Même casting obj_type::text m'a toujours donné une ligne vide.


Informations supplémentaires: Le schéma, pour ce qu'il vaut:

postgres=# \d il2.objects
                                  Table "il2.objects"
  Column  |       Type        | Collation | Nullable |             Default              
----------+-------------------+-----------+----------+----------------------------------
 obj_id   | integer           |           | not null | generated by default as identity
 obj_type | character varying |           |          | 
Indexes:
    "objects_pkey" PRIMARY KEY, btree (obj_id)
6
Randall

Pourquoi le résultat du premier SELECT me donne-t-il une ligne vide?

Parce que la concaténation de NULL avec n'importe quel type de caractère (ou la plupart des autres types, les types de tableau étant une exception notable) entraîne NULL. En relation:

La représentation de NULL dépend de votre client. Certains expliquent NULL, certains (incl. Psql) mettent rien à la place. C'est souvent configurable.

Même le casting obj_type::text M'a toujours donné une ligne vide.

La conversion de NULL vers (presque) n'importe quel type renvoie toujours NULL - d'un autre type de données.

J'ai une requête pour produire du texte pour créer du texte VALUES à mettre dans un fichier .sql pour insérer des lignes.

Avez-vous envisagé COPY ou équivalent psql \copy ?

Autres solutions

Si votre exemple n'est pas simplifié, vous pouvez simplement sélectionner des valeurs de ligne entières:

SELECT o  -- whole row
FROM   il2.objects o
WHERE  obj_id < 11
ORDER  BY obj_id;

Si vous avez besoin de ce format spécifique, utilisez format() pour faire simple. Fonctionne avec NULL valeurs prédéfinies:

SELECT format('(%s, %L),', obj_id, obj_type)
FROM   objects;

Vous obtenez NULL (sans guillemets) à la place de NULL valeurs (qui sont distinctes de '' et peuvent devoir être distingués.)

db <> violon ici (ajouté au violon existant de McNets, cudos)

8
Erwin Brandstetter

Utilisez la fonction COALESCE pour renvoyer la valeur actuelle ou une chaîne vide.

SELECT '  (' || obj_id || ', ''' || coalesce(obj_type, '') || '''),' 
FROM   objects;
 | ?colonne? | 
 | : ----------- | (1, "val 1"), | 
 | (2, ''), | 
 | (3, "val 3"), | 
 | (4, 'val 4'), | 

db <> violon --- (ici

11
McNets