sil*_*iot 117 sql postgresql casting
在PostgreSQL中,我有一个带varchar列的表.数据应该是整数,我在查询中需要整数类型.有些值是空字符串.下列:
SELECT myfield::integer FROM mytable
Run Code Online (Sandbox Code Playgroud)
产量 ERROR: invalid input syntax for integer: ""
如何在postgres中投射期间查询演员并且在出现错误时为0?
Ant*_*ggs 151
我自己只是在解决类似的问题,但不想要一个函数的开销.我想出了以下查询:
SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$';
Run Code Online (Sandbox Code Playgroud)
Postgres会快速调整其条件,因此你不应该让任何非整数命中你的::整数.它还处理NULL值(它们与regexp不匹配).
如果你想要零而不是不选择,那么CASE语句应该有效:
SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable;
Run Code Online (Sandbox Code Playgroud)
Mat*_*ood 89
您还可以创建自己的转换函数,在其中可以使用异常块:
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;
Run Code Online (Sandbox Code Playgroud)
测试:
=# 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)
Run Code Online (Sandbox Code Playgroud)
ghb*_*att 26
我有同样的需求,发现这对我有用(postgres 8.4):
CAST((COALESCE(myfield,'0')) AS INTEGER)
Run Code Online (Sandbox Code Playgroud)
一些测试用例来演示:
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"
Run Code Online (Sandbox Code Playgroud)
如果需要处理字段具有非数字文本的可能性(例如"100bad"),则可以使用regexp_replace在强制转换之前删除非数字字符.
CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER)
Run Code Online (Sandbox Code Playgroud)
然后像"b3ad5"这样的text/varchar值也会给出数字
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
Run Code Online (Sandbox Code Playgroud)
为了解决Chris Cogdon对解决方案的关注,不解决所有情况,包括诸如"坏"(完全没有数字字符)之类的情况,我做了这个调整后的声明:
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
Run Code Online (Sandbox Code Playgroud)
它的工作方式类似于更简单的解决方案,除非转换的值仅为非数字字符时给出0,例如"bad":
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)
Run Code Online (Sandbox Code Playgroud)
Mat*_*att 20
这可能有点像黑客,但它在我们的案例中完成了工作:
(0 || myfield)::integer
Run Code Online (Sandbox Code Playgroud)
解释(在Postgres 8.4上测试):
上面提到的表达式产生空字符串和空字符串中的NULL
NULL值(这种确切的行为可能适合您的用例,也可能不适合您的用例).myfield
0
SELECT id, (0 || values)::integer from test_table ORDER BY id
Run Code Online (Sandbox Code Playgroud)
测试数据:
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');
Run Code Online (Sandbox Code Playgroud)
该查询将产生以下结果:
---------------------
|1|null |NULL|
|2|empty string|0 |
|3|one |1 |
---------------------
Run Code Online (Sandbox Code Playgroud)
而选择仅values::integer
会导致错误消息.
希望这可以帮助.
@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;
Run Code Online (Sandbox Code Playgroud)
这将返回0
空字符串和NULL
任何其他无效输入。
它可以很容易地适应任何数据类型转换。
进入异常块的成本要高得多。如果空字符串很常见,那么在引发异常之前捕获这种情况是有意义的。
如果空字符串非常罕见,则将测试移至异常子句是值得的。
归档时间: |
|
查看次数: |
169278 次 |
最近记录: |