加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

数组 – 在转换unfst()的结果时丢失了NULL数字

发布时间:2020-12-13 16:08:44 所属栏目:百科 来源:网络整理
导读:在扩展阵列后进行投射时,我偶然发现了 unnest() 的非常奇怪的行为. 介绍 使用unnest()有三种基本语法变体: 1)SELECT unnest(‘{1,NULL,4}’:: int [])AS i; 2)SELECT i FROM unnest(‘{2,4}’:: int [])AS i; 3)SELECT i FROM(SELECT unnest(‘{3,4}’:: in
在扩展阵列后进行投射时,我偶然发现了 unnest()的非常奇怪的行为.

介绍

使用unnest()有三种基本语法变体:

1)SELECT unnest(‘{1,NULL,4}’:: int [])AS i;
2)SELECT i FROM unnest(‘{2,4}’:: int [])AS i;
3)SELECT i FROM(SELECT unnest(‘{3,4}’:: int []))AS t(i);

所有这些都包含一个在结果中按预期方式为NULL的行

i
---
 1
(null)
 4

要将数组元素转换为其他类型,可以在扩展数组后立即将元素转换为基本类型,或者在展开之前将数组本身转换为其他数组类型.第一个变体对我来说似乎有点简单和简短:

A)SELECT unnest(‘{4,1}’:: int []):: text;
B)SELECT unnest(‘{4,2}’:: int [] :: text []);

i
---
 4
(null)
 1

奇怪的行为

可能的所有组合除2A)

由于某种原因,不能将2)与A)结合起来

SELECT * FROM unnest('{2,1}'::int[])::text;

ERROR: syntax error at or near “::”

我可以接受.一个罕见的角落案例,由于某种原因尚未实施.
然而,所有其他组合飞行:

1A)SELECT unnest(‘{1,1}’:: int []):: text AS i;
2A)SELECT i FROM unnest(‘{2,1}’:: int []):: text AS i;
3A)SELECT i FROM(SELECT unnest(‘{3,1}’:: int []):: text)AS t(i);
1B)SELECT unnest(‘{1,2}’:: int [] :: text [])AS i;
2B)SELECT i FROM unnest(‘{2,2}’:: int [] :: text [])AS i;
3B)SELECT i FROM(SELECT unnest(‘{3,2}’:: int [] :: text []))AS t(i);

与上述结果相同.

真奇怪的行为

以下观察仅涉及A).用B)代替可以避免这个问题.

正如预期的那样,我们已经看到数组中的NULL元素导致到目前为止在所有查询中都有一个具有NULL值的行.但是,将某些数组类型的结果转换为某些基类型时,情况并非如此.

这里具有NULL值的行突然消失(!):

SELECT unnest('{1,4}'::int[])::int8;

 i
---
 1
 4

例子

我去看兔子洞有多深.这里有些例子:

NULL消失:

SELECT unnest('{1,1}'::int[])::int2;
SELECT unnest('{1,2}'::int[])::int8;
SELECT unnest('{1,3}'::int[])::real;
SELECT unnest('{1,4}'::int[])::float8;
SELECT unnest('{1,5}'::int[])::numeric;
SELECT unnest('{1,6}'::numeric[])::int2;
SELECT unnest('{1,7}'::numeric[])::int8;
SELECT unnest('{1,8}'::numeric[])::real;
SELECT unnest('{1,9}'::numeric[])::float8;
SELECT unnest('{1,a}'::text[])::char;
SELECT unnest('{1,b}'::text[])::char(1);
SELECT unnest('{1,c}'::text[])::varchar(10);      -- !!!
SELECT unnest('{1,d}'::varchar[])::varchar(10);   -- !!!
SELECT unnest('{2013-1-1,2013-1-1}'::date[])::timestamp;
SELECT unnest('{2013-1-1,2013-1-1}'::timestamp[])::date;
SELECT unnest('{23:11,23:11}'::time[])::interval;
SELECT unnest('{23:11,23:11}'::interval[])::time;

NULL保持:

SELECT unnest('{1,1}'::int[])::int4;    -- is really from int to int
SELECT unnest('{1,2}'::int[])::text;
SELECT unnest('{1,3}'::int8[])::text;
SELECT unnest('{1,4}'::numeric[])::text;
SELECT unnest('{1,5}'::text[])::int;
SELECT unnest('{1,6}'::text[])::int8;
SELECT unnest('{1,7}'::text[])::numeric;
SELECT unnest('{1,8}'::text[])::varchar;    -- !!!
SELECT unnest('{1,9}'::varchar[])::text;    -- !!!
SELECT unnest('{2013-1-1,2013-1-1}'::date[])::text;
SELECT unnest('{2013-1-1,2013-1-1}'::text[])::date;
SELECT unnest('{23:11,23:11}'::time[])::text;
SELECT unnest('{23:11,23:11}'::text[])::time;

这似乎是不可接受的.

在测试了很多组合后,模式似乎是:

在相关类型之间转换会导致NULL元素丢失.
在不相关的类型之间转换会导致保留NULL元素.
除了varchar [] – >文本,反之亦然,破坏了我的这个小假设.或varchar和文本的差异比我想象的要多.

使用PostgreSQL 9.1和9.2进行测试.相同的结果.
-> SQLfiddle

问题

我在这里错过了什么吗?有人可以解释这种行为吗?
如果没有,问题就变成了:我应该在文件中提交错误报告吗?

解决方法

不支持转换SRF函数(在FROM子句中) – 您不能在那里使用任何运算符.只允许函数调用.

只能在列列表中进行强制转换:

postgres=# SELECT * FROM unnest('{2,1}'::int[])::text;
ERROR:  syntax error at or near "::"
LINE 1: SELECT * FROM unnest('{2,1}'::int[])::text;
                                                 ^
postgres=# SELECT v::text FROM unnest('{2,1}'::int[]) g(v);
   v    
────────
      2
 [null]
      1
(3 rows)

从NULL中丢失的行可能是错误,应该报告

postgres=# SELECT unnest('{1,4}'::int[])::text;
 unnest 
────────
      1
 [null]
      4
(3 rows)

postgres=# SELECT unnest('{1,4}'::int[])::numeric;
 unnest 
────────
      1
      4
(2 rows)

我认为没有理由,为什么应该删除NULL行

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读