如何检查给定架构中是否存在表



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')

应返回CCD_ 8。

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

如果给定的表同时存在于public和传递的模式中,则函数应返回true
它应该适用于Postgres8.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_classpg_namespace,这也相当快。但是,根据pg_class:上的文件

目录pg_class对表和大多数其他具有列或在其他方面类似于表。这包括索引(但是另请参见pg_index),序列views物化视图复合类型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讨论"strong";信息模式与系统目录"

备选方案:强制转换为regclass

SELECT 'schema_name.table_name'::regclass;

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

如果未对表名进行架构限定,则强制转换为regclass将默认为search_path,并返回找到的第一个表的OID,如果该表不在列出的任何架构中,则返回异常。注意,系统模式pg_catalogpg_temp(当前会话的临时对象的模式)自动地是search_path的一部分。

您可以使用它来捕获函数中可能出现的异常。示例:

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

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

请注意,在这里,名称的每个组件都被视为标识符,而不是上面的查询,在上面的查询中,名称是以文本字符串的形式给出的。标识符被强制转换为小写,除非使用双引号。如果您使用双引号强制使用非法标识符,则需要包括这些标识符。类似:

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

参见:

  • PostgreSQL列名区分大小写吗

研究生9.4中的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'
);

对于PostgreSQL 9.3或更低版本。。。或者谁喜欢所有规范化为文本

我的旧SwissKnife库有三种口味:relname_exists(anyThing)relname_normalized(anyThing)relnamechecked_to_array(anyThing)。所有检查来自pg_catalog.pg_class表,并返回标准通用数据类型(布尔型文本文字[])。

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

相关内容

  • 没有找到相关文章

最新更新