表名作为PostgreSQL函数参数

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

我得到这个:

  1. ERROR: Syntax error at or near "."
  2. LINE 4: ...elect * from quote_ident($1) where quote_ident($1).id=1)...
  3. ^
  4.  
  5. ********** Error **********
  6.  
  7. ERROR: Syntax error at or near "."

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

  1. ERROR: column tab.id does not exist
  2. 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)可以工作,第二个不同时工作?这怎么可能解决

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

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

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

要么:

  1. 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。对于简单的例子,我们可以只是连接:

  1. 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相关文章