search_path 如何影响标识符解析和“当前模式”
Posted
技术标签:
【中文标题】search_path 如何影响标识符解析和“当前模式”【英文标题】:How does the search_path influence identifier resolution and the "current schema" 【发布时间】:2012-02-22 10:50:16 【问题描述】:是否可以定义默认在哪个模式中创建新表? (由“不合格的表名”引用。)
我已经看到了有关在 Postgres 中使用“搜索路径”的一些细节,但我认为它只在检索数据时有效,而不是在创建时有效。
我有一堆 SQL 脚本,它们创建了许多表。我不想修改脚本,而是在默认情况下将数据库创建表设置为特定模式 - 当它们具有非限定名称时。
这可能吗?
【问题讨论】:
【参考方案1】:什么是架构搜索路径search_path
?
The manual:
[...] 表通常由非限定名称引用,这些名称包括 只是表名。系统确定哪个表是指 遵循搜索路径,这是要查看的架构列表。
我的大胆强调。这解释了标识符解析。
“当前架构”(或“默认架构”)是 per documentation:
在搜索路径中命名的第一个架构称为当前 架构。除了是第一个搜索到的模式之外,它也是 如果
CREATE TABLE
命令将在其中创建新表的架构 未指定架构名称。
我的大胆强调。系统架构 pg_temp
(当前会话的临时对象的架构)和 pg_catalog
自动成为搜索路径的一部分并被搜索首先,按此顺序。 The manual:
pg_catalog
始终是搜索路径的有效部分。如果不是 在路径中显式命名,然后在 之前 隐式搜索 搜索路径的模式。这确保了内置名称将 总是可以找到的。但是,您可以将pg_catalog
显式放置在 如果您希望使用用户定义的名称,则搜索路径的结尾 覆盖内置名称。
按照原文的粗体强调。而pg_temp
在此之前出现,除非它被放到不同的位置。
如何设置?
有多种方法可以设置运行时变量search_path
。
为postgresql.conf
中的所有数据库中的所有角色设置集群 范围的默认值(并重新加载)。小心点!
search_path = 'blarg,public'
shipped default for this setting 是:
search_path = "$user",public
第一个元素指定与 当前用户将被搜索。如果不存在这样的架构,则忽略该条目。
将其设置为一个数据库的默认值:
ALTER DATABASE test SET search_path = blarg,public;
将其设置为您连接的角色的默认值(在集群范围内有效):
ALTER ROLE foo SET search_path = blarg,public;
甚至(通常是最好的!)作为数据库中的角色的默认设置:
ALTER ROLE foo IN DATABASE test SET search_path = blarg,public;
在脚本顶部编写命令。或者在您的数据库会话中执行它:
SET search_path = blarg,public;
为函数范围设置一个特定的search_path
(以防止具有足够权限的恶意用户)。阅读手册中的Writing SECURITY DEFINER
Functions Safely。
CREATE FUNCTION foo() RETURNS void AS
$func$
BEGIN
-- do stuff
END
$func$ LANGUAGE plpgsql SECURITY DEFINER
SET search_path=blarg,public,pg_temp;
我列表中较高的数字胜过较低的数字。manual has even more ways,比如设置环境变量或者使用命令行选项。
查看当前设置:
SHOW search_path;
致reset它:
RESET search_path;
The manual:
默认值被定义为参数将 如果在当前会话中没有为它发出过
SET
,那么已经有过。
【讨论】:
我在上面的 cmets 上说的是这个 :) 感谢您向我展示这些选项 ;) +1 用于 ALTER DATABASE,不知道,非常有用:) 谢谢@Erwin。阅读您的回答后,我发现RESET search_path;
为我解决了问题。 (#6?)
@BKSpureon:blarg 只是 foo 和 bar 的丑兄弟。一个随机的名字。
请记住,在会话期间设置搜索路径可能与最理想的 pgBouncer 策略不兼容【参考方案2】:
搜索路径确实是你想要的:
% create schema blarg;
% set search_path to blarg;
% create table foo (id int);
% \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
blarg | foo | table | pgsql
【讨论】:
是的,你是对的......但你已经知道了:)。但我认为它不起作用,因为我以前尝试过,但在不同的会话中:在一个我做了 set search_path,在另一个我创建了表。我认为“set search_path”会适用于给定的数据库。我可以让它粘住吗? 顺便说一句,为了再次测试,我只是将“set search_path”放在了 sql 脚本的顶部,而不是分别做这两件事......谢谢! 您应该能够在配置文件中设置 search_path 参数,或者通过以下方式将其永久设置为用户: ALTER USERALTER DATABASE db SET search_path = ...
,甚至对于特定的用户/数据库组合(在 9.1 上):ALTER ROLE user IN DATABASE db SET search_path = ...
,但如果您过多地使用这些设置,它们可以造成混乱,并注意它们何时被丢弃尚不清楚。以上是关于search_path 如何影响标识符解析和“当前模式”的主要内容,如果未能解决你的问题,请参考以下文章