小编典典

处理PostgreSQL异常的优雅方法?

sql

在PostgreSQL中,我想创建一个安全包装机制,如果发生异常,该机制将返回空结果。考虑以下:

SELECT * FROM myschema.mytable;

我可以在客户端应用程序中进行安全包装:

try {
    result = execute_query('SELECT value FROM myschema.mytable').fetchall();
}
catch(pg_exception) {
    result = []
}

但是我可以直接在SQL中做这样的事情吗?我想使以下代码工作,但似乎应该将其放到DO $$ ...$$块中,在这里我迷路了。

BEGIN
    SELECT * FROM myschema.mytable;
EXCEPTION WHEN others THEN
    SELECT unnest(ARRAY[]::TEXT[])
END

阅读 268

收藏
2021-03-17

共1个答案

小编典典

PL / pgSQL中的异常处理

通常,plpgsql代码总是包装在一个BEGIN .. END块中。那可以在DO语句或函数的主体内。块可以嵌套在内部-但它们不能存在 于外部
,请不要将其与普通SQL混淆。

每个BEGIN块都可以选择包含一个EXCEPTION用于处理异常的子句,但是需要捕获异常的函数要昂贵得多,因此最好避免先验地排除异常。

在示例中如何 避免 异常

一个DO语句不能返回任何东西。创建一个将表和模式名称作为参数并返回所需内容
函数

CREATE OR REPLACE FUNCTION f_tbl_value(_tbl text, _schema text = 'public')
  RETURNS TABLE (value text) AS
$func$
DECLARE
   _t regclass := to_regclass(_schema || '.' || _tbl);
BEGIN
   IF _t IS NULL THEN
      value := ''; RETURN NEXT;    -- return single empty string
   ELSE
      RETURN QUERY EXECUTE
      'SELECT value FROM ' || _t;  -- return set of values
   END
$func$ LANGUAGE plpgsql;

称呼:

SELECT * FROM f_tbl_value('my_table');

或者:

SELECT * FROM f_tbl_value('my_table', 'my_schema');
  • 假设您想要一组具有单列的行,text或者如果表不存在则为空字符串。

  • value如果给定表存在,还假设存在一列。您也可以对此进行测试,但是您并没有要求。

  • 这两个参数都是 区分大小写的 text值。这与处理SQL语句中的标识符的方式略有不同。如果您从未用双引号将标识符引起来,则传递小写字母名称就可以了。

  • 'public'在我的示例中,架构名称默认为。适应您的需求。您甚至可以完全忽略该模式,并且默认为当前模式search_path

  • to_regclass()是Postgres 9.4中的 新功能。对于旧版本,请替换:

    IF EXISTS (
    

    SELECT 1
    FROM information_schema.tables
    WHERE table_schema = _schema
    AND table_name = _tbl
    );

实际上,这 更加准确 ,因为它可以准确测试您的需求。

2021-03-17