空间数据类型概述
适用于:Microsoft Fabric Microsoft Fabric SQL 数据库中Microsoft Fabric
Warehouse 中的 SQL Server
Azure SQL 数据库
Azure SQL 托管实例
SQL 分析终结点
有两种类型的空间数据。 geometry 数据类型支持平面或欧几里得(平面球)数据。 geometry 数据类型符合开放地理空间联盟 (OGC) 的 SQL 简单特征规范 1.1.0 版 并符合 SQL MM(ISO 标准)。
SQL Server 还支持 geography 数据类型,该数据类型可存储诸如 GPS 纬度和经度坐标之类的椭圆体(圆球)数据。
提示
SQL Server 空间工具是 Microsoft 赞助的开源工具集合,可与 SQL Server 中的空间类型一起。 此项目提供了一组可供应用程序使用的可重用函数。 这些函数可能包括数据转换例程、新转换、聚合等。有关更多详细信息,请参阅 GitHub 中的 Microsoft/SQLServerSpatialTools。
空间数据对象
geometry 和 geography 数据类型支持 16 种空间数据对象或实例类型。 但是,这些实例类型中只有 11 种“可实例化”;可以在数据库中创建并使用这些实例(或可对其进行实例化)。 这些实例的某些属性从其父级数据类型派生而来。
下图显示了几何图形和地理数据类型所基于的几何结构层次结构。 geometry 和 geography 的可实例化类型以蓝色表示。
地理数据类型还有一个额外的可实例化类型:FullGlobe。 只要特定实例的格式正确,即使未显式定义该实例,geometry 和 geography 类型也可识别该实例。 例如,如果使用方法显式定义 Point 实例,则只要方法输入格式良好,几何图形和地理将实例识别为 Point。 STPointFromText()
如果你使用 STGeomFromText()
方法定义了相同的实例,则 geometry 和 geography 数据类型都将该实例识别为 Point。
geometry 和 geography 类型的子类型分为简单类型和集合类型。 类似 STNumCurves()
的一些方法仅适用于简单类型。
简单类型:
集合类型:
geometry 和 geography 数据类型的差异
这两种类型的空间数据通常具有类似的行为方式。 在数据存储方式和操作方式上存在某些重要的差别。
如何定义连接边
用于 LineString 和 Polygon 类型的定义数据仅限顶点。 geometry 类型中两个顶点之间的连接边是直线。 但是,geography 类型中两个顶点之间的连接边是两个顶点之间的短的大椭圆弧。 大椭圆是具有穿过其中心的平面的椭圆体的相交部分。 大椭圆弧是大椭圆上的弧形线段。
如何定义圆弧线段
在 XY 笛卡尔坐标平面上定义 geometry 类型的圆弧线段(Z 值被忽略)。 geography 类型的圆弧线段由参考球上的曲线段定义。 参考球上的任何平行面可以由两个互补圆弧(两个弧的点有一个恒定的纬度角)定义。
空间数据类型中的度量
在平面(平面球)系统中,均以相同的度量单位为坐标测量距离和面积。 如果使用 geometry 数据类型,(2, 2) 和 (5, 6) 之间的距离为五个单位,与所用的单位无关。
在椭圆体(或圆球)系统中,坐标以经度和纬度的度数给定。 但是,长度和区域通常以米和平方米为单位测量,但度量可能取决于地理实例的空间引用标识符。 geography 数据类型最常见的度量单位为米。
空间数据的方向
在平面系统中,多边形的环方向并非重要因素。 SQL 规范的 OGC 简单特征未规定环顺序,并且 SQL Server 不会强制实施环的顺序。
在椭圆体系统中,没有方向的多边形无意义,或者模糊不清。 例如,赤道周围的环是否描述了北半球或南半球? 如果我们使用 geography 数据类型存储空间实例,必须指定环的方向并准确地描述实例的位置。
椭圆系统中的多边形的内部是由“左手定则”定义的:如果你想象自己沿着一个地理多边形的环行走,按照点的排列顺序,左边的区域被视为多边形的内部,右边的区域被视为多边形的外部。
在 SQL Server 中当兼容级别为 100 或更低时,geography 数据类型具有以下限制:
每个 geography 实例必须能够容纳在单个半球的内部。 任何大于半球的对象都无法存储。
使用开放地理空间联盟 (OGC) 熟知文本 (Well-Known Text, WKT) 或熟知二进制 (Well-Known Binary, WKB) 表示形式并且会产生大于一个半球的对象的任何 geography 实例都会引发一个 ArgumentException。
如果方法的结果不适合在单个半球内,则需要输入两个地理实例的地理数据类型方法(例如
STIntersection()
,STUnion()
STDifference()
和STSymDifference()
)将返回 null。STBuffer()
如果输出超过单个半球,也将返回 null。
在 SQL Server 中,FullGlobe 是一种特殊类型的多边形,涵盖了整个球体。 它有面积,但是没有边框或顶点。
geography
数据类型中的外环和内环
SQL 规范的 OGC 简单特征讨论了外环和内环,但此差别对 SQL Server geography 数据类型来说几乎毫无意义;多边形的任何环都可以作为外环。
有关 OGC 规范的详细信息,请参阅以下文档:
- OGC Specifications, Simple Feature Access Part 1 - Common Architecture(OGC 规范:简单特征访问第 1 部分 - 公共体系结构)
- OGC Specifications, Simple Feature Access Part 2 - SQL Options(OGC 规范:简单特征访问第 2 部分 - SQL 选项)
圆弧线段
三种可实例化类型可以采用圆弧线段:CircularString、CompoundCurve 和 CurvePolygon。 圆弧线段在二维平面中由三个点定义;第三个点不能与第一个点相同。 圆弧线段的几个示例:
前两个示例显示了典型的圆弧线段。 请注意这三个点如何落在圆周上。
其他两个示例显示如何将直线线段定义为圆弧线段。 仍需要三个点定义圆弧线段,不像普通直线线段只需要两个点来定义。
对圆弧段类型进行操作的方法使用直线段来近似圆弧。用于近似圆弧的线段的数量将取决于圆弧的长度和曲率。可以为每种圆弧段类型存储 Z 值,但不会在计算中使用此值。
注意
如果为圆弧线段指定 Z 值,则这些值对于圆弧线段中的所有点必须相同,才接受输入。 例如,接受 CIRCULARSTRING(0 0 1, 2 2 1, 4 0 1)
,但是不接受 CIRCULARSTRING(0 0 1, 2 2 2, 4 0 1)
。
LineStr 和 CircularString 比较
此示例显示如何使用 LineString 实例和 CircularString 实例存储完全相同的等腰三角形:
DECLARE @g1 geometry;
DECLARE @g2 geometry;
SET @g1 = geometry::STGeomFromText('LINESTRING(1 1, 5 1, 3 5, 1 1)', 0);
SET @g2 = geometry::STGeomFromText('CIRCULARSTRING(1 1, 3 1, 5 1, 4 3, 3 5, 2 3, 1 1)', 0);
IF @g1.STIsValid() = 1 AND @g2.STIsValid() = 1
BEGIN
SELECT @g1.ToString(), @g2.ToString()
SELECT @g1.STLength() AS [LS Length], @g2.STLength() AS [CS Length]
END
CircularString 实例需要七个点才能定义三角形。 LineString 实例只需要四个点定义三角形。 原因是 CircularString 实例存储的是圆弧线段而非直线线段。 存储在 CircularString 实例中的三角形的边是 ABC、CDE 和 EFA。 存储在 LineString 实例中的三角形的边是 AC、CE 和 EA。
请考虑以下示例:
SET @g1 = geometry::STGeomFromText('LINESTRING(0 0, 2 2, 4 0)', 0);
SET @g2 = geometry::STGeomFromText('CIRCULARSTRING(0 0, 2 2, 4 0)', 0);
SELECT @g1.STLength() AS [LS Length], @g2.STLength() AS [CS Length];
结果集如下。
LS Length CS Length
5.65685... 6.28318...
与 LineString 实例相比,CircularString 实例使用更少的点来存储曲线边界,而且更精确。 CircularString 实例对于存储圆边界(如针对特定点的 20 英里搜索半径)很有用。 LineString 实例则适合存储线性边界(如方形城市街区)。
LineStr 和 CompoundCurve 比较
以下代码示例显示如何使用 LineString 和 CompoundCurve 实例存储相同的图形:
SET @g = geometry::Parse('LINESTRING(2 2, 4 2, 4 4, 2 4, 2 2)');
SET @g = geometry::Parse('COMPOUNDCURVE((2 2, 4 2), (4 2, 4 4), (4 4, 2 4), (2 4, 2 2))');
SET @g = geometry::Parse('COMPOUNDCURVE((2 2, 4 2, 4 4, 2 4, 2 2))');
在前面的示例中, LineString 实例或 CompoundCurve 实例可以存储该图。 下一个示例使用 CompoundCurve 存储饼图切片:
SET @g = geometry::Parse('COMPOUNDCURVE(CIRCULARSTRING(2 2, 1 3, 0 2),(0 2, 1 0, 2 2))');
CompoundCurve 实例可以直接存储圆弧线段 (2 2, 1 3, 0 2),但是 LineString 实例则必须将曲线转换为几个更小的直线线段。
CircularStr 和 CompoundCurve 比较
以下代码示例显示如何将饼图切片存储在 CircularString 实例中:
DECLARE @g geometry;
SET @g = geometry::Parse('CIRCULARSTRING( 0 0, 1 2.1082, 3 6.3246, 0 7, -3 6.3246, -1 2.1082, 0 0)');
SELECT @g.ToString(), @g.STLength();
如果使用 CircularString 实例存储饼图切片,要求每个直线线段使用三个点。 如果一个中间点未知,必须计算它或必须将直线线段的端点加倍,如以下代码段所示:
SET @g = geometry::Parse('CIRCULARSTRING( 0 0, 3 6.3246, 3 6.3246, 0 7, -3 6.3246, 0 0, 0 0)');
CompoundCurve 实例允许 LineString 和 CircularString 组件,因此只需要知道饼图切片的直线线段的两个点。 此代码示例显示如何使用 CompoundCurve 存储相同的图形:
DECLARE @g geometry;
SET @g = geometry::Parse('COMPOUNDCURVE(CIRCULARSTRING( 3 6.3246, 0 7, -3 6.3246), (-3 6.3246, 0 0, 3 6.3246))');
SELECT @g.ToString(), @g.STLength();
Polygon 和 CurvePolygon 的比较
在定义外部环和内部环时,CurvePolygon 实例可以使用 CircularString 和 CompoundCurve。 Polygon 实例不能。
限制
在 Microsoft Fabric 中的 SQL 数据库中,支持地理和几何数据类型,但无法镜像到 Fabric OneLake。