[英]How to check if a table exists in a given schema
Postgres 8.4 和更高版本的数据库包含public
表和company
模式中的公司特定表。
company
架构名称始终以'company'
开头并以公司编号结尾。
所以可能有这样的模式:
public
company1
company2
company3
...
companynn
应用程序始终适用于一家公司。
search_path
在 odbc 或 npgsql 连接字符串中相应指定,例如:
search_path='company3,public'
您将如何检查给定的表是否存在于指定的companyn
模式中?
例如:
select isSpecific('company3','tablenotincompany3schema')
应该返回false
,并且
select isSpecific('company3','tableincompany3schema')
应该返回true
。
在任何情况下,function 应该只检查companyn
模式是否通过,而不是其他模式。
如果给定的表同时存在于public
模式和传递的模式中,则 function 应该返回true
。
它应该适用于 Postgres 8.4 或更高版本。
这取决于您要准确测试什么。
要查找“表是否存在”(无论是谁询问),严格来说,查询信息模式( information_schema.tables
)是不正确的,因为( 根据文档):
仅显示当前用户有权访问的那些表和视图(通过成为所有者或具有某些特权)。
@kong 提供的查询可以返回FALSE
,但该表仍然可以存在。 它回答了这个问题:
如何检查表(或视图)是否存在,以及当前用户是否有权访问它?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
信息模式主要用于保持跨主要版本和跨不同 RDBMS 的可移植性。 但是实现很慢,因为 Postgres 必须使用复杂的视图来符合标准( information_schema.tables
是一个相当简单的例子)。 并且一些信息(如 OID)在从系统目录的翻译中丢失了——它实际上携带了所有信息。
你的问题是:
如何检查表是否存在?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
AND c.relkind = 'r' -- only tables
);
直接使用系统目录pg_class
和pg_namespace
,这也相当快。 但是, 根据pg_class
文档:
目录
pg_class
表和大多数其他具有列或与表类似的所有内容进行编目。 这包括索引(但另见pg_index
)、序列、视图、物化视图、复合类型和TOAST 表;
对于这个特定问题,您还可以使用系统视图pg_tables
。 在主要的 Postgres 版本中更简单、更便携(对于这个基本查询几乎不关心):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
标识符在上述所有对象中必须是唯一的。 如果你想问:
如何检查给定模式中的表或类似对象的名称是否被采用?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
);
regclass
为regclass
SELECT 'schema_name.table_name'::regclass
如果(可选模式限定)表(或占用该名称的其他对象)不存在,则会引发异常。
如果您没有对表名进行模式限定,则转换为regclass
默认为search_path
并返回找到的第一个表的 OID - 如果该表不在列出的模式中,则返回异常。 请注意,系统模式pg_catalog
和pg_temp
(当前会话的临时对象的模式)自动成为search_path
一部分。
您可以使用它并在函数中捕获可能的异常。 例子:
像上面这样的查询避免了可能的异常,因此稍微快一点。
to_regclass(rel_name)
现在简单多了:
SELECT to_regclass('schema_name.table_name');
与演员表相同, 但它返回......
... null 而不是在未找到名称时抛出错误
也许使用information_schema :
SELECT EXISTS(
SELECT *
FROM information_schema.tables
WHERE
table_schema = 'company3' AND
table_name = 'tableincompany3schema'
);
我的旧 SwissKnife 库的三种风格: relname_exists(anyThing)
、 relname_normalized(anyThing)
和relnamechecked_to_array(anyThing)
。 所有来自pg_catalog.pg_class表的检查,并返回标准通用数据类型( boolean 、 text或text [] )。
/**
* From my old SwissKnife Lib to your SwissKnife. License CC0.
* Check and normalize to array the free-parameter relation-name.
* Options: (name); (name,schema), ("schema.name"). Ignores schema2 in ("schema.name",schema2).
*/
CREATE FUNCTION relname_to_array(text,text default NULL) RETURNS text[] AS $f$
SELECT array[n.nspname::text, c.relname::text]
FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace,
regexp_split_to_array($1,'\.') t(x) -- not work with quoted names
WHERE CASE
WHEN COALESCE(x[2],'')>'' THEN n.nspname = x[1] AND c.relname = x[2]
WHEN $2 IS NULL THEN n.nspname = 'public' AND c.relname = $1
ELSE n.nspname = $2 AND c.relname = $1
END
$f$ language SQL IMMUTABLE;
CREATE FUNCTION relname_exists(text,text default NULL) RETURNS boolean AS $wrap$
SELECT EXISTS (SELECT relname_to_array($1,$2))
$wrap$ language SQL IMMUTABLE;
CREATE FUNCTION relname_normalized(text,text default NULL,boolean DEFAULT true) RETURNS text AS $wrap$
SELECT COALESCE(array_to_string(relname_to_array($1,$2), '.'), CASE WHEN $3 THEN '' ELSE NULL END)
$wrap$ language SQL IMMUTABLE;
来自https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-PATTERNS
例如,\dt foo*。 bar显示所有表名包含 bar 的表,这些表位于模式名以 foo 开头的模式中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.