PostgreSQL timestamp/numeric 忽略函数参数的精度?
PostgreSQL timestamp/numeric precision ignored on function parameter?
给定以下 PostgreSQL 函数:
CREATE OR REPLACE FUNCTION fn_dtm (
dtm timestamptz(0))
RETURNS void AS $$
BEGIN
RAISE NOTICE 'fn: %, %', dtm, dtm::timestamptz(0);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION fn_num (
num numeric(5, 2))
RETURNS void AS $$
BEGIN
RAISE NOTICE 'num: %, %', num, num::numeric(5, 2);
END;
$$ LANGUAGE plpgsql;
您希望这些函数的输出显示函数参数中声明的类型的结果吗?
尽管参数类型限制了精度,但我很惊讶地发现精度被保留并显示在 "NOTICE" 中。
这是一个错误还是我只是想错了?
Here is the output:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:25:44.184+00, 2015-02-05 10:25:44+00
db=> SELECT fn_num(1.23456789);
NOTICE: num: 1.23456789, 1.23
我正在使用 PostgreSQL 9.3。
编辑:
如果我这样做,我会得到我期望的结果:
CREATE OR REPLACE FUNCTION fn_dtm (
dtm timestamptz(0))
RETURNS void AS $$
BEGIN
dtm = dtm::timestamptz(0); ----- CHANGE PRECISION
RAISE NOTICE 'fn: %', dtm;
END;
$$ LANGUAGE plpgsql;
给出:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:38:38+00
这可能不是您所期望的,但这就是它的工作方式。
如果您向 Postgres 询问函数的定义,原因就很清楚了; 运行 \sf fn_num
在 psql 中,或 SELECT pg_get_functiondef('fn_num'::regproc)
,它会给你:
CREATE OR REPLACE FUNCTION public.fn_num(num numeric) ...
所以当 Postgres 创建您的函数时,precision/scale 信息已经被丢弃。 Return 类型遇到同样的问题。
可以通过使用域为涉及的类型别名来解决此问题:
CREATE DOMAIN timestamptz_seconds AS timestamptz(0);
CREATE FUNCTION fn_dtm(dtm timestamptz_seconds) ...
如果您需要在结果集定义中保持精度,这对 return 类型特别有用。但在大多数情况下,正如您所指出的,您可以通过在函数体中进行一些显式转换来获得相同的结果。
给定以下 PostgreSQL 函数:
CREATE OR REPLACE FUNCTION fn_dtm (
dtm timestamptz(0))
RETURNS void AS $$
BEGIN
RAISE NOTICE 'fn: %, %', dtm, dtm::timestamptz(0);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION fn_num (
num numeric(5, 2))
RETURNS void AS $$
BEGIN
RAISE NOTICE 'num: %, %', num, num::numeric(5, 2);
END;
$$ LANGUAGE plpgsql;
您希望这些函数的输出显示函数参数中声明的类型的结果吗?
尽管参数类型限制了精度,但我很惊讶地发现精度被保留并显示在 "NOTICE" 中。
这是一个错误还是我只是想错了?
Here is the output:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:25:44.184+00, 2015-02-05 10:25:44+00
db=> SELECT fn_num(1.23456789);
NOTICE: num: 1.23456789, 1.23
我正在使用 PostgreSQL 9.3。
编辑: 如果我这样做,我会得到我期望的结果:
CREATE OR REPLACE FUNCTION fn_dtm (
dtm timestamptz(0))
RETURNS void AS $$
BEGIN
dtm = dtm::timestamptz(0); ----- CHANGE PRECISION
RAISE NOTICE 'fn: %', dtm;
END;
$$ LANGUAGE plpgsql;
给出:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:38:38+00
这可能不是您所期望的,但这就是它的工作方式。
如果您向 Postgres 询问函数的定义,原因就很清楚了; 运行 \sf fn_num
在 psql 中,或 SELECT pg_get_functiondef('fn_num'::regproc)
,它会给你:
CREATE OR REPLACE FUNCTION public.fn_num(num numeric) ...
所以当 Postgres 创建您的函数时,precision/scale 信息已经被丢弃。 Return 类型遇到同样的问题。
可以通过使用域为涉及的类型别名来解决此问题:
CREATE DOMAIN timestamptz_seconds AS timestamptz(0);
CREATE FUNCTION fn_dtm(dtm timestamptz_seconds) ...
如果您需要在结果集定义中保持精度,这对 return 类型特别有用。但在大多数情况下,正如您所指出的,您可以通过在函数体中进行一些显式转换来获得相同的结果。