0

我可以将表和函数定义为:

CREATE TABLE mytable
(
  mycol integer
);

INSERT INTO mytable VALUES (1);

CREATE OR REPLACE FUNCTION myfunction (l_myvar integer) RETURNS mytable AS $$

DECLARE
l_myrow mytable;

BEGIN

SELECT      *
INTO        l_myrow
FROM        mytable
WHERE       mycol = l_myvar;

RETURN l_myrow;

END;
$$ LANGUAGE plpgsql;

在这种情况下, l_myvar 充当我调用时传递的值的绑定变量:

SELECT * FROM myfunction(1);

并返回 mycol = 1 的行

If I redefine the function as:

CREATE OR REPLACE FUNCTION myfunction (l_myvar integer) RETURNS mytable AS $$

DECLARE
l_myrow mytable;

BEGIN

SELECT      *
INTO        l_myrow
FROM        mytable
WHERE       mycol IN (l_myvar);

RETURN l_myrow;

END;
$$ LANGUAGE plpgsql;

SELECT * FROM myfunction(1);

仍然返回 mycol = 1 的行

但是,如果我现在更改函数定义以允许我传递一个整数数组并在 IN 子句中尝试这个数组,我会收到一个错误:

CREATE OR REPLACE FUNCTION myfunction (l_myvar integer[]) RETURNS mytable AS $$

DECLARE
l_myrow mytable;

BEGIN

SELECT      *
INTO        l_myrow
FROM        mytable
WHERE       mycol IN (array_to_string(l_myvar, ','));

RETURN l_myrow;

END;
$$ LANGUAGE plpgsql;

分析表明,虽然:

SELECT array_to_string(ARRAY[1, 2], ',');

按预期返回 1,2

SELECT * FROM myfunction(ARRAY[1, 2]);

返回错误

operator does not exist: integer = text

在线:

WHERE       mycol IN (array_to_string(l_myvar, ','));

如果我执行:

SELECT      *
FROM        mytable
WHERE       mycol IN (1,2);

我得到了预期的结果。

鉴于 array_to_string(l_myvar, ',') 如图所示,计算结果为 1,2,为什么这些语句不等效。

从错误消息来看,这与数据类型有关,但 IN(variable) 构造似乎与 = 变量构造的行为不同?

这里有什么规则?

我知道我可以构建一个 EXECUTE 语句,将所有内容都视为字符串,以实现我想要做的事情,所以我不会将其作为解决方案。我确实想了解此示例中发生了什么。是否对这种方法进行了修改以使其工作,具体示例是传入一组值以构建动态 IN 子句而不诉诸 EXECUTE?

提前致谢

克雷格

4

1 回答 1

2

这个:

SELECT array_to_string(ARRAY[1, 2], ',');

不会产生 SQL 列表1,2,而是产生 SQL字符串 '1,2'。所以当你这样做时:

WHERE mycol IN (array_to_string(l_myvar, ','));

你是说:

where mycol in (some_string)

因为mycol是一个整数,所以你会得到错误

运算符不存在:整数 = 文本

因为您实际上是在尝试比较整数和字符串。

如果我们查看手册,我们会看到:

9.23.1。在

expression IN (value [, ...])

右侧是标量表达式的括号列表。

因此,您需要提供IN一个带括号的标量表达式列表,而带括号的字符串是一个带括号的标量表达式列表(带有一个元素),您仍在尝试比较整数和字符串,但这是行不通的。

如果你想使用数组,你可以使用= ANY

WHERE mycol = any (l_myvar)

您可以在我上面链接的文档中查找 ANY 和 SOME 。

我想一个执行摘要将是:

字符串是字符串,SQL 是 SQL,如果要将字符串视为 SQL,则使用 E​​XECUTE。

于 2013-10-18T03:49:44.967 回答