search_path如何影响标识符解析和“当前模式”?

发布于 2024-12-29 20:06:18 字数 202 浏览 7 评论 0原文

是否可以定义默认在哪个模式中创建新表? (由“不合格的表名”引用。)

我已经看到了有关在 Postgres 中使用“搜索路径”的一些详细信息,但我认为它只在检索数据时起作用,而不是在创建数据时起作用。

我有一堆 SQL 脚本,它们创建了许多表。我不想修改脚本,而是想默认设置数据库在特定模式中创建表 - 当它们具有不合格的名称时。

这可能吗?

Is it possible to define in which schema new tables get created by default? (Referred by "unqualified table names".)

I've seen some details about using the "search path" in Postgres, but I think it only works while retrieving data, not creating.

I have a bunch of SQL scripts, which create many tables. Instead of modifying the scripts, I want to set the database create tables in a specific schema by default - when they have unqualified names.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月蹉跎了容颜 2025-01-05 20:06:18

什么是架构搜索路径 search_path

手册:

[...] 表通常由非限定名称引用,其中包括
只是表名。系统确定哪个表是指
遵循搜索路径,该路径是要查找的架构列表

大胆强调我的。这解释了标识符解析

“当前架构”(或“默认架构”)是每个文档:

搜索路径中命名的第一个架构称为当前架构
架构。除了是第一个搜索模式之外,它也是
如果使用 CREATE TABLE 命令,将在其中创建新表的架构
未指定架构名称。


大胆强调我的。系统架构 pg_temp (当前会话临时对象的架构)和 pg_catalog 自动成为搜索的一部分路径并按此顺序首先进行搜索。 手册:

pg_catalog 始终是搜索路径的有效部分。如果不是
在路径中显式命名,然后之前隐式搜索它
搜索路径的模式。这确保内置名称将
总是可以找到的。但是,您可以显式地将 pg_catalog 放置在
如果您希望使用用户定义的名称,则位于搜索路径的末尾
覆盖内置名称。

按照原文加粗强调。并且 pg_temp 位于此之前,除非将其放在不同的位置。

怎么设置呢?

有多种方法可以设置运行时变量 search_path - 或任何运行时变量。

  1. 在配置文件中为所有数据库中的所有角色设置集群范围的默认值postgresql.conf (并重新加载)。小心一点!

     search_path = 'blarg,public'
    

    此设置的出厂默认值< /a> 是:

     search_path = "$user",public
    

    注意:


    <块引用>

    第一个元素指定与
    要搜索当前用户。如果不存在这样的架构,则忽略该条目。

    还有:

    <块引用>

    如果列表项之一是特殊名称 $user,则架构
    如果存在,则替换为 CURRENT_USER 返回的名称
    这样的模式,并且用户拥有它的 USAGE 权限。 (如果不,
    $user 被忽略。)


  2. 使用 ALTER SYSTEM 从 Postgres 内部执行相同操作(Postgres 12 或更高版本)。 手册:

ALTER SYSTEM 将给定的参数设置写入
postgresql.auto.conf 文件,除了读取
postgresql.conf.

  1. 将其设置为一个数据库的默认值:

     ALTER DATABASE test SET search_path = blarg,public;
    
  2. 将其设置为您连接的角色的默认值(集群范围内有效):

     ALTER ROLE foo SET search_path = blarg,public;
    
  3. 甚至(通常是最好的!)作为数据库中的角色的默认值:

     ALTER ROLE foo IN DATABASE test SET search_path = blarg,public;
    
  4. 在脚本顶部编写命令。或者在您的数据库会话中执行它:

     SET search_path = blarg,public;
    
  5. 函数范围设置特定的search_path(以防止恶意用户使用足够的权限)。了解编写SECURITY DEFINER手册中的安全功能

    创建函数 foo()
      退货无效
      语言 plpgsql 安全定义器 SET search_path=blarg,public,pg_temp
      作为
    $函数$
    开始
       ——做事
    结尾
    $func$;

列表中较高的数字胜过较低的数字。
手册有更多的方法,例如设置环境变量或使用命令行选项。

如何检查当前设置?

检查配置文件 postgresql.conf(和 postgresql.auto.conf)。或者(更方便)使用系统视图 pg_file_settings< /code>,它总结了所有配置文件的内容:

SELECT * FROM pg_file_settings WHERE name = 'search_path';

要查看会话中的当前设置:

SHOW search_path;

或从系统视图中获取完整信息pg_settings

SELECT * FROM pg_settings WHERE name = 'search_path';

每个角色/数据库的设置存储在系统目录中 pg_db_role_setting(默认情况下无)。检查:

SELECT d.datname AS database, setrole::regrole AS role, s.setconfig
FROM   pg_db_role_setting s
JOIN   pg_database d ON d.oid = s.setdatabase
WHERE  s.setconfig::text ~ 'search_path';

如何重置?

重置

RESET search_path;

重置: postgresql.org/docs/current/sql-reset.html" rel="nofollow noreferrer">手册:

默认值定义为参数将要使用的值
如果在当前会话中没有为其发出SET,则已经有过。

如何知道这将重置为什么?

SELECT reset_val FROM pg_settings WHERE name = 'search_path';

