在PostgreSQL中,我想创建一个安全包装机制,如果发生异常,该机制将返回空结果。考虑以下:
SELECT * FROM myschema.mytable;
我可以在客户端应用程序中进行安全包装:
try { result = execute_query('SELECT value FROM myschema.mytable').fetchall(); } catch(pg_exception) { result = [] }
但是我可以直接在SQL中做这样的事情吗?我想使以下代码工作,但似乎应该将其放到DO $$ ...$$块中,在这里我迷路了。
DO $$ ...$$
BEGIN SELECT * FROM myschema.mytable; EXCEPTION WHEN others THEN SELECT unnest(ARRAY[]::TEXT[]) END
通常,plpgsql代码总是包装在一个BEGIN .. END块中。那可以在DO语句或函数的主体内。块可以嵌套在内部-但它们不能存在 于外部 ,请不要将其与普通SQL混淆。
BEGIN .. END
DO
每个BEGIN块都可以选择包含一个EXCEPTION用于处理异常的子句,但是需要捕获异常的函数要昂贵得多,因此最好避免先验地排除异常。
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或者如果表不存在则为空字符串。
text
value如果给定表存在,还假设存在一列。您也可以对此进行测试,但是您并没有要求。
value
这两个参数都是 区分大小写的 text值。这与处理SQL语句中的标识符的方式略有不同。如果您从未用双引号将标识符引起来,则传递小写字母名称就可以了。
'public'在我的示例中,架构名称默认为。适应您的需求。您甚至可以完全忽略该模式,并且默认为当前模式search_path。
'public'
search_path
to_regclass()是Postgres 9.4中的 新功能。对于旧版本,请替换:
to_regclass()
IF EXISTS (
SELECT 1 FROM information_schema.tables WHERE table_schema = _schema AND table_name = _tbl );
实际上,这 更加准确 ,因为它可以准确测试您的需求。