在PostgreSQL中,我有一个带varchar列的表。数据应该是整数,我在查询中需要整数类型。有些值是空字符串。 以下内容:
SELECT myfield::integer FROM mytable
收益ERROR: invalid input syntax for integer: ""
如何在postgres中投射期间查询演员表并且出现错误时为0?
答案 0 :(得分:137)
我自己只是在解决类似问题,但不想要功能的开销。我提出了以下问题:
SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$';
Postgres快捷键其条件,所以你不应该得到任何非整数命中你的::整数。它还处理NULL值(它们与正则表达式不匹配)。
如果你想要零而不是不选择,那么CASE语句应该有效:
SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable;
答案 1 :(得分:84)
你也可以创建自己的转换函数,可以使用异常块:
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;
测试:
=# 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)
答案 2 :(得分:24)
我有同样的需求,发现这对我有用(postgres 8.4):
CAST((COALESCE(myfield,'0')) AS INTEGER)
要演示的一些测试用例:
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”这样的text / varchar值也会给出数字
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
为了解决Chris Cogdon对解决方案的关注,不解决所有情况,包括诸如“坏”(完全没有数字字符)之类的情况,我做了这个调整后的陈述:
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
它的工作方式类似于更简单的解决方案,除非转换的值仅为非数字字符时给出0,例如“bad”:
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)
答案 3 :(得分:18)
这可能有点像黑客,但它完成了我们的工作:
(0 || myfield)::integer
解释(在Postgres 8.4上测试):
对于空字符串,上面提到的表达式为NULL
和myfield
中的NULL值产生0
(这种确切的行为可能适合您的用例,也可能不适合您的用例)。
SELECT id, (0 || values)::integer from test_table ORDER BY id
测试数据:
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 |
---------------------
而仅选择values::integer
将导致错误消息。
希望这有帮助。
答案 4 :(得分:3)
SELECT CASE WHEN myfield="" THEN 0 ELSE myfield::integer END FROM mytable
我从未使用过PostgreSQL,但我在manual检查了SELECT查询中IF语句的正确语法。
答案 5 :(得分:3)
@Matthew's answer很好。但它可以更简单,更快捷。问题要求将空字符串(''
)转换为0
,而不是其他“无效输入语法”或“超出范围”输入:
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;
这会返回0
表示空字符串,NULL
表示任何其他无效输入
它可以轻松适应 任何数据类型转换。
输入例外程序块要贵得多。如果空字符串是 common ,则在引发异常之前捕获该情况是有意义的 如果空字符串非常罕见,则将测试移至异常子句是值得的。
答案 6 :(得分:1)
CREATE OR REPLACE FUNCTION parse_int(s TEXT) RETURNS INT AS $$
BEGIN
RETURN regexp_replace(('0' || s), '[^\d]', '', 'g')::INT;
END;
$$ LANGUAGE plpgsql;
如果输入字符串中没有数字,则此函数将始终返回0
。
SELECT parse_int('test12_3test');
将返回123
答案 7 :(得分:1)
我发现以下代码简单易用。原始答案在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)
希望有所帮助
答案 8 :(得分:1)
SUBSTRING在某些情况下可能会有所帮助,您可以限制int的大小。
SELECT CAST(SUBSTRING('X12312333333333', '([\d]{1,9})') AS integer);
答案 9 :(得分:1)
最后,我设法忽略了无效字符并只获取数字以将文本转换为数字。
SELECT (NULLIF(regexp_replace(split_part(column1, '.', 1), '\D','','g'), '')
|| '.' || COALESCE(NULLIF(regexp_replace(split_part(column1, '.', 2), '\D','','g'),''),'00')) AS result,column1
FROM (VALUES
('ggg'),('3,0 kg'),('15 kg.'),('2x3,25'),('96+109'),('1.10'),('132123')
) strings;
答案 10 :(得分:0)
如果数据应该是整数,并且您只需要将这些值作为整数,为什么不进行整个步骤并将列转换为整数列?
然后,您可以在将数据插入表格的系统中将非法值转换为零一次。
通过上述转换,您强制Postgres为该表的每个查询中的每一行反复转换这些值 - 如果您对此表中的此列执行大量查询,这会严重降低性能。
答案 11 :(得分:0)
我也有同样的需求,但适用于JPA 2.0和Hibernate 5.0.2:
SELECT p FROM MatchProfile p WHERE CONCAT(p.id, '') = :keyword
创造奇迹。我认为它也适用于LIKE。
答案 12 :(得分:0)
以下功能可以
error_result
),例如abc
或999999999999999999999999999999999999999999
null
保留为null
bigints
的值与lower_bound
进行比较,例如仅强制使用正值CREATE OR REPLACE FUNCTION cast_to_bigint(text)
RETURNS BIGINT AS $$
DECLARE big_int_value BIGINT DEFAULT NULL;
DECLARE error_result BIGINT DEFAULT -1;
DECLARE lower_bound BIGINT DEFAULT 0;
BEGIN
BEGIN
big_int_value := CASE WHEN $1 IS NOT NULL THEN GREATEST(TRIM($1)::BIGINT, lower_bound) END;
EXCEPTION WHEN OTHERS THEN
big_int_value := error_result;
END;
RETURN big_int_value;
END;
答案 13 :(得分:-3)
这也可以完成这项工作,但这是跨越SQL而不是特定于postgres。
select avg(cast(mynumber as numeric)) from my table