【问题标题】:PostgreSQL timestamp/numeric precision ignored on function parameter?PostgreSQL时间戳/数字精度在函数参数上被忽略了吗?
【发布时间】:2015-02-05 10:32:45
【问题描述】:

给定以下 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;

您是否希望这些函数的输出按照函数参数中声明的类型显示结果?

我很惊讶地发现,尽管参数类型限制了精度,但精度仍然保留并显示在“通知”中。

这是一个错误还是我只是想错了?

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

【问题讨论】:

  • 它也会影响sql 函数。我在手册中没有找到任何对此的直接引用,但 sizing casts 仅在 Type Conversion 章节的Value Storage 部分中提到;这向我表明,只有在表格的列上(或者如果您使用显式大小调整,就像您尝试过的那样)时,才应用比例/精度。
  • 感谢波兹和尼克。无论如何,我已经给他们发了一封电子邮件,只是提到它可能应该被记录下来。

标签: database postgresql stored-procedures postgresql-9.3


【解决方案1】:

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

如果你向 Postgres 询问函数的定义,原因就很清楚了;在 psql 中运行 \sf fn_numSELECT 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) ...

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

【讨论】:

  • 谢谢你,它教会了我一些我不知道的东西:-)
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多