函数内的时间戳比较

Timestamp Comparison within Function

为了防止旧版本覆盖新版本,在这个简单的函数中:

create function myupdate(paramts timestamp without time zone, ...)
  language plpgsql AS
$$
begin
-- step 1 compare current record timestamp vs. supplied timestamp
if exists (select 1 from record where ts <> paramts and ...) then
    raise exception 'A newer version exists, cannot update.';
end if;
...
end
$$;

ts定义相同timestamp without time zone.

paramts 值由函数提供:

create function myfetch(...)
  language plpgsql AS
$$
begin
    return query select ts, ... from record where ...;
end
$$;

节点API和Angular客户端UI得到的是2021-04-16T21:37:35.878Z值也是提交给 myupdate()。但是,在我们的一台西海岸服务器上,在 myupdate() 内部执行期间,ts 会自动转换为 PST 2021-04-16 14:37:35.878694 并且右边多了 3 个数字。

如何在 UTC 和相同精度下进行比较?

您应该使用 timestamptz (timestamp with time zone) 而不是 timestamp (timestamp without time zone) 以避免任何时区混淆.在table中,在函数中,在整个食物链中。值始终在内部存储为 UTC 时间,并且比较会自动正确工作(比较独立于时区的时间点)。

参见:

  • Ignoring time zones altogether in Rails and PostgreSQL

无论哪种方式,两种类型都具有 微秒 分辨率,即 6 小数位数。您的第一个示例以某种方式被截断了,可能是您的客户在显示中截断了。

完整答案如下:

  1. 使用 tz = 时间戳 with 时区定义列。
  2. tz 总是为客户提供 UTC 值,例如我正在使用 node/pg-promise,前端是 Angular/TS,它们都得到像 2021-04-17T22:42:57.610Z 这样的值。
  3. UTC 输出,UTC 提交回来(假设您不触及时间戳),是否足够好?是和否。如果您的客户端支持 6 位数字 十进制秒,则可以,否则对于 JavaScript 及其变体不支持,因为它仅支持 3 位数字。
  4. 解决办法是四舍五入到两位数然后比较

if (select tableTimestamp::timestamp(2) = parameter::timestamp(2) from mytable where ...) then Update mytable ...; else raise exception ...; end if;

P.S., withwithout time zone 令人困惑。