NULL emements铸造UNNEST的结果时,会丢失() [英] NULL emements lost when casting result of unnest()

查看:157
本文介绍了NULL emements铸造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 expected

 i
---
 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) with A)

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 with B).

As expected, we have seen the NULL element in the array resulting in a row with a NULL 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 in NULL elements being preserved.
Except that varchar[] -> text and vice versa trashes this little hypothesis of mine. Or varchar and text differ more than I thought.

Tested with PostgreSQL 9.1 and 9.2. Identical results.
-> SQLfiddle

Questions

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