【问题标题】:How can I detect if a Postgres temporary table already exists?如何检测 Postgres 临时表是否已存在?
【发布时间】:2012-06-28 19:15:18
【问题描述】:

我有一个名为 tester 的表,我需要用一个临时表覆盖它以进行一些测试。到目前为止,我已经使用:

CREATE TEMPORARY TABLE tester AS
  SELECT * FROM tester WHERE name='bananas';

这个临时表将在会话结束时消失,这对我来说很好,但是它是负责连接的外部应用程序并且它倾向于缓存连接以供重用(因此不能保证临时表已被删除)。这意味着如果我再次尝试执行上述查询,它可能会失败,因为临时表仍然存在。

显式删除临时表并不是一个真正的选择。我宁愿忍受失败的查询,也不愿冒险错误地删除底层的“真实”表。

想要只在临时表不存在的情况下创建它。 我确实找到了这个人们建议在检查表是否存在时应该使用的查询:

SELECT * FROM pg_catalog.pg_class WHERE relkind = 'r' AND relname = 'tester';

result when temporary table exists:

 relname | relnamespace | reltype | relowner | relam | relfilenode | reltablespace | relpages | reltuples | reltoastrelid | reltoastidxid | relhasindex | relisshared | relkind | relnatts | relchecks | reltriggers | relukeys | relfkeys | relrefs | relhasoids | relhaspkey | relhasrules | relhassubclass | relfrozenxid | relacl | reloptions
---------+--------------+---------+----------+-------+-------------+---------------+----------+-----------+---------------+---------------+-------------+-------------+---------+----------+-----------+-------------+----------+----------+---------+------------+------------+-------------+----------------+--------------+--------+------------
 tester  |         2200 | 1533065 |  1531747 |     0 |     1533063 |             0 |        0 |         0 |       1533067 |             0 | t           | f           | r       |        3 |         0 |           0 |        0 |        0 |       0 | f          | t          | f           | f              |     17654031 |        |
 tester  |      1533088 | 1533065 |  1531747 |     0 |     1533160 |             0 |        0 |         0 |       1533163 |             0 | f           | f           | r       |        3 |         0 |           0 |        0 |        0 |       0 | f          | f          | f           | f              |     17654066 |        |

如您所见,有两条记录。一个用于原始表,一个用于临时表。第二条记录是临时表——我知道这一点是因为它在不同会话中工作时会消失——但除了缺少索引或主键之外,这是我可以将其识别为临时表的唯一方法。这只是一个测试表 - 我正在使用的一些真实表可能缺少索引和/或主键。

问题(tl;dr 版):如果已经存在同名的“真实”表,我如何测试 临时表是否存在?(或至少确定一个表是临时的?)

免责声明:我添加了 Java 标记是因为我使用它来执行查询(SQL 只是应用程序的一小部分)。尽管 Java 与该问题没有直接关系,但我需要的不是可以从 Java 上下文中使用的答案。

【问题讨论】:

    标签: java sql postgresql


    【解决方案1】:

    用户定义函数检查临时表是否存在。

    CREATE or REPLACE FUNCTION public.iftableexists( varchar)
    RETURNS pg_catalog.bool AS
    $BODY$
    DECLARE
    
     BEGIN
    
         /* check the table exist in database and is visible*/
     perform n.nspname ,c.relname
    FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid
    = c.relnamespace
    where n.nspname like 'pg_temp_%' AND pg_catalog.pg_table_is_visible(c.oid)
    AND Upper(relname) = Upper($1);
    
         IF FOUND THEN
            RETURN TRUE;
         ELSE
            RETURN FALSE;
         END IF;
    
     END;
    $BODY$
    LANGUAGE 'plpgsql' VOLATILE
    

    See here for more details

    【讨论】:

    • 这对我有用,谢谢!有没有办法将函数结果作为条件放入 SQL 查询中(这样我就可以避免在我的 Java 代码中进行额外的查询)?据我所知没有 - 但我很想知道是否有办法。
    • 尝试 SELECT * FROM my_table WHERE iftableexists(my_table) 或者你可以使用 CASE
    【解决方案2】:

    我想做的只是创建临时表,如果它 尚不存在。

    CREATE TEMPORARY TABLE IF NOT EXISTS tester AS
      SELECT * FROM tester WHERE name='bananas';
    

    【讨论】:

    • 注意“如果不存在”是在 PostgreSQL 9.6 中引入的。
    【解决方案3】:

    这对我有用:

    SELECT EXISTS (
       SELECT 1
       FROM   information_schema.tables 
       WHERE  table_schema like 'pg_temp_%'
       AND table_name=LOWER('table_name')
    )
    

    【讨论】:

      【解决方案4】:

      当有一列包含我们需要的信息时,我不明白您为什么要使用like“模糊搜索”。也许有一些我不知道的向后兼容性问题。

      这里的代码和上面一样,但是使用table_type = 'LOCAL TEMPORARY而不是like 'pg_temp_%'

      SELECT EXISTS (
         SELECT 1
         FROM information_schema.tables 
         WHERE table_type = 'LOCAL TEMPORARY'
         AND table_name = 'table_name'
      )
      

      【讨论】:

        猜你喜欢
        • 2019-12-09
        • 2011-12-30
        • 1970-01-01
        • 2011-09-25
        • 2019-11-25
        • 2010-10-30
        • 1970-01-01
        • 2010-10-14
        • 2021-04-16
        相关资源
        最近更新 更多