NULL emements铸造UNNEST的结果时,会丢失() [英] NULL emements lost when casting result of unnest()
问题描述
我偶然发现了与 <$ C $非常古怪的行为C> UNNEST() ,展开阵列后浇注时。
简介
有三种基本语法变体使用UNNEST():
1) SELECT UNNEST({1,NULL,4}':: INT [])正如我;
结果
2)选择,我从UNNEST({2,NULL,4}:: AS我INT []);
结果
3) SELECT我是从(选择UNNEST({3,NULL,4}':: INT []))AS T(I);
他们都包含在结果与 NULL
行如预期
我
---
1
(空值)
4
要投的数组元素为不同的类型,可以扩展的阵列后,投出的元素的为基本类型正确的,或施放的阵列<扩大前/ em>的本身不同的数组类型的 的。第一个变种似乎稍微简单和更短的对我说:
A) SELECT UNNEST({4,NULL,1}':: INT [])::文本;
结果
B) SELECT UNNEST({4,NULL,2}:: INT [] ::文[]);
我
---
4
(空值)
1
古怪的行为
所有可能的除了组合2A)
由于某种原因我们不能将 2)
与 A)
SELECT * FROM UNNEST({2,NULL,1}':: INT [])::文本;
错误:语法错误或接近::
块引用>我可以接受。尚未出于某种原因,执行一种罕见的极端状况。结果
所有其他组合飞行,虽然:1A)
如上SELECT UNNEST({1,NULL,1}':: INT [])::文本作为我;
结果
<击> 2A)选择,我从UNNEST({2,NULL,1}':: INT [])::文本作为我;
击>
3A)SELECT我是从(选择UNNEST({3,NULL,1}':: INT [])::文)为T(I);
结果
1B)SELECT UNNEST({1,NULL,2}:: INT [] ::文本[])正如我;
结果
2B)选择,我从UNNEST({2,NULL,2}:: INT [] ::文本[])正如我;
结果
3B)SELECT我是从(选择UNNEST({3,NULL,2}:: INT [] ::文[])作为T(I));
同样的结果。
真是奇怪的行为
以下意见关注
避免问题A)
独占。人们可以通过B代替)
。正如预期的那样,我们已经看到在数组中导致与在
NULL
值的行的NULL
元素所有查询为止。然而,这是不是从铸造时的结果的情况下的部分数组类型为部分基本类型。下面的 NULL值的行突然消失(!):
SELECT UNNEST({1,NULL,4}':: INT []):: INT8; 一世
---
1
4示例
我去看的有多深兔子洞进入的。下面是一些例子:
NULL
消失:SELECT UNNEST({1,NULL,1}':: INT []):: INT2;
SELECT UNNEST({1,NULL,2}:: INT []):: INT8;
SELECT UNNEST({1,NULL,3}:: INT [])::实;
SELECT UNNEST({1,NULL,4}':: INT []):: float8的;
SELECT UNNEST({1,NULL,5}':: INT [])::数字;
SELECT UNNEST({1,NULL,6}'::数字[]):: INT2;
SELECT UNNEST({1,NULL,7}'::数字[]):: INT8;
SELECT UNNEST({1,NULL,8}'::数字[])::实;
SELECT UNNEST({1,NULL,9}'::数字[]):: float8的;
SELECT UNNEST({1,NULL,一个}'::文[])::字符;
SELECT UNNEST({1,NULL,B}'::文[]):: CHAR(1);
SELECT UNNEST({1,NULL,C}'::文[]):: VARCHAR(10); - !
SELECT UNNEST({1,NULL D}'::的varchar []):: VARCHAR(10); - !
SELECT UNNEST({2013年1月1日,NULL,2013年1月1日}'::日期[])::时间戳;
SELECT UNNEST({2013年1月1日,NULL,2013年1月1日}'::时间戳[])::日期;
SELECT UNNEST({23:11,NULL,23:11}'::时间[])::区间;
SELECT UNNEST({23:11,NULL,23:11}'::区间[])::时间;
NULL
停留SELECT UNNEST({1,NULL,1}':: INT []):: INT4; - 真的是从int到int
SELECT UNNEST({1,NULL,2}:: INT [])::文本;
SELECT UNNEST({1,NULL,3}:: INT8 [])::文本;
SELECT UNNEST({1,NULL,4}'::数字[])::文本;
SELECT UNNEST({1,NULL,5}'::文[]):: INT;
SELECT UNNEST({1,NULL,6}'::文[]):: INT8;
SELECT UNNEST({1,NULL,7}'::文[])::数字;
SELECT UNNEST({1,NULL,8}'::文[]):: VARCHAR; - !
SELECT UNNEST({1,NULL,9}':: VARCHAR [])::文本; - !
SELECT UNNEST({2013年1月1日,NULL,2013年1月1日}'::日期[])::文本;
SELECT UNNEST({2013年1月1日,NULL,2013年1月1日}'::文[])::日期;
SELECT UNNEST({23:11,NULL,23:11}'::时间[])::文本;
SELECT UNNEST({23:11,NULL,23:11}'::文[])::时间;这似乎是不可接受的。
测试相当多的组合后,将图案似乎是:
在相关类型结果之间铸造
NULL
元素丢失。结果
在NULL
无关类型的结果之间进行转换元件是preserved。结果
除VARCHAR []
- >文本
,反之亦然象垃圾一样清除我的这个小假说。或VARCHAR
和文本
不同的比我想象的多。在PostgreSQL 9.1和9.2测试。相同的结果。结果
- > SQLfiddle问题
我失去了一些东西在这里?有人可以解释这种现象?结果
?
如果不是这样,问题就变成了:我应该继续一个文件中的错误报告解决方案铸造SRF功能(在FROM子句中)不支持 - 你不能使用任何运营商那里。只有函数调用是允许的。
铸造仅在列的列表是可能的:
的Postgres =#SELECT * FROM UNNEST({2,NULL,1}':: INT [])::文本;
错误:达到或接近语法错误::
LINE 1:SELECT * FROM UNNEST({2,NULL,1}':: INT [])::文本;
^
Postgres的=#SELECT v ::本文从UNNEST({2,NULL,1}':: INT [])G(V);
v
────────
2
[空值]
1
(3行)从NULL缺失的行可能是错误,应报告
的Postgres =#SELECT UNNEST({1,NULL,4}':: INT [])::文本;
UNNEST
────────
1
[空值]
4
(3行)Postgres的=#SELECT UNNEST({1,NULL,4}':: INT [])::数字;
UNNEST
────────
1
4
(2行)有没有道理,为什么空行应该被丢弃,我觉得
I stumbled upon very odd behavior with
unnest()
, when casting after expanding an array.Introduction
There are three basic syntax variants to use unnest():
1)
SELECT unnest('{1,NULL,4}'::int[]) AS i;
2)SELECT i FROM unnest('{2,NULL,4}'::int[]) AS i;
3)SELECT i FROM (SELECT unnest('{3,NULL,4}'::int[])) AS t(i);
All of them include a row with
NULL
in the result as expectedi --- 1 (null) 4
To cast the array elements to a different type, one can cast the elements to a basic type right after expanding the array, or cast the array itself to a different array type before expanding. The first variant seemed slightly simpler and shorter to me:
A)
SELECT unnest('{4,NULL,1}'::int[])::text;
B)SELECT unnest('{4,NULL,2}'::int[]::text[]);
i --- 4 (null) 1
Odd behaviour
All combinations possible except
2A)
For some reason one cannot combine
2)
withA)
SELECT * FROM unnest('{2,NULL,1}'::int[])::text;
ERROR: syntax error at or near "::"
I can accept that. A rare corner case that has not been implemented for some reason.
All other combinations fly, though:1A)
SELECT unnest('{1,NULL,1}'::int[])::text AS i;
2A)SELECT i FROM unnest('{2,NULL,1}'::int[])::text AS i;
3A)SELECT i FROM (SELECT unnest('{3,NULL,1}'::int[])::text) AS t(i);
1B)SELECT unnest('{1,NULL,2}'::int[]::text[]) AS i;
2B)SELECT i FROM unnest('{2,NULL,2}'::int[]::text[]) AS i;
3B)SELECT i FROM (SELECT unnest('{3,NULL,2}'::int[]::text[])) AS t(i);
Same result as above.
Really odd behaviour
The following observations concern
A)
exclusively. One can avoid the problem by substituting withB)
.As expected, we have seen the
NULL
element in the array resulting in a row with aNULL
value in all queries so far. However, this is not the case when casting the results from some array types to some base types.Here the row with the NULL value suddenly disappears (!):
SELECT unnest('{1,NULL,4}'::int[])::int8; i --- 1 4
Examples
I went to see how deep the rabbit hole goes. Here are some examples:
NULL
disappears:SELECT unnest('{1,NULL,1}'::int[])::int2; SELECT unnest('{1,NULL,2}'::int[])::int8; SELECT unnest('{1,NULL,3}'::int[])::real; SELECT unnest('{1,NULL,4}'::int[])::float8; SELECT unnest('{1,NULL,5}'::int[])::numeric; SELECT unnest('{1,NULL,6}'::numeric[])::int2; SELECT unnest('{1,NULL,7}'::numeric[])::int8; SELECT unnest('{1,NULL,8}'::numeric[])::real; SELECT unnest('{1,NULL,9}'::numeric[])::float8; SELECT unnest('{1,NULL,a}'::text[])::char; SELECT unnest('{1,NULL,b}'::text[])::char(1); SELECT unnest('{1,NULL,c}'::text[])::varchar(10); -- !!! SELECT unnest('{1,NULL,d}'::varchar[])::varchar(10); -- !!! SELECT unnest('{2013-1-1,NULL,2013-1-1}'::date[])::timestamp; SELECT unnest('{2013-1-1,NULL,2013-1-1}'::timestamp[])::date; SELECT unnest('{23:11,NULL,23:11}'::time[])::interval; SELECT unnest('{23:11,NULL,23:11}'::interval[])::time;
NULL
stays:SELECT unnest('{1,NULL,1}'::int[])::int4; -- is really from int to int SELECT unnest('{1,NULL,2}'::int[])::text; SELECT unnest('{1,NULL,3}'::int8[])::text; SELECT unnest('{1,NULL,4}'::numeric[])::text; SELECT unnest('{1,NULL,5}'::text[])::int; SELECT unnest('{1,NULL,6}'::text[])::int8; SELECT unnest('{1,NULL,7}'::text[])::numeric; SELECT unnest('{1,NULL,8}'::text[])::varchar; -- !!! SELECT unnest('{1,NULL,9}'::varchar[])::text; -- !!! SELECT unnest('{2013-1-1,NULL,2013-1-1}'::date[])::text; SELECT unnest('{2013-1-1,NULL,2013-1-1}'::text[])::date; SELECT unnest('{23:11,NULL,23:11}'::time[])::text; SELECT unnest('{23:11,NULL,23:11}'::text[])::time;
This seems unacceptable.
After testing quite a few combinations, the pattern seems to be:
Cast between related types results in
NULL
elements being lost.
Cast between unrelated types results inNULL
elements being preserved.
Except thatvarchar[]
->text
and vice versa trashes this little hypothesis of mine. Orvarchar
andtext
differ more than I thought.Tested with PostgreSQL 9.1 and 9.2. Identical results.
-> SQLfiddleQuestions
Am I missing something here? Can someone explain this behaviour?
If not, the question becomes: Should I go ahead an file a bug report?解决方案Casting SRF function (in FROM clause) is not supported - you cannot use any operator there. Only function call is allowed.
a cast is possible only in column list:
postgres=# SELECT * FROM unnest('{2,NULL,1}'::int[])::text; ERROR: syntax error at or near "::" LINE 1: SELECT * FROM unnest('{2,NULL,1}'::int[])::text; ^ postgres=# SELECT v::text FROM unnest('{2,NULL,1}'::int[]) g(v); v ──────── 2 [null] 1 (3 rows)
Missing row from NULL is probably bug and should be reported
postgres=# SELECT unnest('{1,NULL,4}'::int[])::text; unnest ──────── 1 [null] 4 (3 rows) postgres=# SELECT unnest('{1,NULL,4}'::int[])::numeric; unnest ──────── 1 4 (2 rows)
There is not reason, why NULL rows should be dropped, I think
这篇关于NULL emements铸造UNNEST的结果时,会丢失()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!