这取决于您要准确测试的内容。
信息架构?
要查找“表是否存在”(无论是谁询问) ,严格来说,查询信息架构 ( 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'
);
SELECT 'schema_name.table_name'::regclass
如果(可选的模式限定)表(或占用该名称的其他对象)不存在,则会引发异常。
如果您不对表名进行模式限定,则强制转换regclass
默认为search_path
并返回找到的第一个表的 OID - 如果表不在列出的模式中,则返回异常。请注意,系统架构pg_catalog
和pg_temp
(当前会话的临时对象的架构)自动成为search_path
.
您可以使用它并在函数中捕获可能的异常。例子:
像上面这样的查询避免了可能的异常,因此速度稍快。
现在简单多了:
SELECT to_regclass('schema_name.table_name');
与演员相同,但它返回......
... null 而不是在找不到名称时抛出错误