将数组文字传递给 PostgreSQL 函数

Posted

技术标签:

【中文标题】将数组文字传递给 PostgreSQL 函数【英文标题】:Pass array literal to PostgreSQL function 【发布时间】:2013-06-12 21:24:07 【问题描述】:

我有一个包含 select 语句的 Postgres 函数。我需要使用包含字符串值数组的传入变量添加条件。

CREATE OR REPLACE FUNCTION get_questions(vcode text)
  RETURN return_value as $f$
DECLARE vresult return_value;

BEGIN
--snip--

SELECT id, title, code
FROM questions WHERE code NOT IN (vcode);

--snip--

questions表:

id ,title, code
1, "title1", "qcode1"
2, "title2", "qcode2"
3, "title3", "qcode3"
4, "title4", "qcode4"

vcode 文字在 php 中应该如何格式化,条件的语法应该是什么?

使用 PostgreSQL 9.1.1、PHP 5.3.6、pg_query_params

【问题讨论】:

PostgreSQL 和 PHP 版本?您使用的是 PDO 还是 pg_ 函数? @CraigRinger 我正在使用 pg_ 函数。 pg_query_params($db, $SQL, $input) @user2254435:PostgreSQL and PHP versions 的哪一部分不清楚? @CraigRinger Postgres 9.1.1,PHP 5.3.6 @user2254435 好吧,首先,您很容易受到重大安全漏洞的影响,请更新。 postgresql.org/support/security/faq/2013-04-04 【参考方案1】:

SQL NOT INsets 一起使用。由于您要传递一个数组,因此请使用<> ALL

您必须小心不要将任何NULL 值与此类表达式相关联,因为NULL <> anything 永远不会计算为TRUE,因此永远不会在WHERE 子句中限定。

您的函数可能如下所示:

CREATE OR REPLACE FUNCTION get_questions(vcode text[])
  RETURNS TABLE(id int, title text, code text)
  LANGUAGE sql AS
$func$
SELECT q.id, q.title, q.code
FROM   questions q
WHERE  q.code <> ALL ($1);
$func$;

呼叫:

SELECT * FROM get_questions('qcode2, qcode2');

或者(带有array constructor 的替代语法):

SELECT * FROM get_questions(ARRAY['qcode2', 'qcode2']);

或者您可以使用VARIADIC 参数:

CREATE OR REPLACE FUNCTION get_questions(VARIADIC vcode text[]) ...

... 并传递一个 list 值:

SELECT * FROM get_questions('qcode2', 'qcode2');

详情:

Return rows matching elements of input array in plpgsql function

要点:

使用简单的 SQL 函数,因为您的问题中没有任何内容需要 PL/pgSQL 的过程元素。

输入参数是一个文本数组:text[]

要从查询中返回多行,请使用 RETURNS TABLE 作为返回类型。

使用位置参数 $1 引用 in 参数,因为按名称引用仅在 9.2 版中针对 SQL 函数引入(与现在在某些版本中已经存在的 plpgsql 函数相反)。

表限定列名,否则会与RETURNS 子句中定义的同名参数OUT 冲突。

LEFT JOIN unnest($1) / IS NULL

长数组更快(> ~ 80 个元素,视情况而定):

SELECT q.id, q.title, q.code
FROM   questions q
LEFT   JOIN unnest($1) c(code) USING (code)
WHERE  c.code IS NULL;

此变体(与上述不同)忽略输入数组中的 NULL 值。

【讨论】:

感谢您的回复。将 IN 列类型设置为“text[]”是我没有尝试过的。我以为我可以传入一组文本值,但显然不行。 @user2254435:如果您更容易将逗号分隔的字符串作为text 传递,您可以这样做,并使用string_to_array() 将其转换为函数内部的数组。如果您的列表很长,使用LEFT JOIN / IS NULL 的性能会更好。我在答案中添加了演示代码。 你可以使用WHERE q.code = ANY($1)获取q.code IN [...]的行为

以上是关于将数组文字传递给 PostgreSQL 函数的主要内容,如果未能解决你的问题,请参考以下文章

将数组传递给 PostgreSQL PL/pgSQL 函数

在 Java 中创建一个 bytea 数组以传递给 Postgresql 存储过程

将数组值从 JPA/Hibernate 传递给 PostgreSQL

将表传递给 postgreSQL 函数,执行 select 语句,返回表

为啥 PHP 在一种情况下允许将文字传递给按引用传递的参数,而在其他情况下不允许?

将指向文字的指针直接传递给函数[复制]