我正在尝试将text值转换为timestamp值。对于下表 a :
text
timestamp
a
id | c1 ----+-------------------- 1 | 03-03-2000 2 | 01-01-2000 3 | 12/4/1990 4 | 12 Sept 2011 5 | 12-1-1999 12:33:12 6 | 24-04-89 2:33 am
我试图执行select一个 投 如下:
select
select id, c1, c1::timestampas c2 from a;
select id, c1,
c1::timestamp
as c2 from a;
这正常工作,如果有只有前5行,但第6行地方c1是24-04-89 2:33 am它引发以下错误:
c1
24-04-89 2:33 am
错误:日期/时间字段值超出范围:“ 24-04-89 2:33 am” 提示:也许您需要一个不同的“ datestyle”设置。
我想要的是 null 那些不能转换为时间戳而不是命令完全失败的值。像这样:
null
id | c1 | c2 ----+--------------------+--------------------- 1 | 03-03-2000 | 2000-03-03 00:00:00 2 | 01-01-2000 | 2000-01-01 00:00:00 3 | 12/4/1990 | 1990-12-04 00:00:00 4 | 12 Sept 2011 | 2011-09-12 00:00:00 5 | 12-1-1999 12:33:12 | 1999-12-01 12:33:12 6 | 24-04-89 2:33 am | (null) (6 rows)
编辑: 另外,有没有一种通用的方法来实现这一目标?即:一个plpgsql包装函数,该函数将值设置为null是否将其包装的函数抛出错误。例如:set_null_on_error可以像这样使用的函数:
set_null_on_error
select id, c1, set_null_on_error(c1::timestamp)as c2 from a;
set_null_on_error(c1::timestamp)
或者
select id, c1, set_null_on_error(to_number(c1, '99'))as c2 from a;
set_null_on_error(to_number(c1, '99'))
这可以通过在plpgsql函数中捕获异常来完成。
create or replace function my_to_timestamp(arg text) returns timestamp language plpgsql as $$ begin begin return arg::timestamp; exception when others then return null; end; end $$; select id, c1, my_to_timestamp(c1) as c2 from a;
试图定义一个 泛型 函数。
假设您定义了一个函数set_null_on_error(anyelement)。呼唤
set_null_on_error(anyelement)
select set_null_on_error('foo'::timestamp);
在 执行函数 之前 引发错误。
您可以尝试这样的事情:
create or replace function set_null_on_error(kind text, args anyarray) returns anyelement language plpgsql as $$ begin begin if kind = 'timestamp' then return args[1]::timestamp; elseif kind = 'number' then return to_number(args[1], args[2]); end if; exception when others then return null; end; end; $$; select set_null_on_error('timestamp', array['2014-01-01']); select set_null_on_error('number', array['1.22444', '9999D99']);
我认为这样的解决方案太复杂,使用起来非常不方便,并且通常可能会产生难以调试的问题。