在plpgsql函数中使用quote_ident()的作用是什么?

12

我刚开始创建plpgsql函数。关于在函数内执行动态命令时使用quote_ident()(甚至是quote_literal())需要一些澄清。希望有人能够详细说明它们在函数内的工作原理。TIA

这里是一个例子:

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

31

quote_ident 用于对 标识符 进行引用。 quote_literal 用于对 字符串 进行引用。

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;

或者仅使用format函数

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

如果不引用动态SQL,a) 将无法工作(在语法错误时失败),b)不安全,容易受到SQL注入攻击


参考:https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-QUOTE-LITERAL-EXAMPLE。此形式更好,因为变量以其本机数据类型格式处理,而不是无条件地通过%L将它们转换为文本并引用它们。它也更有效率。 - raphael
1
@raphael - 使用占位符%L的formatquote_literal完全相同。更有效的方法是使用USING子句。 - Pavel Stehule

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接