有什么方法可以在 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)" 更有意义的错误?
你的循环是错误的,你需要使用FOREACH
到loop 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;
如果您需要日志,最好使用 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;
我们喝点茶吧...
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)" 更有意义的错误?
你的循环是错误的,你需要使用FOREACH
到loop 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;
如果您需要日志,最好使用 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;