将数组从 node-postgres 传递给 plpgsql 函数

Posted

技术标签:

【中文标题】将数组从 node-postgres 传递给 plpgsql 函数【英文标题】:Pass array from node-postgres to plpgsql function 【发布时间】:2012-10-30 22:48:09 【问题描述】:

plpgsql函数:

CREATE OR REPLACE FUNCTION testarray (int[]) returns int as $$
  DECLARE
    len int;
  BEGIN
    len := array_upper($1);
  return len;
  END
$$ language plpgsql;

node-postgres 查询 + 测试数组:

var ta = [1,2,3,4,5];
client.query('SELECT testarray($1)', [ta], function(err, result) 
  console.log('err: ' + err);
  console.log('result: ' + result);
);

节点服务器的输出:

错误:错误:数组值必须以“”或维度信息开头 结果:未定义

我还尝试在客户端查询中转换参数,如 testarray($1::int[]),它返回了相同的错误。

我把函数参数改成了(anyarray int),输出错误也改了:

错误:错误:整数的输入语法无效:“1,2,3,4,5” 结果:未定义

以及其他几个变体。

我寻找不产生错误并返回 5 的变体。

我读到了Postgres parse-array issue 和这个关于 node-postgres 中参数化数组的 *** 问题:

node-postgres: how to execute "WHERE col IN (<dynamic value list>)" query?

但似乎没有答案。

【问题讨论】:

【参考方案1】:

参数必须是以下形式之一:

'1,2,3,4,5'         -- array literal
'1,2,3,4,5'::int[]  -- array literal with explicit cast
ARRAY[1,2,3,4,5]      -- array constructor

另外,你可以简化你的功能:

CREATE OR REPLACE FUNCTION testarray (int[])
  RETURNS int AS
$func$
BEGIN
  RETURN array_length($1, 1);
END
$func$ LANGUAGE plpgsql IMMUTABLE;

或者一个简单的SQL函数:

CREATE OR REPLACE FUNCTION testarray2 (int[])
  RETURNS int AS 'SELECT array_length($1, 1)' LANGUAGE sql IMMUTABLE;

或者直接使用array_length($1, 1)

array_upper()错误 函数。数组可以有任意下标。 array_length() 可以满足您的需求。相关问题:

Normalize array subscripts for 1-dimensional array so they start with 1

array_length()array_upper() 都需要 两个 参数。第二个是数组维度-在您的情况下为1

【讨论】:

感谢您对阵列的了解。我一直在文档中转圈。我设法让所有这些变体在 node-postgres 中都未参数化。感谢您提供有关 array_length 的详细信息。【参考方案2】:

感谢 PinnyM 和 Erwin 的回复。我查看了选项并重新阅读了相关答案。

Erwin 描述的数组格式在 node-postgres 中的工作方式如下:

'select testarray(' + "'1,2,3,4,5'" + ')'
'select testarray(' + "'1,2,3,4,5'" + '::INT[])'
'select testarray(ARRAY[1,2,3,4,5])'

javascript quoting的tl:dr

在 node-postgres 中参数化它们: (基于this answer)

var ta = [1,2,3,4,5];
var tas = '' + ta.join() + '';

...skipped over the pg connect code

client.query("select testarray($1)", [tas] ...
client.query("select testarray($1::int[])", [tas] ...
not sure about the ARRAY constructor.

【讨论】:

【参考方案3】:

根据您发布的答案,这可能对您有用:

var ta = [1,2,3,4,5];
var params = [];
for(var i = 1, i <= ta.length; i++) 
    params.push('$'+i);

var ta = [1,2,3,4,5];
client.query('SELECT testarray(\'' + params.join(', ') + '\')', ta, function(err, result) 
  console.log('err: ' + err);
  console.log('result: ' + result);
);

【讨论】:

它会从 postgresql 产生一个新错误:在“”处或附近出现语法错误 对了,我忘了它需要用引号括起来。已更新。 那也没用。起作用的是:client.query("select testarray($1::int[])", [ta], ...etc 这会带来极大的安全风险! @MilesRout 你能澄清一下吗?加入的参数是服务器生成的 - 问题是传递的参数数组的长度吗?

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

将数据集合从 .NET 传递给 PL/SQL 包过程或函数?

将数组传递给 Oracle 函数

将 oracle.sql.ARRAY 传递给 PL/SQL 过程时设置时区

如何传递从多个表创建的 PL/SQL 游标记录?

Node-Postgres/Knex 在 JS 中返回 CITEXT[] 作为字符串,而不是字符串数组

oracle pl/sql 将异常类型传递给函数