【问题标题】:Is it possible to define global variables in postgresql是否可以在 postgresql 中定义全局变量
【发布时间】:2015-09-27 17:51:18
【问题描述】:

我正在使用 postgresql 9.4 并且在编写函数时我想使用自定义的 error_codes (int)。不过我可能想稍后更改确切的数值
比如
-1 表示 USER_NOT_FOUND。
-2 表示 USER_DOES_NOT_HAVE_PERMISSION。

我可以在表code_table(code_name::text, code_value::integer) 中定义这些,并在如下函数中使用它们

(SELECT codes_table.code_value FROM codes_table WHERE codes_table.code_name = 'USER_NOT_FOUND')

还有其他方法吗。也许是全局变量?

【问题讨论】:

  • 只要坚持到桌子上。如果必须,可以将其封装在一个简单的 SQL 函数中。不过,真的,我认为改变这些值没什么意义,为什么不把它们变成静态的呢?
  • @CraigRinger 我们正在开发一个新系统,并将为错误代码设置格式。例如,[-9 -1] 用于权限相关错误,[-19, -10] 用于检查约束错误。但是,目前尚未设置该格式。也许一旦它被设置,以后它就会被重置。所以我想做好准备。
  • 那些不是错误代码,您返回带有RAISE EXCEPTION 的错误代码,并且相当新的版本允许您指定您提出的代码。

标签: postgresql global-variables postgresql-9.4


【解决方案1】:

@klin's answer 的基础上,有几种方法可以将配置参数保留在当前会话之外。请注意,这些需要超级用户权限。

为特定数据库的所有连接设置一个值:

ALTER DATABASE db SET abc.xyz = 1;

您还可以使用 9.4 中添加的 ALTER SYSTEM 命令设置服务器范围的值。如果用户定义的参数在当前会话中已经是SET,它似乎只适用于它们。另请注意,这需要重新加载配置才能生效。

SET abc.xyz = 1;
ALTER SYSTEM SET abc.xyz = 1;
SELECT pg_reload_conf();

在 9.4 之前,您可以通过将参数添加到服务器的 postgresql.conf 文件来完成相同的操作。在 9.1 及更早的版本中,您还需要注册一个custom variable class

【讨论】:

  • 我可以通过 SHOW abc.xyz 查看值。但是我不能在 SELECT 中使用它。如何使用它的价值?
  • 使用我回答中的函数(当然你应该更改前缀glb)。
  • 配置参数的大小是否有限制,或者在开始损害系统性能之前是否有实际限制?例如,它可以进入 100mb(在 100gb 的服务器上)吗?
【解决方案2】:

Postgres 没有全局变量。 但是,您可以定义自定义配置参数。 为了清楚起见,用给定的前缀定义你自己的参数,比如glb

这个简单的函数可以更容易地在查询中放置参数:

create or replace function glb(code text)
returns integer language sql as $$
    select current_setting('glb.' || code)::integer;
$$;

set glb.user_not_found to -1;
set glb.user_does_not_have_permission to -2;

select glb('user_not_found'), glb('user_does_not_have_permission');

用户定义的参数在会话中是本地的,因此应该在每个会话开始时定义参数。

【讨论】:

  • 这个配置参数可以完成这项工作。但是有没有办法让它们永久化(直到我改变它们)?
  • @Nuri:见ALTER SYSTEM,9.4 中的新功能
【解决方案3】:

你可以用这个

CREATE OR REPLACE FUNCTION globals.maxCities()
  RETURNS integer AS
  $$SELECT 100 $$ LANGUAGE sql IMMUTABLE;

.. 并在代码中直接使用 globals.maxCities()。

【讨论】:

    【解决方案4】:

    您可以使用技巧将变量声明为 1 行 CTE,然后将其交叉连接到其余部分。见例子:

    WITH
    variables AS (
        SELECT 'value1'::TEXT AS var1, 10::INT AS var2
    )
    SELECT t.*, v.*
    FROM
        my_table AS t
        CROSS JOIN variables AS v
    WHERE t.random_int_column = var2;
    

    【讨论】:

    • 您可以将variables CTE 简化为with variables (var1, var2, trip_type_var as (values ('value1', 'value2', 'one')) ...
    【解决方案5】:

    Postgresql 不支持数据库级别的全局变量。为什么不添加它:

    CREATE TABLE global_variables (
      key text not null PRIMARY KEY
      value text
    );
    
    INSERT INTO global_variables (key, value) VALUES ('error_code_for_spaceship_engine', '404');
    

    如果值可能是不同的类型,则将 JSON 视为 value 的类型,但每种类型都需要反序列化代码。

    【讨论】:

      猜你喜欢
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      • 2017-03-10
      • 2019-05-28
      • 1970-01-01
      相关资源
      最近更新 更多