运行以下查询:
SELECT exists(
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = 'public'
) as schema_exists;
即使公共架构存在,我也总是FALSE
。
我应该如何检查此架构是否存在?
修改
我正在使用PostgreSQL版本8.4
答案 0 :(得分:2)
由于您用于测试架构存在的数据库角色,我猜您无法看到公共架构。 information_schema.schemata
实际上是一个具有以下定义的视图:
SELECT
current_database()::information_schema.sql_identifier AS catalog_name,
n.nspname::information_schema.sql_identifier AS schema_name,
u.rolname::information_schema.sql_identifier AS schema_owner,
NULL::character varying::information_schema.sql_identifier AS default_character_set_catalog,
NULL::character varying::information_schema.sql_identifier AS default_character_set_schema,
NULL::character varying::information_schema.sql_identifier AS default_character_set_name,
NULL::character varying::information_schema.character_data AS sql_path
FROM pg_namespace n, pg_authid u
WHERE n.nspowner = u.oid AND pg_has_role(n.nspowner, 'USAGE'::text);
documentation中也对此进行了描述。
在这种情况下,您可以使用psql - information_schema
中的\d+
在\d+ information_schema.schemata
中获取视图的定义。
您应该使用pg_namespace
代替information_schema.schemata
答案 1 :(得分:2)
来自information_schema.schemata
的信息取决于您所连接的角色,因此通常不是查询发现模式的正确视图。
doc on information_schema.schemata
in 9.3说:
视图模式包含当前数据库中的所有模式 由当前启用的角色拥有。
然而,从那句话来看,(至少对我来说)并不十分清楚,为什么你看不到public
。
在一个邮件列表帖子中,汤姆莱恩有一个更进一步的解释:
见http://www.postgresql.org/message-id/11650.1357782995@sss.pgh.pa.us
他的结论:
事实上,非超级用户不会看到“public”,“pg_catalog”,也不会看到 甚至“information_schema”本身也在这个视图中,这看起来有点儿 愚蠢的。
看起来与此问题中的问题完全一样。
底线:使用pg_namespace
代替information_schema.schemata
这在版本9.4中进行了修改,以符合用户的期望。 current doc说:
视图模式包含当前数据库中的所有模式 当前用户可以访问(通过作为所有者或拥有 一些特权)。
USAGE
对模式的特权现在足以从这个视图中获取它。
答案 2 :(得分:1)
(作为评论的回答)
直接引用pg_namespace表可能是一个不错的解决方法......
SELECT exists(select 1 from pg_namespace where nspname = 'public') as schema_exists;
我不知道确切的区别是什么,但是知道PostgreSQL内部命名空间“后退”模式。
另外,我相信那些系统pg_ *表不是保证在不同版本之间保持一致,但它至少已经存在7.3(http://www.postgresql.org/docs/7.4/static/catalog-pg-namespace.html)并且现在已经存在(9.3) 0.1)。
答案 3 :(得分:0)
你写的那个查询应该有用......试试这个替代方案:
select count(*) > 0 FROM information_schema.schemata WHERE schema_name = 'public';