Postgres 8.4及更高版本的数据库包含公共模式中的公共表和公司模式中的特定公司表。 公司架构名称总是以“Company”开头,以公司编号结束。 所以可能有这样的图式:

public
company1
company2
company3
...
companynn

应用程序总是与单个公司一起工作。 搜索路径在odbc或npgsql连接字符串中相应地指定,例如:

search_path='company3,public'

如何检查给定的表是否存在于指定的companyn模式中?

eg:

select isSpecific('company3','tablenotincompany3schema')

应该返回false,和

select isSpecific('company3','tableincompany3schema')

应该返回true。

在任何情况下,函数都应该只检查通过的companyn模式,而不是其他模式。

如果给定的表同时存在于public和传递的模式中,函数应该返回true。 它应该适用于Postgres 8.4或更高版本。


也许可以使用information_schema:

SELECT EXISTS(
    SELECT * 
    FROM information_schema.tables 
    WHERE 
      table_schema = 'company3' AND 
      table_name = 'tableincompany3schema'
);

这取决于您想要测试什么。

信息模式?

要查找“表是否存在”(不管谁问),严格来说,查询信息模式(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'
   );

dba相关回答。SE讨论“信息模式与系统目录”

可供选择:强制转换为regclass

SELECT 'schema_name.table_name'::regclass;

如果(可选模式限定的)表(或占用该名称的其他对象)不存在,将引发异常。

如果不对表名进行模式限定,则对regclass的强制转换默认为搜索路径,并返回找到的第一个表的OID——如果表不在列出的模式中,则返回异常。注意,系统模式pg_catalog和pg_temp(当前会话临时对象的模式)自动成为搜索路径的一部分。

您可以使用它在函数中捕获可能的异常。例子:

检查Postgres (plpgsql)中是否存在序列

像上面这样的查询避免了可能的异常,因此稍微快一些。

请注意,在这里名称的每个组件都被视为标识符-与上面的查询相反,在上面的查询中名称是作为文字字符串给出的。标识符强制转换为小写,除非双引号。如果强制使用带有双引号的非法标识符,则需要包括这些标识符。如:

SELECT '"Dumb_SchName"."FoolishTbl"'::regclass;

See:

PostgreSQL列名区分大小写吗?

to_regclass(rel_name) 在 Postgres 9.4+ 中

现在简单多了:

SELECT to_regclass('schema_name.table_name');

和演员一样,但是它回来了……

... 如果没有找到名称,则为Null,而不是抛出错误


对于PostgreSQL 9.3或以下版本…或者谁喜欢所有规范化的文本

我的旧SwissKnife库有三种风格:relname_exists(anyThing)、relname_normalized(anyThing)和relnamechecked_to_array(anyThing)。所有来自pg_catalog的检查。返回标准通用数据类型(布尔型、文本型或文本[]型)。

/**
 * 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;