J'avais le même genre de besoin et j'ai trouvé que cela fonctionnait bien pour moi (postgres 8.4) :
CAST((COALESCE(myfield,'0')) AS INTEGER)
Quelques cas de test pour démontrer :
db=> select CAST((COALESCE(NULL,'0')) AS INTEGER);
int4
------
0
(1 row)
db=> select CAST((COALESCE('','0')) AS INTEGER);
int4
------
0
(1 row)
db=> select CAST((COALESCE('4','0')) AS INTEGER);
int4
------
4
(1 row)
db=> select CAST((COALESCE('bad','0')) AS INTEGER);
ERROR: invalid input syntax for integer: "bad"
Si vous devez gérer la possibilité que le champ contienne du texte non numérique (tel que "100bad"), vous pouvez utiliser regexp_replace pour supprimer les caractères non numériques avant la distribution.
CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER)
Les valeurs de type texte/varchar comme "b3ad5" donneront également des chiffres.
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
Pour répondre à la préoccupation de Chris Cogdon concernant le fait que la solution ne donne pas 0 pour tous les cas, y compris un cas tel que "mauvais" (aucun caractère numérique), j'ai fait cette déclaration ajustée :
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
Elle fonctionne de la même manière que les solutions plus simples, sauf qu'elle donne 0 lorsque la valeur à convertir est constituée uniquement de caractères non numériques, comme "mauvais" :
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)