在PostgreSQL函数中如何设置时区

3
CREATE OR REPLACE FUNCTION myfunction(userid BIGINT)
  RETURNS REAL
  SECURITY DEFINER
LANGUAGE plpgsql
AS $$
DECLARE
  ------------------------Fetch all Active Games for a user and add it to one cursor--------------------------------------
    PersonGames NO SCROLL CURSOR FOR select timezonename from user where id=userid;
BEGIN
  OPEN PersonGames;
  LOOP

    FETCH PersonGames INTO PersonGame;
    IF NOT found
    THEN
      EXIT;
    END IF;
    SET TIMEZONE=PersonGame.timezonename;
  --  execute 'set TIMEZONE=$1' using PersonGame.timezonename;
end loop;
END;
$$;

我得到了一个错误:“TimeZone”的参数值无效:“timezonename”

即使我尝试使用PersonGame.timezonename执行“set TIMEZONE=$1”更改代码,但这也没有起作用。

我想在我的函数内设置时区。

非常感谢任何帮助。

谢谢


  1. 为什么要更改Postgres数据库的时区?这个设置适用于整个数据库。
  2. 语法是SET TIME ZONE value请参阅文档)。
- Kristo Mägi
我有一个需求,需要按用户进行。我已经尝试过了,但是没有起作用。 - deadpool
1
@KristoMägi:通过set更改时区不会应用于“整个数据库”,只会应用于当前会话。 - user330315
1个回答

3
您可以用两种不同的方式完成它:
  1. You can use the EXECUTE command, with a fully-constructed string (i.e.: without USING1), and use the SET [LOCAL] TIME ZONE statement, as you were doing in your function.

    This function will let you test it:

    CREATE OR REPLACE FUNCTION test_set_time_zone(_new_time_zone TEXT)
       RETURNS TEXT
       SECURITY DEFINER
       LANGUAGE plpgsql
    AS $$
    BEGIN
        EXECUTE 'SET LOCAL TIME ZONE ''' || _new_time_zone || ''';' ;
        RETURN current_setting('timezone')  ;
    END;
    $$;
    

    You can check it with:

    SELECT test_set_time_zone('Europe/Paris');
    
    | test_set_time_zone |
    | :----------------- |
    | Europe/Paris       |
    
  2. You can use the set_config() function in a similar fashion, being called via PERFORM, setting 'timezone' as the parameter to configure, and deciding whether to make the setting local or global.

    You can check it with:

    CREATE OR REPLACE FUNCTION test_set_time_zone_2 (_new_time_zone TEXT)
       RETURNS TEXT
       SECURITY DEFINER
       LANGUAGE plpgsql
    AS $$
    BEGIN
        PERFORM set_config('timezone', _new_time_zone, true /* local */) ;
        RETURN current_setting('timezone')  ;
    END;
    $$;
    
    SELECT test_set_time_zone_2('US/Central') ;
    
    | test_set_time_zone_2 |
    | :------------------- |
    | US/Central           |
    
您可以在此处检查这两个功能:dbfiddle 这里。我没有尝试任何全局设置,因为我猜想在这个平台上,一个Web用户将没有适当的权限;我最好的猜测是你可以在你的系统中做相应的事情来进行全局更改。
1) 根据Pavel Stehule的评论:`USING`子句仅适用于执行计划参数。`SET`没有执行计划,因此`USING`子句不可用。

2
USING子句仅适用于执行计划参数。SET没有执行计划,因此USING子句不可用。 - Pavel Stehule
是的,第二部分使用以下代码: PERFORM 'SET TIME ZONE '||时区名称; - deadpool
为什么在这里 PostgreSQL 要求使用字符串字面量? - Malachi Holden
第一个使用EXECUTE的解决方案似乎极易受到SQL注入攻击的威胁。 - Jake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接