In my case, I have an issue in my data where selecting WHERE SHAPE IS NULL actually selects rows where shape is not null.
It's a surprising issue; Oracle isn't querying the data correctly due to the SHAPE values being broken.
Esri Case #03477586
BUG-000115133: Incorrect result returned from query "shape is null" after migrating storage from sdelob to st_geometry and transferring Feature Class using Oracle datapump utility.
Best guess is:
My organization moved from SDEBINARY to ST_GEOMETRY as part of an old upgrade project from 9.3.1 to 10.x (7-8 years ago). The transition from SDEBINARY to ST_GEOMETRY must have broken the SHAPES. We don't have the SHAPE IS NULL issue in rows that were created after that migration; we only have the issue in old rows.
With this particular FC, we wouldn't have needed to update the rows using a field calculation, import/export, Catalog copy/paste, etc. Doing operations like that would automatically fix the shapes. Even a simple field calculation on a non-spatial field would automatically fix the shapes. But we likely didn't need to do that for this FC (whereas with other FCs, we do lots of field calculations on the entire table). So that's likely why we didn't catch the issue until now. Further, querying for WHERE SHAPE IS NULL is relatively rare.
So, in this particular scenario, I want to avoid SHAPE IS NULL, since that doesn't work properly (at least not until I fix all our old data). I'll use isEmpty to find null shapes instead:
where
(sde.st_isempty(a.shape) = 1
or sde.st_isempty(a.shape) is null)
For my notes, here is a screenshot of my testing data -- with state #3 split out into #3a and #3b:
select
a.objectid,
a.comment2 as state_num,
a.shape,
(a.shape).points as geometry,
sde.st_area(a.shape) as area,
sde.st_isempty(a.shape) as is_empty,
a.comment3,
case
when b.objectid is not null then 'NOT NULL'
when b.objectid is null then 'NULL'
end as null_flag_join, --I used a join for this since a regular case statement on table "a" doesn't produce the same result.
case
when a.shape is not null then 'NOT NULL'
when a.shape is null then 'NULL'
end as null_flag_case,
sde.st_numpoints(a.shape) as num_points
from
infrastr.inf_record_sp a
left join
(select objectid from infrastr.inf_record_sp where shape is not null) b
on a.objectid = b.objectid
where
a.comment2 in ('1','2','3a','3b','4')
order by
state_num