PostgreSQL 没有内置方法来定义(全局)变量,如 MySQL 或 Oracle。 (使用"customized options" 的解决方法有限)。根据您的具体要求,还有其他方法:
对于一个查询
您可以在CTE 中的查询顶部提供值,例如@Gordon already provided。
全局持久常量:
您可以为此创建一个简单的 IMMUTABLE 函数:
CREATE FUNCTION public.f_myid()
RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT 5';
(Parallel safety 设置仅适用于 Postgres 9.6 或更高版本。)
它必须存在于对当前用户可见的架构中,即在各自的search_path 中。默认情况下,类似于架构 public。如果安全是一个问题,请确保它是 search_path 中的第一个架构或在您的调用中对其进行架构限定:
SELECT public.f_myid();
对数据库中的所有用户可见(允许访问架构public)。
当前会话的多个值:
CREATE TEMP TABLE val (val_id int PRIMARY KEY, val text);
INSERT INTO val(val_id, val) VALUES
( 1, 'foo')
, ( 2, 'bar')
, (317, 'baz');
CREATE FUNCTION f_val(_id int)
RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
'SELECT val FROM val WHERE val_id = $1';
SELECT f_val(2); -- returns 'baz'
由于 plpgsql 在创建时检查表是否存在,因此您需要在创建函数之前创建(临时)表val - 即使在会话结束时删除临时表而函数仍然存在.如果在调用时未找到基础表,该函数将引发异常。
默认情况下,临时对象的当前架构位于 search_path 的其余部分之前 - 如果没有明确指示。您不能排除 search_path 中的临时架构,但您可以先放置其他架构。
夜晚的邪恶生物(具有必要的特权)可能会修补 search_path 并将另一个同名对象放在前面:
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'
威胁不大,因为只有特权用户才能更改全局设置。其他用户只能为自己的会话执行此操作。考虑creating functions with SECURITY DEFINER上手册的相关章节。
硬连线架构通常更简单、更快:
CREATE FUNCTION f_val(_id int)
RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
'SELECT val FROM pg_temp.val WHERE val_id = $1';
更多选项的相关答案: