转换时函数 error/failure 上的 Postgres return 空值
Postgres return null values on function error/failure when casting
我正在尝试将 text
值转换为 timestamp
值。
对于以下 table 调用 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
我正在尝试使用 cast 执行 select
,如下所示:
select id, c1,
c1::timestamp
as c2 from a;
如果只有前 5 行,这可以正常工作,但对于 c1
为 24-04-89 2:33 am
的第 6 行,它会抛出以下错误:
ERROR: date/time field value out of range: "24-04-89 2:33 am"
HINT: Perhaps you need a different "datestyle" setting.
我想要的是 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
可以这样使用:
select id, c1,
set_null_on_error(c1::timestamp)
as c2 from a;
或
select id, c1,
set_null_on_error(to_number(c1, '99'))
as c2 from a;
这可以通过在 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)
。呼叫
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']);
在我看来,这样的解决方案过于复杂,使用起来很不方便,而且通常会产生难以调试的问题。
我正在尝试将 text
值转换为 timestamp
值。
对于以下 table 调用 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
我正在尝试使用 cast 执行 select
,如下所示:
select id, c1,
c1::timestamp
as c2 from a;
如果只有前 5 行,这可以正常工作,但对于 c1
为 24-04-89 2:33 am
的第 6 行,它会抛出以下错误:
ERROR: date/time field value out of range: "24-04-89 2:33 am"
HINT: Perhaps you need a different "datestyle" setting.
我想要的是 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)
编辑:
另外,有没有通用的方法来实现这个?即:(基于 null
。
例如:函数 set_null_on_error
可以这样使用:
select id, c1,
set_null_on_error(c1::timestamp)
as c2 from a;
或
select id, c1,
set_null_on_error(to_number(c1, '99'))
as c2 from a;
这可以通过在 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)
。呼叫
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']);
在我看来,这样的解决方案过于复杂,使用起来很不方便,而且通常会产生难以调试的问题。