J'ai une table Postgres avec une colonne de chaîne contenant des valeurs numériques. J'ai besoin de convertir ces chaînes en nombres pour les mathématiques, mais j'ai besoin des valeurs NULL
ainsi que des chaînes vides à interpréter comme 0
.
Je peux convertir des chaînes vides en valeurs nulles :
# select nullif('','');
nullif
--------
(1 row)
Et je peux convertir des valeurs nulles en 0
:
# select coalesce(NULL,0);
coalesce
----------
0
(1 row)
Et je peux convertir les chaînes en nombres :
# select cast('3' as float);
float8
--------
3
(1 row)
Mais lorsque j'essaie de combiner ces techniques, j'obtiens des erreurs:
# select cast( nullif( coalesce('',0), '') as float);
ERROR: invalid input syntax for integer: ""
LINE 1: select cast( nullif( coalesce('',0), '') as float);
# select coalesce(nullif('3',''),4) as hi;
ERROR: COALESCE types text and integer cannot be matched
LINE 1: select coalesce(nullif('3',''),4) as hi;
Qu'est-ce que je fais mal?
Les types de valeurs doivent être cohérents; la fusion de la chaîne vide à un 0 signifie que vous ne pouvez pas la comparer à null
dans le nullif
. Donc, l'un de ces travaux:
# create table tests (orig varchar);
CREATE TABLE
# insert into tests (orig) values ('1'), (''), (NULL), ('0');
INSERT 0 4
# select orig, cast(coalesce(nullif(orig,''),'0') as float) as result from tests;
orig | result
------+--------
1 | 1
| 0
| 0
0 | 0
(4 rows)
# select orig, coalesce(cast(nullif(orig,'') as float),0) as result from tests;
orig | result
------+--------
1 | 1
| 0
| 0
0 | 0
(4 rows)
Vous pouvez également utiliser
cast(
case
when coalesce(orig, '') = '' then '0'
else orig
end
as float
)
Vous pouvez également déballer cela un peu puisque vous commencez de toute façon assez verbeux:
cast(
case
when orig is null then '0'
when orig = '' then '0'
else orig
end
as float
)
ou vous pouvez mettre le plâtre à l'intérieur du CAS:
case
when coalesce(orig, '') = '' then 0.0
else cast(orig as float)
end
Un CASE facilite un peu la prise en compte d'autres conditions spéciales, cela semble également être une expression plus claire de la logique IMO. OTOH, goût personnel et tout ça.
En fait, vous pouvez convertir NULL en int, vous ne pouvez simplement pas convertir une chaîne vide en int. En supposant que vous vouliez NULL dans la nouvelle colonne si data1 contient une chaîne vide ou NULL, vous pouvez faire quelque chose comme ceci:
UPDATE table SET data2 = cast(nullif(data1, '') AS int);
ou
UPDATE table SET data2 = nullif(data1, '')::int;