如何将一个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