Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法在PostgreSQL查询中定义命名常量?_Sql_Postgresql - Fatal编程技术网

有没有办法在PostgreSQL查询中定义命名常量?

有没有办法在PostgreSQL查询中定义命名常量?,sql,postgresql,Sql,Postgresql,有没有办法在PostgreSQL查询中定义命名常量?例如: MY_ID = 5; SELECT * FROM users WHERE id = MY_ID; 这个问题以前有人问过。但是,我有时会在查询时使用一个技巧: with const as ( select 1 as val ) select . . . from const cross join <more tables> 也就是说,我定义了一个名为const的CTE,其中定义了常量。然后,我可以在任何级

有没有办法在PostgreSQL查询中定义命名常量?例如:

MY_ID = 5;
SELECT * FROM users WHERE id = MY_ID;

这个问题以前有人问过。但是,我有时会在查询时使用一个技巧:

with const as (
    select 1 as val
)
select . . .
from const cross join
     <more tables>

也就是说,我定义了一个名为const的CTE,其中定义了常量。然后,我可以在任何级别多次将其交叉连接到我的查询中。我发现这在处理日期时特别有用,需要处理多个子查询中的日期常量。

PostgreSQL没有内置的方法来定义MySQL或Oracle等全局变量。有一个有限的解决办法使用。根据您的具体需求,还有其他方法:

一个问题 您可以在like中的查询顶部提供值

全局持久常数: 您可以为此创建一个简单的不可变函数:

CREATE FUNCTION public.f_myid()
  RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT 5';
设置仅适用于Postgres 9.6或更高版本

它必须位于当前用户可见的模式中,即位于相应的搜索路径中。默认情况下,与公共模式类似。如果存在安全问题,请确保它是搜索路径中的第一个架构,或在调用中对其进行模式限定:

SELECT public.f_myid();
对数据库中允许访问公共架构的所有用户可见

当前会话的多个值: 由于plpgsql在创建时检查表的存在性,因此在创建函数之前需要创建临时表val,即使在会话结束时临时表被删除,而函数仍然存在。如果在调用时未找到基础表,函数将引发异常

默认情况下,临时对象的当前模式位于搜索路径的其余部分之前-如果没有明确指示,则为。不能从搜索路径中排除临时架构,但可以先放置其他架构。 拥有必要特权的夜间邪恶生物可能会修补搜索路径,并将另一个同名物体放在前面:

CREATE TABLE myschema.val (val_id int PRIMARY KEY, val text);
INSERT INTO val(val_id, val) VALUES (2, 'wrong');

SET search_path = myschema, pg_temp;

SELECT f_val(2);  -- returns 'wrong'
这不是什么威胁,因为只有特权用户才能更改全局设置。其他用户只能在自己的会话中执行此操作。请参阅手册上的相关章节

硬连线模式通常更简单、更快:

CREATE FUNCTION f_val(_id int)
  RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
'SELECT val FROM pg_temp.val WHERE val_id = $1';
提供更多选项的相关答案:


除了Gordon和Erwin已经提到的合理选项temp tables、常量返回函数、CTE等,您还可以滥用PostgreSQL GUC机制来创建全局、会话和事务级别的变量

请参阅详细显示该方法的部分


我不建议在一般情况下使用它,但它可能在狭窄的情况下很有用,如链接问题中提到的情况,海报希望找到一种方法为触发器和函数提供应用程序级用户名。

我发现了这个解决方案:

with vars as (
    SELECT * FROM (values(5)) as t(MY_ID)
)
SELECT * FROM users WHERE id = (SELECT MY_ID FROM vars)

我发现以下几种可用方法是最好的:

将变量存储在表中: 创建表变量 id INT NOT NULL主键默认值1, zipcode INT NOT NULL默认值90210, -等等。。 检查id=1 ; 创建一个动态函数,用于加载表的内容,并使用它来: 重新/创建另一个单独的静态不可变getter函数。 创建函数generate\u var\u getter 返回VOID作为$$ 声明 变量名称文本; var_值文本; 新的_行文本[]; 新的sql文本; 开始 对于中的var_名称 选择columns.column\u name 从信息_schema.columns 其中columns.table_schema='public' 和columns.table_name='vars' 按列排序。顺序位置ASC 环 处决 格式为“从变量限制1中选择%I”,变量名称 转化为var_值; 新的\u行:=数组\u追加 新行, 格式“%s,%s”,变量名称,变量值 ; 端环; new_sql:=格式$sql$ 在文本中创建或替换函数var_getkey_ 以$config的形式返回文本$ 声明 结果数字; 开始 结果:= 从值%s中选择值 作为vars_tmp键,值 其中key=key\u in ; 返回结果; 终止 $config$LANGUAGE plpgsql不可变; $sql$,数组_到_STRINGnew_行,','; 执行新的sql; 回来 终止 $$语言plpgsql; 在表中添加一个更新触发器,以便在更改一个变量后,调用generate\u var\u getter,并重新创建不可变的var\u get函数。 创建函数变量\u重新生成\u更新 将触发器返回为$$ 开始 执行generate_var_getter; 返回NULL; 终止 $$语言plpgsql; 创建触发器触发器变量重新生成更改 插入或更新变量后 执行函数vars\u renate\u update; 现在,您可以轻松地将变量保存在一个表中,但也可以获得对它们的快速不可变访问。两全其美:

插入变量的默认值; -插入0 1 选择var_get'zipcode'::INT; - 90210 更新变量集zipcode=84111; -更新1 选择var_get'zipcode'::INT; - 84111
再来一点背景怎么样?你在玩儿吗
在psql中,试图避免反复记住或计算某些内容?或者您正在为某些东西编写SQL脚本?范围应该是什么?交易一场对于集群中的一个用户/所有用户/一个数据库/所有数据库?我真的只是在寻找一种简单的方法,使我的SQL查询在将来更容易更改。与其把5放在整个查询的一堆地方,我宁愿定义我的_ID,然后在需要时更改它。使用vars作为SELECT*FROM values 5作为tMY_ID可以简化为使用vars MY_ID作为values 5这很有效。但这真的是博士后最好的吗?我使用的是只读数据库,因此无法编写函数。如果我使用这个解决方案,我将不得不为复杂的查询编写许多交叉连接。我只想设置一个变量,然后忘记@萨姆斯布兰德。交叉连接不应影响性能。CTE只有一行。如何对常量列表使用此方法。类似于:``常数为1,4,3,6517为VAL``我试过了,但没有成功。@bappak。常数为1时,选择1作为值1,选择4作为值2。谢谢@GordonLinoff。这对我来说不起作用,因为用例要求整个列表只有一个名称,这样列表就可以在主查询中使用,比如:select。。。其中foobar位于从constVery选择VAL的位置。对于生产使用,我们还可以添加适当的授权,以确保vars表不会意外更新。或者可能为常量实现一个只读标志,这些常量将在设计时固定,但这需要一个多行vars表。
with vars as (
    SELECT * FROM (values(5)) as t(MY_ID)
)
SELECT * FROM users WHERE id = (SELECT MY_ID FROM vars)