关于“NULL索引表键值”错误的一点说明
1、错误说明
A和B是两张空间表,均含有SDE.ST_GEOMETRY类型的字段(字段名为shape)。当对这两张表进行空间查询:
select * from a,b where sde.st_intersects(a.shape,b.shape)=1;
报了如下的错误:
其实错误提示信息也很明确了:在查询索引表时,当赋予的键值为NULL时,ODCIIndexFetch()会抛出异常。空间索引的键值是根据geometry的范围计算得到的外包矩形,即一个矩形范围,当geometry自身为null时,外包矩形自然也是null,此时就产生了NULL索引表键值的错误。
2、错误分析
错误提示倒是好理解,现在我们需要知道到底是哪些记录的shape字段为空,进而导致了上图所见的异常,于是发出查询:
Select objectid, shape as sp from a where sde.st_isempty(shape)=1;
Select objectid, shape as sp from b where sde.st_isempty(shape)=1;
返回结果都是空的。但我们去看数据,却发现B表中有一条记录的shape字段明明是空的呀,如下图OBJECTID=18684的记录:
怎么回事?
……
那换一个写法试试:
咦,换个写法竟然查出来了。那么sde.st_isempty到底是在查什么呢?我们来看一下这个方法的具体实现:
当shape字段的geometry为null时,直接返回null;当numpts属性>0或len属性>0时,图形非空,返回0;其他情况图形为空,返回1。原来这里的isempty和null是不同的语义。
下面,我们分别制造一个null的图形和空的图形。
1)当shape字段未赋值时,shape字段的geometry为null。此时sde.st_isempty得到的结果即不是0也不是1,而是null。我们来验证一下:
这里有个疑问:当geometry为null时,会报上图的异常吗?答案是:会的,这种情况下会报"NULL索引表键值"错误。
2)当为shape字段赋予一个numpts=0的空图形(可通过如下方法构造一个空图形)
此时sde.st_isempty得到的结果是1。我们来验证一下:
这里也有个疑问:当geometry为空时,会报上图的异常吗?答案是:也会的,这种情况下也会报"NULL索引表键值"错误。
3、总结
1)当ORACLE SQL的执行计划使用空间索引时,若向空间索引传入了null图形或空图形,会产生ORA-06502:"NULL索引表键值"异常。
例如执行SQL:
Select * from a,b where sde.st_intersects(a.shape,b.shape)=1;
若执行计划使用了A表的空间索引,且B表记录中存在null图形或空图形,会产生上述异常。
2)sde.st_isempty=1的图形与null是不同的语义,代表了不同的含义。