如何检查给定模式中是否存在表

 mobiledu2502918997 发布于 2023-02-10 14:30

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.

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

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

2 个回答
  • 也许使用information_schema:

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

    2023-02-10 14:33 回答
  • 这取决于你想要准确测试的内容.

    信息架构?

    要查找"表是否存在"(无论是谁在询问),严格来说,查询信息模式(information_schema.tables)是不正确的,因为(每个文档):

    仅显示当前用户可以访问的那些表和视图(通过作为所有者或具有某些特权).

    @kong演示的查询可以返回FALSE,但表仍然可以存在.它回答了这个问题:

    如何检查表(或视图)是否存在,以及当前用户是否可以访问它?

    SELECT EXISTS (
       SELECT 1
       FROM   information_schema.tables 
       WHERE  table_schema = 'schema_name'
       AND    table_name = 'table_name'
       );
    

    信息模式主要用于在主要版本和不同RDBMS之间保持可移植性.但是实现很慢,因为Postgres必须使用复杂的视图来遵守标准(这information_schema.tables是一个相当简单的例子).并且一些信息(如OID)在系统目录的翻译中丢失 - 实际上包含所有信息.

    系统目录

    你的问题是:

    如何检查表是否存在?

    SELECT EXISTS (
       SELECT 1 
       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),序列,视图,物化视图,复合类型TOAST表 ;

    对于此特定问题,您还可以使用系统视图pg_tables.主要的Postgres版本更简单,更便携(这个基本查询几乎不关心):

    SELECT EXISTS (
       SELECT 1 
       FROM   pg_tables
       WHERE  schemaname = 'schema_name'
       AND    tablename = 'table_name'
       );
    

    标识符必须在上面提到的所有对象中是唯一的.如果你想问:

    如何检查给定模式中的表或类似对象的名称是否被采用?

    SELECT EXISTS (
       SELECT 1 
       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强制转换为search_path和返回找到的第一个表的OID - 如果表中没有列出的模式,则返回异常.请注意,系统架构pg_catalogpg_temp(当前会话的临时对象的架构)自动成为其中的一部分search_path.

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

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

    像上面这样的查询可以避免可能的异常,因此会稍快一些.

    to_regclass(rel_name) 在Postgres 9.4+

    现在简单得多:

    SELECT to_regclass('schema_name.table_name');
    

    与演员相同,它返回...

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

    2023-02-10 14:33 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有