【问题标题】:Unneccesary postgres array casting required?需要不必要的 postgres 数组转换?
【发布时间】:2014-12-03 14:38:32
【问题描述】:

在 Postgres 9.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[]?没有意义。

【问题讨论】:

    标签: arrays postgresql casting any


    【解决方案1】:

    内部选择的结果 (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 -- 并返回 1 行。如果您尝试将 z 强制转换为 integer[] 它将不起作用 - 因为 FROM 子句需要一个结果集,而不是一个整数数组。

    但是,可以将包含一行一列的结果集转换为该单例类型的实例(在本例中为integer[])。这消除了“我正在查看此子查询的任何行”与“我正在查看此子查询的单行/列的数组”之间的歧义。

    因此,需要显式转换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-25
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 1970-01-01
      相关资源
      最近更新 更多