In PostgreSQL I have a table with a varchar column. The data is supposed to be integers and I need it in integer type in a query. Some values are empty strings. The followin
I was just wrestling with a similar problem myself, but didn't want the overhead of a function. I came up with the following query:
SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$';
Postgres shortcuts its conditionals, so you shouldn't get any non-integers hitting your ::integer cast. It also handles NULL values (they won't match the regexp).
If you want zeros instead of not selecting, then a CASE statement should work:
SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable;
If the data is supposed to be integers, and you only need those values as integers, why don't you go the whole mile and convert the column into an integer column?
Then you could do this conversion of illegal values into zeroes just once, at the point of the system where the data is inserted into the table.
With the above conversion you are forcing Postgres to convert those values again and again for each single row in each query for that table - this can seriously degrade performance if you do a lot of queries against this column in this table.
SELECT CASE WHEN myfield="" THEN 0 ELSE myfield::integer END FROM mytable
I haven't ever worked with PostgreSQL but I checked the manual for the correct syntax of IF statements in SELECT queries.
I found the following code easy and working. Original answer is here https://www.postgresql.org/message-id/371F1510.F86C876B@sferacarta.com
prova=> create table test(t text, i integer);
CREATE
prova=> insert into test values('123',123);
INSERT 64579 1
prova=> select cast(i as text),cast(t as int)from test;
text|int4
----+----
123| 123
(1 row)
hope it helps
I had the same sort of need and found this to work well for me (postgres 8.4):
CAST((COALESCE(myfield,'0')) AS INTEGER)
Some test cases to demonstrate:
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"
If you need to handle the possibility of the field having non-numeric text (such as "100bad") you can use regexp_replace to strip non-numeric characters before the cast.
CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER)
Then text/varchar values like "b3ad5" will also give numbers
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
To address Chris Cogdon's concern with the solution not giving 0 for all cases, including a case such as "bad" (no digit characters at all), I made this adjusted statement:
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
It works similar to the simpler solutions, except will give 0 when the value to convert is non-digit characters only, such as "bad":
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)
This should also do the job but this is across SQL and not postgres specific.
select avg(cast(mynumber as numeric)) from my table