在Postgres9.3中有以下设置:

CREATE TABLE t (id INTEGER);
INSERT INTO t VALUES (1), (2), (3);

我将这些值聚合到数组中(不要问为什么,实际的设置非常复杂,所以我只需要这种方法)。
现在我需要检查某个整数是否属于数组。试过这个:
SELECT 1=ANY((SELECT array_agg(id) FROM t))

获取错误:
ERROR:  operator does not exist: integer = integer[]
LINE 1: SELECT 1=ANY((SELECT array_agg(id) FROM t))
                ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

经过一些实验,找到了一个可行的解决方案:
SELECT 1=ANY((SELECT array_agg(id) FROM t)::integer[])

为什么postgres要求我将integer[]转换为integer[]?没有道理。

最佳答案

内部选择(SELECT array_agg(id) FROM t)的结果不是一个integer[]它是一个包含一行integer[]的结果集。
你可以用两种方式揭露发生的事情。
如果你试着
SELECT 1=ANY((SELECT array_agg(id) FROM t)::text[]);
错误消息是
ERROR: operator does not exist: integer = text
请注意,错误消息不是指text[],而是指text
这是因为等式将左参数与右参数的每个元素进行比较。因此,在原始查询中,它是integer[]的一个结果集,它试图将1与每个结果集(您只有一个)进行比较。
另一种方法是反思
integer[]
这会将原始子查询嵌入为select count(*) from (select array_agg(id) from t) as z——并返回一行。如果尝试将z强制转换为z则无法工作,因为FROM子句需要resultset,而不是整数数组。
但是,可以将包含一行一列的resultset强制转换为该singleton类型的实例(在本例中为integer[])。这消除了“我正在查找此子查询的任何行”与“我正在查找此子查询的单个行/列的数组”之间的歧义。
因此,需要显式转换。

关于arrays - 是否需要不必要的postgres数组转换?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27274400/

10-15 21:10