Tre*_*reg 17 sql postgresql exception-handling dynamic-sql plpgsql
在PostgreSQL中,我想创建一个安全包装机制,如果发生异常,它将返回空结果.考虑以下:
SELECT * FROM myschema.mytable;
Run Code Online (Sandbox Code Playgroud)
我可以在客户端应用程序中进行安全包装:
try {
result = execute_query('SELECT value FROM myschema.mytable').fetchall();
}
catch(pg_exception) {
result = []
}
Run Code Online (Sandbox Code Playgroud)
但我可以直接在SQL中做这样的事情吗?我想使下面的代码工作,但似乎它应该被放入DO $$ ... $$
块中,在这里我迷路了.
BEGIN
SELECT * FROM myschema.mytable;
EXCEPTION WHEN others THEN
SELECT unnest(ARRAY[]::TEXT[])
END
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 12
通常,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;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT * FROM f_tbl_value('my_table');
Run Code Online (Sandbox Code Playgroud)
要么:
SELECT * FROM f_tbl_value('my_table', 'my_schema');
Run Code Online (Sandbox Code Playgroud)
假设您想要一组具有单个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
);
Run Code Online (Sandbox Code Playgroud)
这实际上更准确,因为它可以准确测试您的需求.更多选项和详细说明:
使用动态SQL时始终防止SQL注入!演员regclass
在这里做的伎俩.更多细节:
归档时间: |
|
查看次数: |
23253 次 |
最近记录: |