Tenía el mismo tipo de necesidad y encontré que esto funcionaba bien para mí (postgres 8.4):
CAST((COALESCE(myfield,'0')) AS INTEGER)
Algunos casos de prueba para demostrar:
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 necesita manejar la posibilidad de que el campo tenga texto no numérico (como "100bad"), puede usar regexp_replace para quitar caracteres no numéricos antes de la conversión.
CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER)
Luego, los valores de texto / varchar como "b3ad5" también darán números
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
Para abordar la preocupación de Chris Cogdon con la solución de no dar 0 para todos los casos, incluido un caso como "incorrecto" (sin caracteres de dígitos), hice esta declaración ajustada:
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
Funciona de manera similar a las soluciones más simples, excepto que dará 0 cuando el valor a convertir sea solo caracteres que no sean dígitos, como "incorrecto":
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)