reset_val 文本
RESET 将在当前会话中将参数重置为的值

在更改之前保存当前状态(可能与重置值不同)首先,SET 将其恢复到该状态(而不是RESET)。有一个方便的函数 set_config() 接受一个变量,而不是SET。示例 PL/pgSQL 代码块:

DO
$do$
DECLARE
   _org_search_path text := current_setting('search_path');
BEGIN
   SET search_path = public, pg_temp;
   -- do stuff
   PERFORM set_config('search_path', _org_search_path, true);
END;
$do$

使用 设置本地。这会持续到当前事务结束,这可能会超过函数的结束。细微差别!

What is the schema search path search_path?

The manual:

[...] tables are often referred to by unqualified names, which consist
of just the table name. The system determines which table is meant by
following a search path, which is a list of schemas to look in.

Bold emphasis mine. This explains identifier resolution.

The “current schema” (or “default schema”) is, per documentation:

The first schema named in the search path is called the current
schema
. Aside from being the first schema searched, it is also the
schema in which new tables will be created if the CREATE TABLE command
does not specify a schema name.

Bold emphasis mine. The system schemas pg_temp (schema for temporary objects of the current session) and pg_catalog are automatically part of the search path and searched first, in this order. The manual:

pg_catalog is always effectively part of the search path. If it is not
named explicitly in the path then it is implicitly searched before
searching the path's schemas. This ensures that built-in names will
always be findable. However, you can explicitly place pg_catalog at
the end of your search path if you prefer to have user-defined names
override built-in names.

Bold emphasis as per original. And pg_temp comes before that, unless it's put into a different position.

How to set it?

There are various ways to set the runtime variable search_path - or any runtime variable, for that matter.

  1. Set a cluster-wide default for all roles in all databases in the configuration file postgresql.conf (and reload). Careful with that!

     search_path = 'blarg,public'
    

    The factory default for this setting is:

     search_path = "$user",public
    

    Note:

    The first element specifies that a schema with the same name as the
    current user is to be searched. If no such schema exists, the entry is ignored.

    And:

    If one of the list items is the special name $user, then the schema
    having the name returned by CURRENT_USER is substituted, if there is
    such a schema and the user has USAGE permission for it. (If not,
    $user is ignored.)

  2. Do the same from inside Postgres with ALTER SYSTEM (Postgres 12 or later). The manual:

ALTER SYSTEM writes the given parameter setting to the
postgresql.auto.conf file, which is read in addition to
postgresql.conf.

  1. Set it as default for one database:

     ALTER DATABASE test SET search_path = blarg,public;
    
  2. Set it as default for the role you connect with (effective cluster-wide):

     ALTER ROLE foo SET search_path = blarg,public;
    
  3. Or even (often best!) as default for a role in a database:

     ALTER ROLE foo IN DATABASE test SET search_path = blarg,public;
    
  4. Write the command at the top of your script. Or execute it in your DB session:

     SET search_path = blarg,public;
    
  5. Set a specific search_path for the scope of a function (to be safe from malicious users with sufficient privileges). Read about Writing SECURITY DEFINER Functions Safely in the manual.

    CREATE FUNCTION foo()
      RETURNS void
      LANGUAGE plpgsql SECURITY DEFINER SET search_path=blarg,public,pg_temp
      AS
    $func$
    BEGIN
       -- do stuff
    END
    $func$;

Higher number in the list trumps lower number.
The manual has even more ways, like setting environment variables or using command-line options.

How check current settings?

Inspect the configuration file(s) postgresql.conf (and postgresql.auto.conf). Or (more conveniently) use the system view pg_file_settings, which summarizes the contents of all configuration files:

SELECT * FROM pg_file_settings WHERE name = 'search_path';

To see the current setting in your session:

SHOW search_path;

Or get complete information from the system view pg_settings:

SELECT * FROM pg_settings WHERE name = 'search_path';

Settings per role / database are stored in the system catalog pg_db_role_setting (none by default). To check:

SELECT d.datname AS database, setrole::regrole AS role, s.setconfig
FROM   pg_db_role_setting s
JOIN   pg_database d ON d.oid = s.setdatabase
WHERE  s.setconfig::text ~ 'search_path';

How reset it?

To reset:

RESET search_path;

The manual:

The default value is defined as the value that the parameter would
have had, if no SET had ever been issued for it in the current session.

How to know what this will reset to?

SELECT reset_val FROM pg_settings WHERE name = 'search_path';

reset_val text
Value that RESET would reset the parameter to in the current session

Or save the current state (which may differ from the reset value) before you change it in the first place, and SET it back to that state (rather than RESET). There is the convenient function set_config() taking a variable, as opposed to SET. Example PL/pgSQL code block:

DO
$do$
DECLARE
   _org_search_path text := current_setting('search_path');
BEGIN
   SET search_path = public, pg_temp;
   -- do stuff
   PERFORM set_config('search_path', _org_search_path, true);
END;
$do$

Or use SET LOCAL. That lasts till the end of the current transaction, which may be past the end of a function. Subtle difference!

淡水深流 2025-01-05 20:06:18

搜索路径确实是你想要的:

% 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

Search path is indeed what you want:

% 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文