Answers:
我本人只是在努力解决类似的问题,但不想增加函数的开销。我想出了以下查询:
SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$';
Postgres缩短了它的条件条件,因此您不应让:: integer演员遇到任何非整数。它还处理NULL值(它们与regexp不匹配)。
如果您想要零而不是不选择,那么CASE语句应该起作用:
SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable;
E'\\d{1,5}$'
。
{1,5}
如果您担心溢出,则@Bobort 在数字上的限制可能是个好主意,但它将掩盖较大的数字,如果要转换表,可能会造成麻烦。就我个人而言,我宁愿预先提出查询错误,并且知道我的某些“整数”是棘手的(您也可以先选择with E'\\d{6,}$'
来确保)。
您还可以创建自己的转换函数,在其中可以使用异常块:
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)
INSERT
声明中?
我有同样的需求,发现这对我很有效(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)
然后,文本/ varchar值(例如“ b3ad5”)也会给出数字
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
为了解决克里斯·科格登(Chris Cogdon)的关注,即在所有情况下(包括“坏”(根本没有数字字符))都不给0的解决方案,我做了以下调整后的语句:
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
它的工作方式与较简单的解决方案相似,不同之处在于,当要转换的值仅是非数字字符(例如“坏”)时将给出0:
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)
这可能有点骇人听闻,但在我们的案例中它完成了工作:
(0 || myfield)::integer
说明(在Postgres 8.4上测试):
上述表达产量NULL
为NULL值myfield
和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
将导致错误消息。
希望这可以帮助。
SELECT CASE WHEN myfield="" THEN 0 ELSE myfield::integer END FROM mytable
我以前从未使用过PostgreSQL,但是我检查了手册中SELECT查询中IF语句的正确语法。
@Matthew的回答很好。但是它可以更简单,更快。问题要求将空字符串(''
)转换为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
任何其他无效输入。
它可以轻松地适应任何数据类型转换。
输入异常块实际上要贵得多。如果常见的是空字符串,则在引发异常之前捕获该情况是有意义的。
如果空字符串非常罕见,则需要将测试移至exception子句。
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
我发现以下代码简单且有效。原始答案在这里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对该表的每个查询中的每一行一次又一次地转换这些值-如果您对此表中的该列进行大量查询,则可能严重降低性能。
以下功能
error_result
不可浇注结果EG)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;