有什么方法可以在 postgres 中获得更有意义的错误消息?

Any way to get a more meaningful error message in postgres?

我们喝点茶吧...

CREATE OR REPLACE FUNCTION allRelevantTeas() RETURNS TABLE(tea_id INTEGER) AS $function$
DECLARE
    result REFCURSOR;
    stmt TEXT;
    countries_with_tea TEXT[] := array['england', 'turkey', 'india', 'japan', 'china'];
BEGIN
    stmt := '';
    FOR tea_drinker in countries_with_tea LOOP
        stmt := stmt || format($$(SELECT tea_id FROM %I)$$, tea_drinker);
        IF tea_drinker <> 'china' THEN
            stmt := stmt || $$ UNION $$;
        END IF;
    END LOOP;

    OPEN result FOR EXECUTE stmt;
    RETURN result;
END $function$
LANGUAGE plpgsql STABLE;

SELECT * FROM allRelevantTeas();

让我们测试一下...

syntax error at or near "countries_with_tea"

我没看到。这可能很明显,但我就是看不到。

有人发现这有什么问题吗?或者,如果没有,有什么方法可以让我从 postgres 得到比 "there was a syntax error (but I don't tell you what it was)" 更有意义的错误?

你的循环是错误的,你需要使用FOREACHloop through the elements of an array:

CREATE OR REPLACE FUNCTION allRelevantTeas() RETURNS TABLE(tea_id INTEGER) AS $function$
DECLARE
    stmt TEXT;
    tea_drinker text;
    countries_with_tea TEXT[] := array['england', 'turkey', 'india', 'japan', 'china'];
BEGIN
    stmt := '';
    FOREACH tea_drinker in array countries_with_tea LOOP
        stmt := stmt || format($$(SELECT tea_id FROM %I)$$, tea_drinker);
        IF tea_drinker <> 'china' THEN
            stmt := stmt || $$ UNION $$;
        END IF;
    END LOOP;

    RETURN query execute stmt;
END $function$
LANGUAGE plpgsql STABLE;

你真的不需要 UNION,你可以使用 return query 到 return 多个结果:

CREATE OR REPLACE FUNCTION allrelevantteas() 
  RETURNS TABLE(tea_id INTEGER) AS $function$
DECLARE
    stmt TEXT;
    tea_drinker text;
    countries_with_tea TEXT[] := array['england', 'turkey', 'india', 'japan', 'china'];
BEGIN
    stmt := '';
    FOREACH tea_drinker in array countries_with_tea LOOP
      stmt := format($$(SELECT tea_id FROM %I)$$, tea_drinker);
      return query execute stmt;
    END LOOP;
END $function$
LANGUAGE plpgsql STABLE;

Online example


如果您需要日志,最好使用 table 继承或视图来创建包含所有其他日志的单个 table。

a_horse_with_no_name 已经告诉你如何修复错误,但是为了获得更有意义的错误消息,我已经得到一个,使用 psql:

ERROR:  syntax error at or near "countries_with_tea"
LINE 8:     FOR tea_drinker in countries_with_tea LOOP
                               ^

如果你只看到第一行而不是接下来的两行,那么你正在使用一些不是你朋友的工具。

只是一张小纸条。我经常查看我的代码并询问 "Is there anything that is subject to breaking at any foreseeable change and can I prevent it now?" 它已经为我服务多年,而且我几乎总能找到一些东西。这里有一个。 "If tea_drinker ... end if" 语句非常脆弱。当另一个国家被添加到数组中并被添加到中国之后会发生什么。回答,你的 SQL 在执行时失败了。强化版本将检查当前 tea_drinker 到数组中最后一个输入的位置。这可以通过 array functions、array_position 和 array_length 来完成。

-- Instead of: 
IF tea_drinker <> 'china' THEN
   stmt := stmt || $$ UNION $$;
END IF;

-- Use 
if array_position(countries_with_tea, tea_drinker) <> array_length(countries_with_tea, 1)
then 
   stmt := stmt || $$ UNION $$;
end if;