CREATE TABLE usertime(
username text PRIMARY KEY -- careful, "user" is a reserved word
, timezone text -- ... but "timezone" is not
);
INSERT INTO usertime VALUES
('postgres', '+4')
, ('my_role' , '+3')
;
编写一个小型SQL函数:
CREATE FUNCTION f_user_ts()
RETURNS timestamp
LANGUAGE sql STABLE AS
$func$
SELECT now() AT TIME ZONE u.timezone
FROM usertime u
WHERE u.username = current_user
$func$;
3条答案
按热度按时间jk9hmnmh1#
首先,考虑数据类型
timestamptz
(timestamp with time zone
)而不是timestamp
(timestamp without time zone
)。然后用户的时区就不重要了。now()
返回timestamptz
,您的问题源于将其强制为timestamp
。请参阅:“但我需要
timestamp
类型!"如果您的连接与**可绑定到时区的数据库角色(登录)**发生关联,则PostgreSQL提供了一个简单的解决方案:
使用此角色启动的每个连接都将在其预设时区中自动运行(除非另有说明)。
请注意,quoting the manual:
这只在登录时发生;执行
SET ROLE
或SET SESSION AUTHORIZATION
不会导致设置新的配置值。您可能希望使用 * 时区名称 * 而不是纯偏移量来遵循DST规则和其他对当地时间的政治操纵。更多信息:
或者,您可以为您的登录创建一个查找表,在其中存储相应的时区(可能用于其他用途):
编写一个小型SQL函数:
现在,这将返回当前角色(用户)的本地时间戳:
更多信息
请参阅
AT TIME ZONE
构造的详细手册。以下两种语法变体都是有效的:但
now() AT TIMEZONE foo;
不是!它必须是:foo
是text
变量(或类似于上述函数中的列),包含时区偏移量、缩写或名称。您也可以直接提供字符串文字。vcudknz32#
在SQL中,
若要获取时区的名称,请使用
lrpiutwd3#
这只是一个很长的机会,但是如果您设置了所使用的角色的时区会怎么样呢?