如何将一个string转换为整型,并且在PostgreSQL中转换时出现错误0?

在postgres中我有一个varchar列的表。 数据应该是整数,我需要它在迭代types的查询。 有些值是空string。 下列:

SELECT myfield::integer FROM mytable 

产生ERROR: invalid input syntax for integer: ""

如何查询一个强制转换,并在postgres中抛出时出错?

我只是自己摔跤类似的问题,但不希望一个函数的开销。 我想出了以下的查询:

 SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$'; 

Postgres快捷键的条件,所以你不应该得到任何非整数击中你的::整数铸造。 它也处理NULL值(它们不会匹配正则expression式)。

如果你想要零而不是select,那么CASE语句应该工作:

 SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable; 

您也可以创build自己的转换函数,在其中您可以使用exception块:

 CREATE OR REPLACE FUNCTION convert_to_integer(v_input text) RETURNS INTEGER AS $$ DECLARE v_int_value INTEGER DEFAULT NULL; BEGIN BEGIN v_int_value := v_input::INTEGER; EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'Invalid integer value: "%". Returning NULL.', v_input; RETURN NULL; END; RETURN v_int_value; END; $$ LANGUAGE plpgsql; 

testing:

 =# select convert_to_integer('1234'); convert_to_integer -------------------- 1234 (1 row) =# select convert_to_integer(''); NOTICE: Invalid integer value: "". Returning NULL. convert_to_integer -------------------- (1 row) =# select convert_to_integer('chicken'); NOTICE: Invalid integer value: "chicken". Returning NULL. convert_to_integer -------------------- (1 row) 

我有同样的需求,发现这对我来说很好(postgres 8.4):

 CAST((COALESCE(myfield,'0')) AS INTEGER) 

一些testing用例来演示:

 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" 

如果您需要处理字段具有非数字文本(例如“100bad”)的可能性,则可以使用regexp_replace在转换之前去除非数字字符。

 CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER) 

然后像“b3ad5”文本/ varchar值也会给数字

 db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER); regexp_replace ---------------- 35 (1 row) 

为了解决Chris Cogdon关于所有情况下不给0的解决scheme的顾虑,包括诸如“坏”(根本没有数字字符)的情况,我做了这个调整陈述:

 CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER); 

它的作用类似于更简单的解决scheme,除非在转换的值是非数字字符时才会给出0,例如“bad”:

 db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER); coalesce ---------- 0 (1 row) 

这可能有些黑客,但是在我们的案例中完成了这项工作:

 (0 || myfield)::integer 

解释(testingPostgres 8.4):

上面提到的expression式在myfield为NULL值,在空string中为0 (这个确切的行为可能会或可能不符合你的用例)。

 SELECT id, (0 || values)::integer from test_table ORDER BY id 

testing数据:

 CREATE TABLE test_table ( id integer NOT NULL, description character varying, "values" character varying, CONSTRAINT id PRIMARY KEY (id) ) -- Insert Test Data INSERT INTO test_table VALUES (1, 'null', NULL); INSERT INTO test_table VALUES (2, 'empty string', ''); INSERT INTO test_table VALUES (3, 'one', '1'); 

该查询将产生以下结果:

  --------------------- |1|null |NULL| |2|empty string|0 | |3|one |1 | --------------------- 

而只selectvalues::integer将导致错误消息。

希望这可以帮助。

SELECT CASE WHEN myfield="" THEN 0 ELSE myfield::integer END FROM mytable

我从来没有使用过PostgreSQL,但是我在SELECT查询中检查了手册中正确的IF语句语法。

@马修的答案是好的。 但它可以更简单,更快。 问题是要将空string( '' )转换为0 ,而不是其他“无效input语法”或“超出范围”input:

 CREATE OR REPLACE FUNCTION convert_to_int(text) RETURNS int AS $func$ BEGIN IF $1 = '' THEN -- special case for empty string like requested RETURN 0; ELSE RETURN $1::int; END IF; EXCEPTION WHEN OTHERS THEN RETURN NULL; -- NULL for other invalid input END $func$ LANGUAGE plpgsql IMMUTABLE; 

这将为空string返回0 ,对于任何其他无效input返回NULL
它可以很容易地适应任何数据types转换

input一个exception块实际上比较昂贵。 如果空string是常见的,那么在引发exception之前捕获该情况是有意义的。
如果空string非常罕见,那么将testing移到exception子句是值得的。

 CREATE OR REPLACE FUNCTION parse_int(s TEXT) RETURNS INT AS $$ BEGIN RETURN regexp_replace(('0' || s), '[^\d]', '', 'g')::INT; END; $$ LANGUAGE plpgsql; 

如果inputstring中没有数字,此函数将始终返回0

SELECT parse_int('test12_3test');

将返回123

我发现下面的代码很容易和工作。 原始答案在这里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) 

希望能帮助到你

如果数据应该是整数,并且只需要这些值作为整数,为什么不去整个英里并将列转换为整数列?

然后,您可以在将数据插入到表中的系统的位置将非法值转换为零。

通过上面的转换,你迫使Postgres为每个查询中的每一行重复地转换这些值 – 如果你在这个表中对这个列进行大量的查询,这会严重降低性能。

这也应该做这个工作,但这是横跨SQL,而不是postgres具体。

 select avg(cast(mynumber as numeric)) from my table