在 plpgsql 函数中使用 quote_ident()

Posted

技术标签:

【中文标题】在 plpgsql 函数中使用 quote_ident()【英文标题】:the use of quote_ident() in a plpgsql function 【发布时间】:2015-07-21 03:39:57 【问题描述】:

我是创建 plpgsql 函数的新手。我需要对在函数内部执行的动态命令使用 quote_ident()(甚至是 quote_literal())进行一些说明。希望任何人都可以给我一个关于他们如何在函数中工作的具体解释。 TIA

这是一个例子:

EXECUTE 'UPDATE tbl SET ' || quote_ident(colname) || ' = ' || quote_literal(newvalue) || ' WHERE key = ' || quote_literal(keyvalue);

【问题讨论】:

【参考方案1】:

quote_ident 用于 标识符 引用。 quote_literal 用于 string 引用。

postgres=# select quote_ident('tablename');
┌─────────────┐
│ quote_ident │
╞═════════════╡
│ tablename   │
└─────────────┘
(1 row)

postgres=# select quote_ident('special name');
┌────────────────┐
│  quote_ident   │
╞════════════════╡
│ "special name" │
└────────────────┘
(1 row)

postgres=# select quote_literal(e'some text with special char"\'"');
┌───────────────────────────────────┐
│           quote_literal           │
╞═══════════════════════════════════╡
│ 'some text with special char"''"' │
└───────────────────────────────────┘
(1 row)

什么是标识符?表名、列名、模式名、序列名……什么是文字? - 通常是一些文本值(但可以是任何类型的值)。函数搜索和替换一些特殊字符,但规则不同 - SQL 中的标识符和字符串不同。

现在 - 这些功能有点过时了。 quote_literal 应替换为子句USING(更好的性能),quote_ident 应替换为格式化函数format(由于更好的可读性):

EXECUTE format('UPDATE tbl SET %I=$1 WHERE key=$2', colname) 
  USING newvalue, keyvalue;

或仅具有格式功能

EXECUTE format('UPDATE tbls SET %I=%L WHERE key=%L', colname, newvalue, keyvalue);

不引用您的动态 SQL a) 不应该工作(因语法错误而失败),b) 对 sql 注入不安全

【讨论】:

参考:postgresql.org/docs/current/static/…。还应使用格式,因为:“这种形式更好,因为变量以其本机数据类型格式处理,而不是无条件地将它们转换为文本并通过 %L 引用它们。它也更有效” @raphael - 使用带有占位符 %L 的 formatquote_literal 完全相同。更有效的方法是使用USING 子句。

以上是关于在 plpgsql 函数中使用 quote_ident()的主要内容,如果未能解决你的问题,请参考以下文章

在 plpgsql 函数中访问 select 语句结果

PostgreSQL:在 plpgsql 函数中回滚事务?

需要使用 plpgsql 函数截断表

如何在 Postgres/plpgsql 的视图定义中使用变量

返回查询时如何退出plpgsql函数

plpgsql 错误:RETURN 在返回 void 的函数中不能有参数