ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### 第19章:MySQL中的空间扩展 MySQL支持空间扩展,允许生成、保存和分析地理特征。这些特征可用于MyISAM、InnoDB、NDB、BDB和ARCHIVE表(但是,ARCHIVE引擎不支持索引功能,因此,不能为ARCHIVE列中的空间列编制索引)。 本章介绍了下述议题: ・         OpenGIS几何模型中这些空间扩展的基础。 ・         用于表示空间数据的数据格式。 ・         如何在MySQL中使用空间数据。 ・         使用关于空间数据的索引功能。 ・         MySQL与OpenGIS规范的差异。 如果在MySQL空间扩展的使用方面有任何问题,可在我们网站的[GIS论坛](http://forums.mysql.com/list.php?23)中讨论。 ### 19.1. 前言 遵从OpenGIS联盟(OGC)的规范,MySQL实施了空间扩展。OGC是一个由250多家公司、代理机构和大学参与的国际联盟,负责开发公开的概念解决方案,这类解决方案对所有用来管理空间数据的应用都是有用的。OGC的网站是[http://www.opengis.org/](http://www.opengis.org/)。 1997年,OpenGIS联盟(OGC)发布了_针对SQL的OpenGISR简单特征规范_,在该文档中,提出了扩展SQL RDBMS以支持空间数据的一些概念性方法。该规范可从OpenGIS网站上获得[http://www.opengis.org/docs/99-049.pdf](http://www.opengis.org/docs/99-049.pdf)。其中包含与本章有关的额外信息。 MySQL实施了OGC建议的**具有Geometry类型的SQL**环境的一个子集。该术语指的是用一组集合类型扩展的环境。具有几何值的SQL列是作为拥有集合类型的列实施的。该规范描述了SQL几何类型集合,以及作用在这些类型上用于创建和分析几何值的函数。 **地理特征**指的是世界上具有地理位置的任何事物。它可以是: ・         实体,如山、池溏、城市。 ・         空间,如邮政区域、热带。 ・         可定义的位置,如两条街道相交的十字路口。 有些文件采用术语**地理空间特征**来指代地理特征。 **几何**是另一个表示地理特征的术语。最初,单词**几何**表示的是对大地的测量。来自制图学的另一个含义指的是制图人员用于绘制世界地图的地理特征。 本章将所有这些术语当作同义词对待:**地理特征、****地理空间特征****、****或几何****。最常使用的术语是几何。** 我们将**几何**定义为世界上具有地理位置的点或点的集合。 ### 19.2. OpenGIS几何模型 [ 19.2.1. Geometry类的层次](#)[ 19.2.2. 类Geometry](#)[ 19.2.3. 类Point``](#)[ 19.2.4. 类Curve``](#)[ 19.2.5. 类LineString](#)[ 19.2.6. 类Surface](#)[ 19.2.7. 类Polygon](#)[ 19.2.8. 类GeometryCollection](#)[ 19.2.9. 类MultiPoint](#)[ 19.2.10. 类MultiCurve](#)[ 19.2.11. 类MultiLineString](#)[ 19.2.12. 类MultiSurface](#)[ 19.2.13. 类MultiPolygon](#) OGC**具有几何类型的SQL**环境建议的几何类型集合,基于OpenGIS几何模型。在本模型中,每个几何对象均具有下述一般属性: ・         与空间参考系统相关,其中介绍了定义对象的坐标空间。 ・         属于某种几何类。 ### 19.2.1. Geometry类的层次 几何类定义了下述层次: ・         Geometry(非实例化) o        Point(可实例化的) o        Curve(非实例化) §         LineString(可实例化的) ・         Line ・         LinearRing o        Surface(非实例化) §         Polygon(可实例化的) o        GeometryCollection(可实例化的) §         MultiPoint(可实例化的) §         MultiCurve(非实例化) ・         MultiLineString(可实例化的) §         MultiSurface(非实例化) ・         MultiPolygon(可实例化的) 不能在非实例化类中创建对象。能够在可实例化类中创建对象。所有类均有属性,可实例化类还可以包含声明(定义有效类实例的规则)。 Geometry是一种基本类。它是一种抽象类。Geometry的可实例化子类限制为可在2维坐标空间中存在的0、1、2维几何对象。所有的可实例化几何类是这样定义的,从而使得几何类的实例从拓扑意义上讲是闭合的(也就是说,所有定义的几何类包含其边界)。 基本Geometry类具有关于Point、Curve、Surface和GeometryCollection的子类: ・         Point表示0维对象。 ・         Curve表示1维对象,具有子类LineString,以及次级子类Line和LinearRing。 ・         Surface是为2维对象设计的,具有子类Polygon。 ・         GeometryCollection具有特殊的0维、1维和2维类集合,名为MultiPoint、MultiLineString和MultiPolygon,分别用于为对应的Points、LineStrings和Polygons集合进行几何建模。MultiCurve和MultiSurface是作为抽象超类引入的,它们归纳了用于处理Curves和Surfaces的集合接口。 Geometry、Curve、Surface、MultiCurve和MultiSurface定义为非实例化类。它们为其子类定义了公用方法集合,而且是为扩展而包含在内的。 Point、LineString、Polygon、GeometryCollection、MultiPoint、MultiLineString和MultiPolygon定义为可实例化类。 ### 19.2.2. 类Geometry Geometry是层次结构的根类。它是一种非实例化类,但具有很多属性,这些属性对由任何Geometry子类创建的所有几何值来说是共同的。下面介绍了这些属性(尤其是具有自己特殊属性的子类)。 **Geometry属性** Geometry值具有下述属性: ・         其**type**(类型)。每个geometry属于层次结构中可实例化类之一。 ・         其**SRID**,或空间参考ID。该值确定了用于描述定义几何对象的坐标空间的空间坐标系统。 在MySQL中,SRID值仅是与geometry值相关的整数值。所有计算均是在欧几里得几何系(平面)中进行的。 ・         它在其空间坐标系统中的**coordinates**(坐标),表示为双精度数值(8字节)。所有的非空几何对象至少包含一对坐标(X、Y)。空几何对象不含坐标。 坐标与SRID相关。例如,在不同的坐标系内,两个对象之间的距离会有所不同,即使这两个对象具有相同的坐标也同样。这是因为,平面坐标系中的距离和地心坐标系(地球表面上的坐标)中的距离是不同的事项。 ・         其**interior**(内部)、**boundary**(边界)和**exterior**(外部)。 每个几何对象均占据空间中的某一位置。几何对象的exterior(外部)指的是未被该对象占据的所有空间。其interior(内部)指的是被该对象占据的空间。其boundary(边界)指的是几何对象内部和外部之间的界面。 ・         其**MBR**(最小边界矩形)或包络面。这是一种边界几何值,由最小和最大坐标(X,Y)构成。 ・                ((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY)) ・         无论值是**简单的**或**非简单的**。类型(LineString、MultiPoint、MultiLineString)的几何值或是简单的,或是非简单的。每个类型决定了其自己的简单或非简单声明。 ・         无论值是**封闭的**或**非封闭的**。类型(LineString、MultiPoint)的几何值或是封闭的,或是非封闭的。每个类型决定了其自己的封闭或非封闭声明。 ・         无论值是**空的**或**非空的**。如果没有任何点,几何对象是空的。空几何对象的内部、外部和边界未定义(也就是说,它们由Null值表示)。空的几何对象定义为总是简单的,面积为0。 ・         其**dimension**(维数)。几何对象的维数为−1、0、1或2: o        −1用于空几何对象。 o        0用于无长度、无面积的几何对象。 o        1用于具有非0长度和0面积的几何对象。 o        2用于具有非0面积的几何对象。 Point对象的维数为0。LineString对象的维数为1。Polygon对象的维数为2。MultiPoint、MultiLineString和MultiPolygon对象的维数与构成它们的元素的维数相同。 ### 19.2.3. 类Point`` Point(点)指的是代表坐标空间中单个位置的几何类。 **Point****示例** ・         想像一张具有众多城市的大世界地图。每个Point对象可代表1个城市。 ・         在城市地图上,Point对象可代表1个公共汽车站。 **Point****属性** ・         X-坐标值。 ・         Y-坐标值。 ・         Point定义为0维几何对象。 ・         Point的边界为空集合。 ### 19.2.4. 类Curve`` Curve(曲线)是一种1维几何对象,通常由一系列点表示。Curve的特殊子类定义了点之间的内插类型。Curve是一种非实例化类。 **Curve****属性** ・         Curve具有其点的坐标。 ・         Curve定义为1维几何对象。 ・         如果未通过相同的点两次,Curve就是简单的。 ・         如果其起点等于其终点,Curve就是封闭的。 ・         封闭Curve的边界为空。 ・         非封闭Curve的边界由其两个端点构成。 ・         简单且封闭的Curve是LinearRing。 ### 19.2.5. 类LineString LineString是具有点之间线性内插特性的Curve。 **LineString****示例** ・         在世界地图上,LineString对象可表示河流。 ・         在城市地图上,LineString对象可表示街道。 **LineString****属性** ・         LineString具有线段的坐标,由每个连续的点对(两点)定义。 ・         如果仅包含两点,LineString为Line。 ・         如果它既是简单的也是封闭的,LineString为LinearRing。 ### 19.2.6. 类Surface Surface是一种2维几何对象。它是一种非实例化类。其唯一的可实例化子类是Polygon. **Surface****属性** ・         Surface定义为2维几何对象。 ・         在OpenGIS规范中,将简单的Surface定义为由单一“patch”构成的几何对象,它与单个外部边界以及0或多个内部边界有关。 ・         简单Surface的边界是一组与其内部和外部边界对应的封闭曲线的集合。 ### 19.2.7. 类Polygon Polygon是代表多边几何对象的平面Surface。它由单个外部边界以及0或多个内部边界定义,其中,每个内部边界定义为Polygon中的1个孔。 **Polygon****示例** ・         在地区地图上,Polygon对象可表示森林、区等。 **Polygon****声明** ・         Polygon的边界由一组构成其外部边界和比内部边界的LinearRing归向集合构成(即,简单且封闭的LineString对象)。 ・         Polygon没有交叉的环。Polygon边界中的环可能会在Point处相交,但仅以切线方式相交。 ・         Polygon没有线、尖峰或穿孔。 ・         Polygon有由连接点集合构成的内部。 ・         Polygon可能包含孔。对于具有孔的Polygon,其外部不连接。每个孔定义了连接的外部部件。 前述声明使得Polygon成为简单的几何对象。 ### 19.2.8. 类GeometryCollection GeometryCollection是由1个或多个任意类几何对象构成的几何对象。 GeometryCollection中的所有元素必须具有相同的空间参考系(即相同的坐标系)。对GeometryCollection的元素无任何限制,但下面介绍的GeometryCollection的子类会限制其成员。这类限制可能基于: ・         元素类型(例如,MultiPoint可能仅包含Point元素)。 ・         维数。 ・         对元素间空间交迭程度的限制。 ### 19.2.9. 类MultiPoint MultiPoint是一种由Point元素构成的几何对象集合。这些点未以任何方式连接或排序。 **MultiPoint****示例** ・         在世界地图上,MultiPoint可以代表岛链。 ・         在城市地图上,MultiPoint可以表示售票处的出口。 **MultiPoint****属性** ・         MultiPoint是0维几何对象。 ・         如果没有两个Point是相同的(具有等同的坐标值),MultiPoint是简单的。 ・         MultiPoint的边界为空集合。 ### 19.2.10. 类MultiCurve MultiCurve是一种由Curve元素构成的几何对象集合。MultiCurve是一种非实例化类。 **MultiCurve****属性** ・         MultiCurve是1维几何对象。 ・         当且仅当其所有元素均是简单的时,MultiCurve才是简单的。任意两元素的唯一交叉仅出现在两元素边界的点上。 ・         MultiCurve边界是通过采用“模2联合规则”(也称为奇偶规则)获得的:如果某一点位于奇数编号MultiCurve元素的边界内,它将位于MultiCurve的边界内。 ・         如果其所有元素均是封闭的,则MultiCurve为封闭的。 ・         封闭MultiCurve的边界总为空。 ### 19.2.11. 类MultiLineString MultiLineString是一种由LineString元素构成的MultiCurve几何对象集合。 **MultiLineString****示例** ・         在地区地图上,MultiLineString可表示河流体系或高速路系统。 ### 19.2.12. 类MultiSurface MultiSurface是一种由Surface元素构成的几何对象集合。MultiSurface是一种非实例化类。其唯一的可实例化子类是MultiPolygon。 **MultiSurface****声明** ・         2个MultiSurface面没有相交的内部。 ・         2个MultiSurface元素具有最多在有限点上相交的边界。 ### 19.2.13. 类MultiPolygon MultiPolygon是一种由Polygon元素构成的几何对象集合。 **MultiPolygon****示例** ・         在地区地图上,MultiPolygon可表示湖泊系统。 **MultiPolygon****声明** ・         MultiPolygon没有内部相交的的2个Polygon元素。 ・         MultiPolygon没有2个交叉的Polygon元素(前述声明也禁止交叉),也没有在无数点处相接触的2个Polugon元素。 ・         MultiPolygon不能含有有断开的线、尖峰或穿孔。MultiPolygon是一种正常的封闭点集合。 ・         对于有1个以上Polygon元素的MultiPolygon,具有不连接的内部。MultiPolygon内部已连接部件的数目等于MultiPolygon中Polygon值的数目。 **MultiPolygon****属性** ・         MultiPolygon是2维几何对象。 ・         MultiPolygon边界是与其Polygon元素的边界对应的封闭曲线集合(LineString值)。 ・         MultiPolygon边界中的每个Curve准确位于1个Polygon元素的边界内。 ・         Polygon元素边界中的每个Curve位于MultiPolygon的边界中。 ### 19.3. 支持的空间数据格式 [ 19.3.1. 著名的文本(WKT)格式](#)[ 19.3.2. 著名的二进制(WKB)格式](#) 在本节中,介绍了用于表示查询中几何对象的标准空间数据格式。它们是: ・         著名的文本(WKT)格式 ・         著名的二进制(WKB)格式 从其内部看,MySQL以不完全等同于WKT或WKB的格式保存几何对象值。 ### 19.3.1. 著名的文本(WKT)格式 对于Geometry的著名文本(WKT)表示,它是为与采用ASCII格式的几何数据进行交换而设计的。 几何对象WKT表示的示例: ・         Point: ・                POINT(15 20) 注意,指定点坐标时不使用分隔用逗号。 ・         具有4个点的LineString: ・                LINESTRING(0 0, 10 10, 20 25, 50 60) 注意,点坐标对采用逗号隔开。 ・         具有1个外部环和1个内部环的Polygon: ・                POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)) ・         具有三个Point值的MultiPoint: ・                MULTIPOINT(0 0, 20 20, 60 60) ・         具有2个LineString值的MultiLineString: ・                MULTILINESTRING((10 10, 20 20), (15 15, 30 15)) ・         具有2个Polygon值的MultiPolygon: ・                MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5))) ・         由2个Point值和1个LineString构成的GeometryCollection: ・                GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20)) 在本章开始处给出的OGC规范文档中,可找到相应的Backus-Naur语法,它指定了用于编写WKT值的正式生产规则。 ### 19.3.2. 著名的二进制(WKB)格式 用于几何值的著名二进制(WKB)表示是由OpenGIS规范定义的。它还定义在ISO “SQL/MM Part 3: Spatial”标准中。 WKB用于以二进制流的形式交换几何数据,二进制流由含几何WKB信息的BLOB值表示。 WKB使用1字节无符号整数、4字节无符号整数、以及8字节双精度数(IEEE 754格式)。1字节等于8比特。 例如,与POINT(1 1)对应的WKB值由下述21字节序列构成(在此,每个字节由2个十六进制数值表示): 0101000000000000000000F03F000000000000F03F 该序列可分为下述部分: Byte order : 01 WKB type   : 01000000 X          : 000000000000F03F Y          : 000000000000F03F 表示如下: ・         字节顺序(Byte order)可以是0或1,分别表明little-endian或big-endian存储。little-endian和big-endian字节顺序也分别称为网络数据表示(NDR)和外部数据表示(XDR)。 ・         “WKB type”(WKB类型)是指明几何类型的代码。取值从1到7,分别表示Point、LineString、Polygon、MultiPoint、MultiLineString、MultiPolygon、和GeometryCollection。 ・         Point值具有X和Y坐标,每个值均用双精度值表示。 对于更复杂几何值的WKB值,它们是由更复杂的数据结构表示的,详情请参见OpenGIS规范。 ### 19.4. 创建具备空间功能的MySQL数据库 [ 19.4.1. MySQL空间数据类型](#)[ 19.4.2. 创建空间值](#)[ 19.4.3. 创建空间列](#)[ 19.4.4. 填充空间列](#)[ 19.4.5. 获取空间数据](#) 本节介绍了可用于表示MySQL中空间数据的数据类型,以及用于创建和检索空间值的函数。 ### 19.4.1. MySQL空间数据类型 MySQL具有与OpenGIS类对应的数据类型。某些类型只能保存单个几何值: ・         GEOMETRY ・         POINT ・         LINESTRING ・         POLYGON GEOMETRY能够保存任何类型的几何值。其他的单值类型POINT、LINESTRING以及POLYGON只能保存特定几何类型的值。 其他数据类型能保存多个值: ・         MULTIPOINT ・         MULTILINESTRING ・         MULTIPOLYGON ・         GEOMETRYCOLLECTION GEOMETRYCOLLECTION能保存任意类型的对象集合。对于其他集合类型,MULTIPOINT、MULTILINESTRING、MULTIPOLYGON和GEOMETRYCOLLECTION,仅限于具有特定几何类型的集合成员。 ### 19.4.2. 创建空间值 [ 19.4.2.1. 使用WKT函数创建Geometry(几何)值](#)[ 19.4.2.2. 使用WKB函数创建Geometry(几何)值](#)[ 19.4.2.3. 使用MySQL函数创建几何值](#) 在本节中,介绍了使用OpenGIS标准中定义的WKT和WKB函数创建空间值的方法,以及使用相应MySQL函数的方法。 #### 19.4.2.1. 使用WKT函数创建Geometry(几何)值 MySQL提供了众多以WKT表达式、以及可选的空间参考系ID(SRID)为输入参数的函数。它们将返回对应的几何对象。 GeomFromText()接受任何几何类型的WKT作为其第1个参量。在实施方案中也提供了与类型相关的构造函数,用于构造每一种几何类型的几何值。 - GeomCollFromText(_wkt_[,_srid_]) , GeometryCollectionFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造GEOMETRYCOLLECTION值。 - GeomFromText(_wkt_[,_srid_]) , GeometryFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造任何类型的几何值。 - LineFromText(_wkt_[,_srid_]) , LineStringFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造LINESTRING值。 - MLineFromText(_wkt_[,_srid_]) , MultiLineStringFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造MULTILINESTRING值。 - MPointFromText(_wkt_[,_srid_]) , MultiPointFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造MULTIPOINT值。 - MPolyFromText(_wkt_[,_srid_]) , MultiPolygonFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造MULTIPOLYGON值。 - PointFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造POINT值。 - PolyFromText(_wkt_[,_srid_]) , PolygonFromText(_wkt_[,_srid_]) 使用其WKT表示和SRID构造POLYGON值。 OpenGIS规范还介绍了用于构造Polygon或MultiPolygon值的可选函数,这些值基于环和封闭LineString值集合的WKT表达式。这些值可以相交。MySQL未实施下述函数: - BdMPolyFromText(_wkt_,_srid_) 以包含已关闭LineString值任意集合的WKT格式,从MultiLineString值构造MultiPolygon值。 - BdPolyFromText(_wkt_,_srid_) 以包含已关闭LineString值任意集合的WKT格式,从MultiLineString值构造Polygon值。 #### 19.4.2.2. 使用WKB函数创建Geometry(几何)值 MySQL提供了众多函数,它们将包含WKT表达式、或可选的空间参考系统ID(SRID)的BLOB作为输入参数。它们返回对应的几何对象。 GeomFromWKB()接受任何几何类型的WKB作为其第1个参量。在实施方案中也提供了与类型相关的构造函数,用于构造每一种几何类型的几何值。 - GeomCollFromWKB(_wkb_[,_srid_]) , GeometryCollectionFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造GEOMETRYCOLLECTION值。 - GeomFromWKB(_wkb_[,_srid_]) , GeometryFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造任意类型的几何值。 - LineFromWKB(_wkb_[,_srid_]) , LineStringFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造LINESTRING值。 - MLineFromWKB(_wkb_[,_srid_]) , MultiLineStringFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造MULTILINESTRING值。 - MPointFromWKB(_wkb_[,_srid_]) , MultiPointFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造MULTIPOINT值。 - MPolyFromWKB(_wkb_[,_srid_]) , MultiPolygonFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造MULTIPOLYGON值。 - PointFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造POINT值。 - PolyFromWKB(_wkb_[,_srid_]) , PolygonFromWKB(_wkb_[,_srid_]) 使用其WKB表示和SRID构造POLYGON值。 OpenGIS规范还介绍了用于构造Polygon或MultiPolygon值的可选函数,这些值基于环和封闭LineString值集合的WKB表达式。这些值可以相交。MySQL未实施下述函数: - BdMPolyFromWKB(_wkb_,_srid_) 以包含已关闭LineString值任意集合的WKB格式,从MultiLineString值构造MultiPolygon值。 - BdPolyFromWKB(_wkb_,_srid_) 以包含已关闭LineString值任意集合的WKB格式,从MultiLineString值构造Polygon值。 #### 19.4.2.3. 使用MySQL函数创建几何值 **注释:**MySQL未实施本节所列的函数。 MySQL为创建几何WKB表达式提供了有用的函数集合。本节介绍的函数是对OpenGIS规范的MySQL扩展。这些函数的结果是包含几何值(无SRID)的BLOB值。这些函数的结果可被GeomFromWKB()函数系列中任意函数的第1个参量取代。 - GeometryCollection(_g1_,_g2_,...) 构造WKB GeometryCollection。如果任何参量不是构造良好的几何对象WKB表达式,返回值为NULL。 - LineString(_pt1_,_pt2_,...) 从多个WKB Point参量构造WKB LineString值。如果任何参量不是WKB Point,返回值为NULL。如果Point参量的数目小于2,返回值为NULL。 - MultiLineString(_ls1_,_ls2_,...) 使用WKB LineString参量构造WKB MultiLineString值。如果任何参量不是WKB LineString,返回值为NULL。 - MultiPoint(_pt1_,_pt2_,...) 使用WKB Point参量构造WKB MultiPoint值。如果任何参量不是WKB Point,返回值为NULL。 - MultiPolygon(_poly1_,_poly2_,...) 从一组WKB Polygon参量构造WKB MultiPolygon值。如果任何参量不是WKB Polygon,返回值为NULL。 - Point(_x_,_y_) 使用其坐标构造WKB Point。 - Polygon(_ls1_,_ls2_,...) 从多个WKB LineString参量构造WKB Polygon值。如果任何参量未表示为LinearRing的WKB形式(即,非封闭和简单LineString),返回值为NULL。 ### 19.4.3. 创建空间列 MySQL提供了为几何类型创建空间列的标准方法,例如,使用CREATE TABLE或ALTER TABLE。目前,仅对MyISAM标支持空间列。 ・         使用CREATE TABLE语句创建具有空间列的表: ・                mysql> CREATE TABLE geom (g GEOMETRY); ・                Query OK, 0 rows affected (0.02 sec) ・         使用ALTER TABLE语句在已有表中增加空间列,或将空间列从已有表中删除: ・                mysql> ALTER TABLE geom ADD pt POINT; ・                Query OK, 0 rows affected (0.00 sec) ・                Records: 0  Duplicates: 0  Warnings: 0 ・                mysql> ALTER TABLE geom DROP pt; ・                Query OK, 0 rows affected (0.00 sec) ・                Records: 0  Duplicates: 0  Warnings: 0 ### 19.4.4. 填充空间列 创建了空间列后,可用空间数据填充它们。 值应以内部几何格式保存,但你也能将其从WKT或WKB格式转换为内部几何格式。在下面的示例中,介绍了通过将WKT值转换为内部几何格式以便将几何值插入表中的方法。 你可以在INSERT语句中执行直接转换操作: INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'));   SET @g = 'POINT(1 1)'; INSERT INTO geom VALUES (GeomFromText(@g)); 也可以在INSERT之前执行转换操作: SET @g = GeomFromText('POINT(1 1)'); INSERT INTO geom VALUES (@g); 在下面的示例中,将多个复杂的几何值插入到了表中: SET @g = 'LINESTRING(0 0,1 1,2 2)'; INSERT INTO geom VALUES (GeomFromText(@g));   SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'; INSERT INTO geom VALUES (GeomFromText(@g));   SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'; INSERT INTO geom VALUES (GeomFromText(@g)); 在前面的所有示例中,均采用了GeomFromText()来创建几何值。你也可以使用与类型相关的函数: SET @g = 'POINT(1 1)'; INSERT INTO geom VALUES (PointFromText(@g));   SET @g = 'LINESTRING(0 0,1 1,2 2)'; INSERT INTO geom VALUES (LineStringFromText(@g));   SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'; INSERT INTO geom VALUES (PolygonFromText(@g));   SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'; INSERT INTO geom VALUES (GeomCollFromText(@g)); 注意,如果客户端应用程序打算使用几何值的WKB表示,它需要在队列中将正确构造的WKB发送至服务器。但是,存在数种满足该要求的方法。例如: ・         用十六进制文字语法插入POINT(1 1)值: ・                mysql> INSERT INTO geom VALUES ・                    -> (GeomFromWKB(0x0101000000000000000000F03F000000000000F03F)); ・         ODBC应用程序能够发送WKB表达式,并使用具有BLOB类型的参量将其绑定到占位符: ・                INSERT INTO geom VALUES (GeomFromWKB(?)) 其他编程接口或许也支持类似的占位符机制。 在C程序中,可以使用mysql_real_escape_string()转义二进制值,并将结果包含在将发送至服务器的查询字符串。请参见[25.2.3.52节,“mysql_real_escape_string()”](# "25.2.3.52. mysql_real_escape_string()") ### 19.4.5. 获取空间数据 [ 19.4.5.1. 以内部格式获取空间数据](#)[ 19.4.5.2. 以WKT格式获取空间数据](#)[ 19.4.5.3. 以格式获取空间数据](#) 对于表中保存的几何值,能够以内部格式获取。你也能将其转换为WKT或WKB格式。 #### 19.4.5.1. 以内部格式获取空间数据 在表对表传输中,使用内部格式来获取几何值可能是有用的。 CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom; #### 19.4.5.2. 以WKT格式获取空间数据 AsText()函数能够将几何值从内部格式转换为WKT字符串。 SELECT AsText(g) FROM geom; #### 19.4.5.3. 以格式获取空间数据 AsBinary()函数能够将几何值从内部格式转换为包含WKB值的BLOB。 SELECT AsBinary(g) FROM geom; ### 19.5. 分析空间信息 [ 19.5.1. Geometry格式转换函数](#)[19.5.2. Geometry函数](#)[ 19.5.3. 从已有Geometry创建新Geometry的函数](#)[ 19.5.4. 测试几何对象间空间关系的函数](#)[ 19.5.5. 关于几何最小边界矩形(MBR)的关系](#)[ 19.5.6. 测试几何类之间空间关系的函数](#) 用值填充了空间列后,即可查询和分析它们。MySQL提供了一组在空间数据上执行各种操作的函数。根据它们所执行的操作类型,可以将这些函数分为四种主要类别: ・         用于在各种格式间转换几何值的函数。 ・         用于访问几何值定性或定量属性的函数。 ・         描述两种几何值之间关系的函数。 ・         从已有Geometry创建新Geometry的函数 空间分析函数可用于很多场合下,如: ・         任何交互式SQL程序,如**mysql**或**MySQLCC**。 ・         以任何语言编写的、支持MySQL客户端API的应用程序。 ### 19.5.1. Geometry格式转换函数 MySQL支持下述用于在内部格式和WKT或WKB格式间转换几何值的函数: - AsBinary(_g_) 将采用内部几何格式的值转换为其WKB表示,并返回二进制结果。 SELECT AsBinary(g) FROM geom; - AsText(_g_) 将采用内部几何格式的值转换为其WKT表示,并返回字符串结果。 mysql> SET @g = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(GeomFromText(@g)); +--------------------------+ | AsText(GeomFromText(@g)) | +--------------------------+ | LINESTRING(1 1,2 2,3 3) | +--------------------------+ - GeomFromText(_wkt_[,_srid_]) 将字符串值从其WKT表示转换为内部几何格式,并返回结果。也支持多种与类型相关的函数,如PointFromText()和LineFromText(),请参见[19.4.2.1节,“使用WKT函数创建Geometry(几何)值”](# "19.4.2.1. Creating Geometry Values Using WKT Functions")。 - GeomFromWKB(_wkb_[,_srid_]) 将二进制值从其WKB表示转换为内部几何格式,并返回结果。也支持多种与类型相关的函数,如PointFromWKB()和LineFromWKB(),请参见[19.4.2.2节,“使用WKB函数创建Geometry(几何)值”](# "19.4.2.2. Creating Geometry Values Using WKB Functions")。 ### 19.5.2. Geometry函数 [ 19.5.2.1. 通用几何函数](#)[19.5.2.2. Point函数  ](#)[19.5.2.3. LineString函数](#)[19.5.2.4. MultiLineString函数](#)[19.5.2.5. Polygon函数](#)[19.5.2.6. MultiPolygon函数](#)[19.5.2.7. GeometryCollection函数](#) 属于该组的每个函数均将几何值作为其参量,并返回几何值的定性或定量属性。某些函数限制了其参量类型。如果参量是不正确的几何类型,这类函数将返回NULL。例如,如果对象类型既不是Polygon也不是MultiPolygon,Area()将返回NULL。 #### 19.5.2.1. 通用几何函数 本节列出的函数不限制其参量,可接受任何类型的几何值。 - Dimension(_g_) 返回几何值_g_的固有维数。结果可以是-1、0、1或2。(关于这些值的含义,请参见[19.2.2节,“类Geometry”](# "19.2.2. Class Geometry"))。 mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)')); +------------------------------------------------+ | Dimension(GeomFromText('LineString(1 1,2 2)')) | +------------------------------------------------+ | 1 | +------------------------------------------------+ - Envelope(_g_) 返回几何值g的最小边界矩形(MBR)。结果以Polygon值的形式返回。 多边形(polygon)是由边界框的顶点定义的: POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY)) mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))); +-------------------------------------------------------+ | AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) | +-------------------------------------------------------+ | POLYGON((1 1,2 1,2 2,1 2,1 1)) | +-------------------------------------------------------+ - GeometryType(_g_) 以字符串形式返回几何类型的名称,几何实例g是几何类型的成员。该名称与可实例化几何子类之一对应。 mysql> SELECT GeometryType(GeomFromText('POINT(1 1)')); +------------------------------------------+ | GeometryType(GeomFromText('POINT(1 1)')) | +------------------------------------------+ | POINT | +------------------------------------------+ - SRID(_g_) 返回指明了几何值g的空间参考系统ID的整数。 在MySQL中,SRID值仅是与几何值相关的整数。所有计算均是在欧几里得(平面)几何中进行的。 mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101)); +-----------------------------------------------+ | SRID(GeomFromText('LineString(1 1,2 2)',101)) | +-----------------------------------------------+ | 101 | +-----------------------------------------------+ OpenGIS规范还定义了下述函数,MySQL未实施这类函数: - Boundary(_g_) 返回几何值g的组合边界的闭包的几何对象。 - IsEmpty(_g_) 如果几何值g为空的几何对象,返回1,如果非空,返回0,如果参量为NULL,返回-1。如果几何对象是空的,它表示空的点集合。 - IsSimple(_g_) 目前该函数是占位符,不应使用它。如果实施了它,其行为与下段所给出的描述类似。 如果几何值g没有异常的几何点(如自相交或自相切),返回1。如果参量不是简单参量,IsSimple()返回0,如果参量是NULL,返回-1。 对于本章前面介绍的每个可实例化几何类,均包含特定的条件,这类条件会使类实例被分类为非简单的。 #### 19.5.2.2. Point函数   Point由X和Y坐标构成,可使用下述函数获得它们: - X(_p_) 以双精度数值返回点p的X坐标值。 mysql> SELECT X(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | X(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 56.7 | +--------------------------------------+ - Y(_p_) 以双精度数值返回点p的Y坐标值。 mysql> SELECT Y(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | Y(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 53.34 | +--------------------------------------+ #### 19.5.2.3. LineString函数 LineString由Point值组成。你可以提取LineString的特定点,计数它所包含的点数,或获取其长度。 - EndPoint(_ls_) 返回LineString值1s的最后一个点的Point。 mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(EndPoint(GeomFromText(@ls))); +-------------------------------------+ | AsText(EndPoint(GeomFromText(@ls))) | +-------------------------------------+ | POINT(3 3) | +-------------------------------------+ - GLength(_ls_) 以双精度数值返回LineString值1s在相关的空间参考系中的长度。 mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT GLength(GeomFromText(@ls)); +----------------------------+ | GLength(GeomFromText(@ls)) | +----------------------------+ | 2.8284271247462 | +----------------------------+ - NumPoints(_ls_) 返回LineString值1s中的点数。 mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT NumPoints(GeomFromText(@ls)); +------------------------------+ | NumPoints(GeomFromText(@ls)) | +------------------------------+ | 3 | +------------------------------+ - PointN(_ls_,_n_) 返回LineString值1s中的第_n_个点。点编号从1开始。 mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(PointN(GeomFromText(@ls),2)); +-------------------------------------+ | AsText(PointN(GeomFromText(@ls),2)) | +-------------------------------------+ | POINT(2 2) | +-------------------------------------+ - StartPoint(_ls_) 返回LineString值1s的第一个点的Point。 mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(StartPoint(GeomFromText(@ls))); +---------------------------------------+ | AsText(StartPoint(GeomFromText(@ls))) | +---------------------------------------+ | POINT(1 1) | +---------------------------------------+ OpenGIS规范还定义了下述函数,MySQL尚未实施这些函数: - IsRing(_ls_) 如果LineString值_ls_是封闭的(即其StartPoint()和EndPoint()值相同)和简单的(未通过相同的点1次以上)返回1。如果ls不是环,返回0,如果它是NULL,返回-1。 #### 19.5.2.4. MultiLineString函数 - GLength(_mls_) 以双精度数值形式返回MultiLineString值m1s的长度。_mls_的长度等于其元素的长度之和。 mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))'; mysql> SELECT GLength(GeomFromText(@mls)); +-----------------------------+ | GLength(GeomFromText(@mls)) | +-----------------------------+ | 4.2426406871193 | +-----------------------------+ - IsClosed(_mls_) 如果MultiLineString值m1s是封闭的(即StartPoint()和EndPoint()值对m1s中的每个LineString是相同的)返回1。如果mls是非封闭的,返回0,如果它是NULL,返回-1。 mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))'; mysql> SELECT IsClosed(GeomFromText(@mls)); +------------------------------+ | IsClosed(GeomFromText(@mls)) | +------------------------------+ | 0 | +------------------------------+ #### 19.5.2.5. Polygon函数 - Area(_poly_) 以双精度数值形式返回Polygon值_poly_的面积,根据在其空间参考系中的测量值。 mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))'; mysql> SELECT Area(GeomFromText(@poly)); +---------------------------+ | Area(GeomFromText(@poly)) | +---------------------------+ | 4 | +---------------------------+ - ExteriorRing(_poly_) 以LineString形式返回Polygon值_poly_的外环。 mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT AsText(ExteriorRing(GeomFromText(@poly))); +-------------------------------------------+ | AsText(ExteriorRing(GeomFromText(@poly))) | +-------------------------------------------+ | LINESTRING(0 0,0 3,3 3,3 0,0 0) | +-------------------------------------------+ - InteriorRingN(_poly_,_n_) 以LineString形式返回Polygon值_poly_的第n个内环。环编号从1开始。 mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1)); +----------------------------------------------+ | AsText(InteriorRingN(GeomFromText(@poly),1)) | +----------------------------------------------+ | LINESTRING(1 1,1 2,2 2,2 1,1 1) | +----------------------------------------------+ - NumInteriorRings(_poly_) 返回Polygon值_poly_的内环的数目。 mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT NumInteriorRings(GeomFromText(@poly)); +---------------------------------------+ | NumInteriorRings(GeomFromText(@poly)) | +---------------------------------------+ | 1 | +---------------------------------------+ #### 19.5.2.6. MultiPolygon函数 - Area(_mpoly_) 以双精度数值形式返回MultiPolygon值_mpoly_的面积,根据在其空间参考系中的测量结果。 mysql> SET @mpoly = -> 'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'; mysql> SELECT Area(GeomFromText(@mpoly)); +----------------------------+ | Area(GeomFromText(@mpoly)) | +----------------------------+ | 8 | +----------------------------+ OpenGIS规范还定义了下述函数,MySQL未实施这类函数: - Centroid(_mpoly_) 以Point形式返回用于MultiPolygon值_mpoly_的数学质心。不保证结果位于MultiPolygon上。 - PointOnSurface(_mpoly_) 返回Point值,保证该值位于MultiPolygon值_mpoly_上。 #### 19.5.2.7. GeometryCollection函数 - GeometryN(_gc_,_n_) 返回GeometryCollection值_gc_中第n个几何对象。几何对象的编号从1开始。 mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))'; mysql> SELECT AsText(GeometryN(GeomFromText(@gc),1)); +----------------------------------------+ | AsText(GeometryN(GeomFromText(@gc),1)) | +----------------------------------------+ | POINT(1 1) | +----------------------------------------+ - NumGeometries(_gc_) 返回GeometryCollection值_gc_中几何对象的数目。 mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))'; mysql> SELECT NumGeometries(GeomFromText(@gc)); +----------------------------------+ | NumGeometries(GeomFromText(@gc)) | +----------------------------------+ | 2 | +----------------------------------+ ### 19.5.3. 从已有Geometry创建新Geometry的函数 [ 19.5.3.1. 生成新Geometry的Geometry函数](#)[ 19.5.3.2. 空间操作符](#) #### 19.5.3.1. 生成新Geometry的Geometry函数 在[19.5.2节,“Geometry函数”](# "19.5.2. Geometry Functions")中,我们讨论了一些可从已有几何对象构造新几何对象的函数: - Envelope(_g_) - StartPoint(_ls_) - EndPoint(_ls_) - PointN(_ls_,_n_) - ExteriorRing(_poly_) - InteriorRingN(_poly_,_n_) - GeometryN(_gc_,_n_) #### 19.5.3.2. 空间操作符 OpenGIS建议了很多可生成几何对象的其他函数。它们是为实施空间操作符而设计的。 在MySQL中未实施这些函数。它们或许会在未来的版本中出现。 - Buffer(_g_,_d_) 返回几何对象,该对象代表所有距几何值g的距离小于或等于d的所有点。 - ConvexHull(_g_) 返回几何对象,该对象代表几何值_g_的凸包。 - Difference(_g1_,_g2_) 返回几何对象,该对象表示了几何值g1与g2的点集合差异。 - Intersection(_g1_,_g2_) 返回几何对象,该对象表示了几何值g1与g2的点集合交集。 - SymDifference(_g1_,_g2_) 返回几何对象,该对象表示了几何值g1与g2的点集合对称差。 - Union(_g1_,_g2_) 返回几何对象,该对象表示了几何值g1与g2的点集合联合。 ### 19.5.4. 测试几何对象间空间关系的函数 这些节中所介绍的函数以2个几何对象作为输入参数,并返回它们之间的定量或定性关系。 ### 19.5.5. 关于几何最小边界矩形(MBR)的关系 MySQL提供了一些可测试两个几何对象g1和g2最小边界矩形之间关系的函数。它们包括: - MBRContains(_g1_,_g2_) 返回1或0以指明_g1_的最小边界矩形是否包含_g2_的最小边界矩形。 mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); mysql> SET @g2 = GeomFromText('Point(1 1)'); mysql> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1); ----------------------+----------------------+ | MBRContains(@g1,@g2) | MBRContains(@g2,@g1) | +----------------------+----------------------+ | 1 | 0 | +----------------------+----------------------+ - MBRDisjoint(_g1_,_g2_) 返回1或0以指明两个几何变量_g1_和_g2_的最小边界矩形是否不相交。 - MBREqual(_g1_,_g2_) 返回1或0以指明两个几何变量_g1_和_g2_的最小边界矩形是否相同。 - MBRIntersects(_g1_,_g2_) 返回1或0以指明两个几何变量_g1_和_g2_的最小边界矩形是否相交。 - MBROverlaps(_g1_,_g2_) 返回1或0以指明两个几何变量_g1_和_g2_的最小边界矩形是否交迭。 - MBRTouches(_g1_,_g2_) 返回1或0以指明两个几何变量_g1_和_g2_的最小边界矩形是否接触。 - MBRWithin(_g1_,_g2_) 返回1或0以指明_g1_的最小边界矩形是否位于_g2_的最小边界矩形内。 mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); mysql> SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))'); mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1); +--------------------+--------------------+ | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) | +--------------------+--------------------+ | 1 | 0 | +--------------------+--------------------+ ### 19.5.6. 测试几何类之间空间关系的函数 OpenGIS规范定义了下述函数。目前在MySQL尚未按照规范实施它们。对于那些已实施的函数,它们返回的结果与对应的基于MBR的函数返回的相同。包括下面列出的函数,但Distance()和Related()除外。 在未来的版本中,可能会实施这些函数,为空间分析提供全部支持,而不仅仅是基于MBR的支持。 这些函数作用在2个几何值g1和g2上。 - Contains(_g1_,_g2_) 返回1或0以指明_g1_是否完全包含_g2_。 - Crosses(_g1_,_g2_) 如果g1在空间上与g2相交,返回1。如果g1为Polygon或MultiPolygon,返回NULL,或如果g2为Point或MultiPoint返回NULL。否则,返回0。 术语“空间上交叉”指的是2个给定几何对象之间的空间关系,它具有下述属性: o        2个结合对象交叉。 o        其交叉结果将导致其维数小于两个给定几何对象最大维数的几何对象。 o        其交叉不等于两个几何对象中的任何1个。 - Disjoint(_g1_,_g2_) 返回1或0以指明_g1_是否与_g2_从空间上不相交。 - Distance(_g1_,_g2_) 以双精度数值形式返回2个几何对象中2点间的最短距离。 - Equals(_g1_,_g2_) 返回1或0以指明_g1_是否从空间上等同于_g2_。 - Intersects(_g1_,_g2_) 返回1或0以指明_g1_是否从空间上与_g2_相交。 - Overlaps(_g1_,_g2_) 返回1或0以指明_g1_是否从空间上与_g2_交迭。如果2个几何对象交叉而且其交叉将导致具有相同维数但并不等同于任一几何对象的几何对象,将使用术语“空间交迭”。 - Related(_g1_,_g2_,_pattern_matrix_) 返回1或0以指明由_pattern_matrix_指定的空间关系是否在_g1_和_g2_间存在。如果参量为NULL返回-1。模式矩形为字符串。如果实施了该函数,其规范将在此给出。 - Touches(_g1_,_g2_) 返回1或0以指明_g1_是否从空间上与_g2_接触。如果几何对象的内部不交叉,但1个几何对象的边界与另一个的边界或内部交叉,这两个几何对象是从空间上接触的。 - Within(_g1_,_g2_) 返回1或0以指明_g1_是否从空间上位于_g2_内。 ### 19.6. 优化空间分析 [ 19.6.1. 创建空间索引](#)[ 19.6.2. 使用空间索引](#) 可以使用索引对2个非空间数据库中的搜索操作进行优化。对于空间数据库,这同样成立。有了以前设计的大量多维索引功能的帮助,能够对空间搜索进行优化。最典型的情况如下: ・         搜索包含给定点的所有对象的Point查询。 ・         搜索与给定地区交迭的所有对象的地区查询。 MySQL采用了**具有2次分裂特性的R-Trees**来为空间列编制索引。使用几何对象的MBR来创建空间索引。对于大多数几何对象,MBR是包围几何对象的最小矩形。对于水平或垂直linestring,MBR退化为linestring的矩形。对于点,MBR是退化为点的矩形。 此外,还能在空间列上创建正常索引。需要为除POINT列之外的空间列上的任何索引(非空间)声明前缀。 ### 19.6.1. 创建空间索引 MySQL能够使用与创建正规索引类似的语法创建空间索引,但使用了SPATIAL关键字进行了扩展。对于目前编制了索引的空间列,必须将其声明为NOT NULL。在下面的示例中,介绍了创建空间索引的方法。 ・         对于CREATE TABLE: ・                mysql> CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)); ・         对于ALTER TABLE: ・                mysql> ALTER TABLE geom ADD SPATIAL INDEX(g); ・         对于CREATE INDEX: ・                mysql> CREATE SPATIAL INDEX sp_index ON geom (g); 对于MyISAM表,SPATIAL INDEX负责创建R-tree索引。对于支持空间索引的其他存储引擎,SPATIAL INDEX能够创建B-tree索引。对于准确的值查找而不是范围扫描,作用在空间值上的B-tree索引很有用。 要想撤销空间索引,可使用ALTER TABLE或DROP INDEX: ・         对于ALTER TABLE: ・                mysql> ALTER TABLE geom DROP INDEX g; ・         对于DROP INDEX: ・                mysql> DROP INDEX sp_index ON geom; 示例:假定表geom包含32000以上的几何对象,它们保存在类型为GEOMETRY的列g中。该表还有用于保存对象ID值的AUTO_INCREMENT列。 mysql> DESCRIBE geom; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | fid | int(11) | | PRI | NULL | auto_increment | | g | geometry | | | | | +-------+----------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> SELECT COUNT(*) FROM geom; +----------+ | count(*) | +----------+ | 32376 | +----------+ 1 row in set (0.00 sec) 要想在列g上添加空间索引,可使用下述语句: mysql> ALTER TABLE geom ADD SPATIAL INDEX(g); Query OK, 32376 rows affected (4.05 sec) Records: 32376 Duplicates: 0 Warnings: 0 ### 19.6.2. 使用空间索引 优化程序将调查可用的空间索引是否能包含在使用某些函数的查询搜索中,如WHERE子句中的MBRContains()或MBRWithin()函数。例如,假定我们打算找出位于给定矩形中的所有对象: mysql> SELECT fid,AsText(g) FROM geom WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-----+-----------------------------------------------------------------------------+ | fid | AsText(g) | +-----+-----------------------------------------------------------------------------+ | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8) | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4) | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2) | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823) | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2) | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) | | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2) | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121) | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113) | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6) | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2) | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077) | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4) | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019) | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8) | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8) | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134) | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4) | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001) | +-----+-----------------------------------------------------------------------------+ 20 rows in set (0.00 sec) 我们使用EXPLAIN来检查该查询的执行方式(ID列已被删除,以便输出能更好地与页匹配): mysql> EXPLAIN SELECT fid,AsText(g) FROM geom WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-------------+-------+-------+---------------+------+---------+------+------+-------------+ | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------------+-------+-------+---------------+------+---------+------+------+-------------+ | SIMPLE | geom | range | g | g | 32 | NULL | 50 | Using where | +-------------+-------+-------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) 让我们检查一下在没有空间索引的情况下会出现什么: mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-------------+-------+------+---------------+------+---------+------+-------+-------------+ | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------------+-------+------+---------------+------+---------+------+-------+-------------+ | SIMPLE | geom | ALL | NULL | NULL | NULL | NULL | 32376 | Using where | +-------------+-------+------+---------------+------+---------+------+-------+-------------+ 1 row in set (0.00 sec) 执行SELECT语句,忽略空间键: mysql> SELECT fid,AsText(g) FROM geom IGNORE INDEX (g) WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-----+-----------------------------------------------------------------------------+ | fid | AsText(g) | +-----+-----------------------------------------------------------------------------+ | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2) | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121) | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113) | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6) | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2) | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077) | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4) | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019) | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8) | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8) | | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8) | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4) | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2) | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823) | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2) | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134) | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4) | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001) | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) | +-----+-----------------------------------------------------------------------------+ 20 rows in set (0.46 sec) 未使用索引时,该查询的执行时间将从0.00秒上升到0.46秒。 在未来的版本中,空间索引也可能会用于优化其他函数。请参见[19.5.4节,“测试几何对象间空间关系的函数”](# "19.5.4. Functions for Testing Spatial Relations Between Geometric Objects")。 ### 19.7. MySQL的一致性和兼容性 [ 19.7.1. 尚未实施的GIS特性](#) ### 19.7.1. 尚未实施的GIS特性 - 额外的元数据视图 OpenGIS规范建议了数种额外的元数据视图。例如,包含几何列的描述的名为GEOMETRY_COLUMNS的系统视图,对于数据库中的每列有1行相关内容。 - 作用在LineString和MultiLineString上的OpenGIS函数Length()目前应在MySQL中以GLength()的方式调用。 问题在于存在1个用于计算字符串值长度的已有SQL函数Length(),而且在某些情况下无法判断函数是在文本场景下还是空间场景下调用的。我们需要以某种方式解决该问题,或确定另一个函数名。 这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访问[dev.mysql.com](http://dev.mysql.com/doc/mysql/en)。原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的。