如果表不存在,如何选择而没有错误

问题描述 投票:1回答:2

我想从给定的表中运行SELECT,如果该表不存在,则该操作不会失败。假设,为简单起见,该表仅包含一列和一行,而我在该标量之后。如果该表不存在,我想返回0

我知道我可以做类似的事情:

query("select count(1) from information_schema.tables where table_name = 'versions'")
if result > 0
  return query("select version from versions limit 1")
else
  return 0

或者我可以使用存储过程/ plpgsql函数来做等效的事情。

但是有没有办法在单个即席查询中执行相同的操作?

((我正在执行两个查询。我没有充分的理由来更改它。我只是很好奇是否可以这样做。)

sql postgresql plpgsql dynamic-sql
2个回答
0
投票

我相信您正在寻找一个简短的PLpg / SQL函数。您可以像往常一样检查表是否存在于information_schema.tables中,并将结果存储在变量中。之后,您可以在IF语句中评估结果集,并返回所需的任何内容,例如

CREATE OR REPLACE FUNCTION f(p_table_name TEXT) 
  RETURNS INT 
LANGUAGE plpgsql AS 
$BODY$
DECLARE 
  res INT;
BEGIN 
  SELECT count(*) 
     into res
  FROM information_schema.tables 
  WHERE table_name = p_table_name;

  IF res>0 THEN RETURN res;
  ELSE RETURN 0;
  END IF;
END 
$BODY$;

不存在的表

SELECT * FROM f('versions');
 f 
---
 0
(1 Zeile)

现有表

SELECT * FROM f('t');
 f 
---
 1
(1 Zeile)

0
投票

您希望使用纯SQL解决方案单次往返服务器。这些年来,有许多相关的请求。 << [原则上不可能。

  • 任一个
需要动态SQL-这需要使用PL / pgSQL或另一个PL的函数。
  • Or
  • 您需要two往返服务器。首先检查是否存在,然后查询。您还

    不能

    将其嵌套在一个普通的SQL函数中,该函数将在执行前计划主体中的每个语句,并在尝试解析不存在的表名时失败。它甚至不会在函数创建时通过表面测试。参见:
  • 针对您的简单案例的两种简单解决方案(在许多可能的方法中:]]

    CREATE OR REPLACE FUNCTION f_select_version_if_exists1() RETURNS int LANGUAGE plpgsql PARALLEL SAFE AS $func$ BEGIN IF EXISTS ( SELECT FROM pg_catalog.pg_tables WHERE tablename = 'versions' AND schemaname = 'public' -- see below! ) THEN RETURN (SELECT version FROM versions LIMIT 1); ELSE RETURN 0; END IF; END $func$;

    或:

    CREATE OR REPLACE FUNCTION f_select_version_if_exists2(INOUT _version int = 0) AS $func$ BEGIN IF EXISTS ( SELECT FROM pg_catalog.pg_tables WHERE tablename = 'versions' AND schemaname = 'public' -- see below! ) THEN SELECT INTO _version version FROM versions LIMIT 1; END IF; END $func$ LANGUAGE plpgsql PARALLEL SAFE;

    我强烈建议您还固定模式名称。表名称在Postgres中不是唯一的。参见:

  • 此外,我创建了函数PARALLEL SAFE(仅在它可能嵌套在

    big查询中时才重要)。依赖于PARALLEL SAFE时,这将是[[错误,因为它通常包括临时对象的模式,这使其成为search_path第二是创造性地使用PARALLEL UNSAFE参数。相关:

    INOUT

  • © www.soinside.com 2019 - 2024. All rights reserved.