函数参数忽略PostgreSQL时间戳/数字精度?

时间:2015-02-05 10:32:45

标签: database postgresql stored-procedures postgresql-9.3

鉴于以下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

1 个答案:

答案 0 :(得分:2)

它可能不是你所期望的,但这就是它的工作方式。

如果你向Postgres询问函数的定义,原因很清楚;在psql中运行\sf fn_num,或SELECT pg_get_functiondef('fn_num'::regproc),它会给你:

CREATE OR REPLACE FUNCTION public.fn_num(num numeric) ...

因此,当Postgres创建您的函数时,精度/比例信息已被丢弃。返回类型遭遇同样的问题。

可以通过使用域来对所涉及的类型进行别名来解决此问题:

CREATE DOMAIN timestamptz_seconds AS timestamptz(0);
CREATE FUNCTION fn_dtm(dtm timestamptz_seconds) ...

如果需要保留结果集定义的精度,这对返回类型特别有用。但在大多数情况下,正如您所指出的,您可以通过函数体中的一些显式转换获得相同的结果。