cim*_*non 12 postgresql plpgsql catalogs
我正在为一个应用程序编写一个安装脚本,该脚本是另一个应用程序的插件,所以我想检查另一个应用程序的表是否存在。如果没有,我想给用户一个有用的错误。但是,我不知道什么模式将保存这些表。
DO LANGUAGE plpgsql $$
BEGIN
PERFORM 1
FROM
pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE
n.nspname = current_setting('search_path')
AND c.relname = 'foo'
AND c.relkind = 'r'; -- not sure if I actually need this or not...
IF NOT FOUND THEN
RAISE 'This application depends on tables created by another application';
END IF;
END;
$$;
Run Code Online (Sandbox Code Playgroud)
但是,current_setting('search_path')
返回"$user",public
默认包含的 TEXT ,这不是很有用。
我唯一能想到的另一件事是尝试从表中选择并捕获异常。它可以完成这项工作,但我认为它不是很优雅,而且我读到它使用起来很昂贵(尽管在这种情况下可能没问题,因为我只运行一次?)。
Erw*_*ter 20
在 Postgres 9.4 或更新版本中使用to_regclass()
:
SELECT to_regclass('foo');
Run Code Online (Sandbox Code Playgroud)
如果搜索路径中没有该名称的关系,则返回 NULL。
在 Postgres 9.3 或更早版本(或任何版本)中,使用强制转换来regclass
:
SELECT 'foo'::regclass;
Run Code Online (Sandbox Code Playgroud)
这引发了一个异常,如果没有找到的对象!
看:
如果'foo'
找到,oid
则返回 - 表示为文本。这是关系名称,根据当前搜索路径进行模式限定,并在必要时加双引号。
如果未找到该关系,您可以确定它不存在于搜索路径中的任何位置 - 或者根本不存在模式限定名称 ( schema.foo
)。
如果发现有两个缺点:
搜索包括search_path 的隐式模式,即pg_catalog
和pg_temp
。但是您可能希望出于您的目的排除临时表和系统表。(?)
流延到regclass
系统中的目录的发现任何关系(表状物体)pg_class
:表,索引,视图,序列等不只是一个普通的表。其他同名对象可能会产生误报。
我们回到类似于您的查询的内容。但不要使用,它会返回裸设置。使用专用的系统信息功能current_setting('search_path')
current_schemas()
。手册:
current_schemas(boolean)
name[]
搜索路径中的模式名称,可选地包括隐式模式
"$user"
在search_path
巧妙地解决。如果不存在具有当前名称的模式SESSION_USER
,则解析为空。您还可以输出隐式模式(pg_catalog
可能还有pg_temp
) - 但我假设不是手头的情况,所以:
DO
$do$
BEGIN
IF EXISTS (
SELECT -- list can be empty
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = ANY(current_schemas(FALSE))
AND n.nspname NOT LIKE 'pg_%' -- exclude system schemas!
AND c.relname = 'foo'
AND c.relkind = 'r') -- you probably need this
THEN
RAISE 'This application depends on tables created by another application';
END IF;
END
$do$;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
29978 次 |
最近记录: |