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

标签 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;

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

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

这是一个错误还是我只是以错误的方式思考它?

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 询问函数的定义,原因就很清楚了;在 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) ...

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

关于database - 函数参数忽略 PostgreSQL 时间戳/数字精度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28341630/

相关文章:

php - 使用时间戳在 mysqli 中创建表

sql-server - 如何让一个事务覆盖多个存储过程?

mysql - 存储过程不在mysql中使用游标返回多行

mysql - 创建过程以在 PostgreSQL 中执行查询

mysql - 对有点复杂的 LEFT/RIGHT JOIN 查询感到困惑

database - 规范化依赖

sql - 数据库行中的标志,最佳实践

linux - 如何在 Emacs lisp/config 中使用 unix 登录用户名?

javascript - 如何在 sequelize 中按嵌套的 JSONB 属性排序

同一查询中的 PostgreSQL nextval 和 currval