SQL Server中的地理数据类型与几何数据类型

时间:2013-02-04 18:53:10

标签: sql geometry geospatial sql-server-2012 geography

环境:SQL Server 2012 我正在使用一个在线工具,这是迄今为止我唯一能找到的工具,用于绘制地球上的多边形和点。 http://www.birdtheme.org/useful/googletool.html 我有两张桌子。一个存储“区域”作为多边形,另一个表存储与我的问题无关的其他事项。 为简单起见,我只是将我的场景减少为sql变量。

在下面的查询中,我将地理数据类型用于众所周知的兴趣点。 我在罗本岛周围绘制了一个多边形,罗本岛上的一个点和恶魔城的一个点。

DECLARE @robben_island geography = ('POLYGON((18.351803 -33.788421,18.382788 -33.787494,18.386736 -33.820515,18.354464 -33.822369,18.351803 -33.788421))')
DECLARE @point_in_robben_island geography= ('POINT(18.369226 -33.80554)')
DECLARE @point_in_alcatraz geography= ('POINT(-122.423401 37.827006)')

SELECT @robben_island.STContains(@point_in_robben_island)   --returns 'False', but it's not what I expected
SELECT @robben_island.STContains(@point_in_alcatraz)        --returns 'True', but it's not what I expected

如果我理解正确的话,上面的这个查询会告诉我@point_in_robben_island中没有@robben_island,而@robben_island中我的@point_in_alcatraz存在,我们都知道,不是真的。

现在当我将数据类型从地理位置更改为几何图形时,一切正常,但我担心如果我继续使用几何数据类型,我可能会遇到一些问题。我只是想知道几何不能完全解释地球的曲率这一事实是否会受到负面影响。触摸木材。

DECLARE @robben_island geometry = ('POLYGON((18.351803 -33.788421,18.382788 -33.787494,18.386736 -33.820515,18.354464 -33.822369,18.351803 -33.788421))')
DECLARE @point_in_robben_island geometry= ('POINT(18.369226 -33.80554)')
DECLARE @point_in_alcatraz geometry= ('POINT(-122.423401 37.827006)')

SELECT @robben_island.STContains(@point_in_robben_island)   --returns 'True' as it should
SELECT @robben_island.STContains(@point_in_alcatraz)        --returns 'False' as it should

现在我的问题是,为什么地理数据类型会在几何体按预期工作时返回意外结果?非常感谢你。

1 个答案:

答案 0 :(得分:5)

地理类型比几何更具限制性。它不能穿过不同的半球,外环必须逆时针绘制。

不幸的是(有些人觉得这很好),SQL Server 2012在创建无效的地理位置时不再引发错误。您需要反转Roben Island几何中的点的顺序,例如:

DECLARE @robben_island geography = ('POLYGON((18.351803 -33.788421, 18.354464 -33.822369,18.386736 -33.820515, 18.382788 -33.787494, 18.351803 -33.788421))')
DECLARE @point_in_robben_island geography= ('POINT(18.369226 -33.80554)')
DECLARE @point_in_alcatraz geography= ('POINT(-122.423401 37.827006)')

SELECT @robben_island.STContains(@point_in_robben_island)   --returns 'True'
SELECT @robben_island.STContains(@point_in_alcatraz)        --returns 'False'