表名作为PostgreSQL函数参数

前端之家收集整理的这篇文章主要介绍了表名作为PostgreSQL函数参数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想在Postgres函数中传递一个表名作为参数。我试过这个代码
CREATE OR REPLACE FUNCTION some_f(param character varying) RETURNS integer 
AS $$
    BEGIN
    IF EXISTS (select * from quote_ident($1) where quote_ident($1).id=1) THEN
     return 1;
    END IF;
    return 0;
    END;
$$ LANGUAGE plpgsql;

select some_f('table_name');

我得到这个:

ERROR:  Syntax error at or near "."
LINE 4: ...elect * from quote_ident($1) where quote_ident($1).id=1)...
                                                             ^

********** Error **********

ERROR: Syntax error at or near "."

这里是我得到的错误改变为这个select * from quote_ident($ 1)tab where tab.id = 1:

ERROR:  column tab.id does not exist
LINE 1: ...T EXISTS (select * from quote_ident($1) tab where tab.id...

可能,quote_ident($ 1)工作,因为没有where quote_ident($ 1).id = 1部分,我得到1,这意味着某事被选中。为什么第一个quote_ident($ 1)可以工作,第二个不同时工作?这怎么可能解决

这可以进一步简化和改进:
CREATE OR REPLACE FUNCTION some_f(_tbl regclass,OUT result integer) AS
$func$
BEGIN
EXECUTE format('SELECT (EXISTS (SELECT 1 FROM %s WHERE id = 1))::int',_tbl)
INTO result;
END
$func$ LANGUAGE plpgsql;

调用(使用模式限定名称的示例 – 请参见下文):

SELECT some_f('myschema.mytable');  -- would fail with quote_ident()

要么:

SELECT some_f('"my very uncommon table name"')

要点

>使用OUT参数简化功能。您可以直接选择动态sql的结果并完成。不需要额外的变量和代码
> EXISTS确实是你想要的,我把它保存在我的查询。有多种方法可以做到这一点。
>你似乎想要一个整数回,所以我把布尔结果从EXISTS()转换为整数,这产生了你所拥有的。我会返回boolean
>我使用对象标识符类型regclass作为_tbl的输入类型。这一切都quote_ident(_tbl)format('%I',_tbl)一切,但更好,因为:

> ..它也阻止sql注入。
> ..如果表名无效/不存在/对当前用户不可见,它立即失败并更优雅。
> ..它与模式限定的表名称,其中纯quote_ident(_tbl)或格式(%I)将失败,因为他们不能解决歧义。

>我仍然使用format(),因为它简化了语法(并演示如何使用),但使用%s而不是%I。对于简单的例子,我们可以只是连接:

EXECUTE 'SELECT (EXISTS (SELECT 1 FROM ' || _tbl || ' WHERE id = 1))::int'

>不需要对id列进行表格限定。

用Postgresql 9.1测试。 format()至少需要该版本。

这就是为什么你总是正确转义动态sql用户输入:
SQL Fiddle demo for SQL injection

猜你在找的Postgre SQL相关文章