當我在展開數組之後進行強制轉換時,我偶然發現了一個非常奇怪的行爲unnest()
。當uncast拋出結果時丟失NULL emements()
介紹
有三種基本的語法變種使用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);
它們都包括與NULL
行在預期的結果
要投射的數組元素爲不同的類型,可以右擴大陣列後鑄元件爲基本型,或擴大之前陣列本身轉換爲不同的陣列型。第一個變種似乎稍微簡單和更短的對我說:
A)SELECT unnest('{4,NULL,1}'::int[])::text;
B)SELECT unnest('{4,NULL,2}'::int[]::text[]);
i
---
4
(null)
1
古怪的行爲
所有可能的組合,除了2A)
出於某種原因,缺一不可結合2)
與A)
SELECT * FROM unnest('{2,NULL,1}'::int[])::text;
ERROR: syntax error at or near "::"
我可以接受。一個罕見的角落案件,由於某種原因尚未實施。
所有其他組合飛,雖然:
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);
相同的結果以上。
非常奇怪的行爲
以下意見涉及A)
獨佔。用B)
代替可以避免這個問題。
正如預期的那樣,我們已經看到數組中的NULL
元素導致所有查詢中的值爲NULL
。但是,在將結果從某些陣列類型投射到某些基本類型時,情況並非如此。
這裏與NULL值的行突然消失(!):
SELECT unnest('{1,NULL,4}'::int[])::int8;
i
---
1
4
例子
我去看兔子洞有多深。下面是一些例子:
NULL
消失:
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
住宿:
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;
這似乎是不可接受的。
測試相當多的組合後,該模式似乎是:丟失在NULL
元素相關類型結果之間
演員。
在不相關類型之間進行投射會導致NULL
元素被保留。
除了varchar[]
- >text
,反之亦然會破壞我的這個小小的假設。或者varchar
和text
的差異比我想象的要多。
使用PostgreSQL 9.1和9.2進行測試。相同的結果。
-> SQLfiddle
問題
我失去了一些東西在這裏?有人可以解釋這種行爲嗎?
如果沒有,問題就變成了:我應該在文件中提交一個錯誤報告嗎?
謝謝,帕維爾。我將提交第二部分的錯誤報告。 – 2013-05-09 22:42:46
[我報告了錯誤,Tom Lane立即發現並解決了這個問題](http://www.postgresql.org/message-id/flat/[email protected]#E1Ub8p6-0006NC-Ja @ wrigleys.postgresql.org)。 Postgres 9.3不會出現這個錯誤,但他們沒有反補丁,所以不會破壞舊代碼。 – 2013-05-14 21:20:29