目錄
MySQL支援空間延伸,允許生成、保存和分析地理特徵。這些特徵可用於MyISAM、InnoDB、NDB、BDB和ARCHIVE資料表(但是,ARCHIVE引擎不支援索引功能,因此,不能為ARCHIVE列中的空間列編製索引)。
本章介紹了下述議題:
· OpenGIS幾何模型中這些空間延伸的基礎。
· 用於資料表示空間數據的數據格式。
· 如何在MySQL中使用空間數據。
· 使用關於空間數據的索引功能。
· MySQL與OpenGIS規範的差異。
如果在MySQL空間延伸的使用方面有任何問題,可在我們網站的GIS論壇中討論。
遵從OpenGIS聯盟(OGC)的規範,MySQL實施了空間延伸。OGC是一個由250多家公司、代理機構和大學參與的國際聯盟,負責開發公開的概念解決方案,這類解決方案對所有用來管理空間數據的應用都是有用的。OGC的網站是http://www.opengis.org/。
1997年,OpenGIS聯盟(OGC)發佈了針對SQL的OpenGISR簡單特徵規範,在該文檔中,提出了延伸SQL RDBMS以支援空間數據的一些概念性方法。該規範可從OpenGIS網站上獲得http://www.opengis.org/docs/99-049.pdf。其中包含與本章有關的額外訊息。
MySQL實施了OGC建議的具有Geometry類型的SQL環境的一個子集。該術語指的是用一組集合類型延伸的環境。具有幾何值的SQL列是作為擁有集合類型的列實施的。該規範描述了SQL幾何類型集合,以及作用在這些類型上用於建立和分析幾何值的函數。
地理特徵指的是世界上具有地理位置的任何事物。它可以是:
· 實體,如山、池溏、城市。
· 空間,如郵政區域、熱帶。
· 可定義的位置,如兩條街道相交的十字路口。
有些檔案採用術語地理空間特徵來指代地理特徵。
幾何是另一個資料表示地理特徵的術語。最初,單詞幾何資料表示的是對大地的測量。來自製圖學的另一個含義指的是製圖人員用於繪製世界地圖的地理特徵。
本章將所有這些術語當作同義詞對待:地理特徵、地理空間特徵、或幾何。最常使用的術語是幾何。
我們將幾何定義為世界上具有地理位置的點或點的集合。
OGC具有幾何類型的SQL環境建議的幾何類型集合,基於OpenGIS幾何模型。在本模型中,每個幾何對像均具有下述一般屬性:
· 與空間參考系統相關,其中介紹了定義對象的坐標空間。
· 屬於某種幾何類。
幾何類定義了下述層次:
· 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定義為可實例化類。
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對象的維數與構成它們的元素的維數相同。
Point(點)指的是代資料表坐標空間中單個位置的幾何類。
Point示範
· 想像一張具有眾多城市的大世界地圖。每個Point對象可代資料表1個城市。
· 在城市地圖上,Point對象可代資料表1個公共汽車站。
Point屬性
· X-坐標值。
· Y-坐標值。
· Point定義為0維幾何對象。
· Point的邊界為空集合。
Curve(曲線)是一種1維幾何對象,通常由一系列點資料表示。Curve的特殊子類定義了點之間的內插類型。Curve是一種非實例化類。
Curve屬性
· Curve具有其點的坐標。
· Curve定義為1維幾何對象。
· 如果未通過相同的點兩次,Curve就是簡單的。
· 如果其起點等於其終點,Curve就是封閉的。
· 封閉Curve的邊界為空。
· 非封閉Curve的邊界由其兩個端點構成。
· 簡單且封閉的Curve是LinearRing。
LineString是具有點之間線性內插特性的Curve。
LineString示範
· 在世界地圖上,LineString對象可資料表示河流。
· 在城市地圖上,LineString對象可資料表示街道。
LineString屬性
· LineString具有線段的坐標,由每個連續的點對(兩點)定義。
· 如果僅包含兩點,LineString為Line。
· 如果它既是簡單的也是封閉的,LineString為LinearRing。
Surface是一種2維幾何對像。它是一種非實例化類。其唯一的可實例化子類是Polygon.
Surface屬性
· Surface定義為2維幾何對象。
· 在OpenGIS規範中,將簡單的Surface定義為由單一「patch」構成的幾何對象,它與單個外部邊界以及0或多個內部邊界有關。
· 簡單Surface的邊界是一組與其內部和外部邊界對應的封閉曲線的集合。
Polygon是代資料表多邊幾何對象的平面Surface。它由單個外部邊界以及0或多個內部邊界定義,其中,每個內部邊界定義為Polygon中的1個孔。
Polygon示範
· 在地區地圖上,Polygon對象可資料表示森林、區等。
Polygon聲明
· Polygon的邊界由一組構成其外部邊界和比內部邊界的LinearRing歸向集合構成(即,簡單且封閉的LineString對像)。
· Polygon沒有交叉的環。Polygon邊界中的環可能會在Point處相交,但僅以切線方式相交。
· Polygon沒有線、尖峰或穿孔。
· Polygon有由連接點集合構成的內部。
· Polygon可能包含孔。對於具有孔的Polygon,其外部不連接。每個孔定義了連接的外部部件。
前述聲明使得Polygon成為簡單的幾何對象。
MultiCurve屬性
· MultiCurve是1維幾何對象。
· 當且僅當其所有元素均是簡單的時,MultiCurve才是簡單的。任意兩元素的唯一交叉僅出現在兩元素邊界的點上。
· MultiCurve邊界是通過採用「模2聯合規則」(也稱為奇偶規則)獲得的:如果某一點位於奇數編號MultiCurve元素的邊界內,它將位於MultiCurve的邊界內。
· 如果其所有元素均是封閉的,則MultiCurve為封閉的。
· 封閉MultiCurve的邊界總為空。
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的邊界中。
幾何對像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值的正式生產規則。
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規範。
· GEOMETRY
· POINT
· LINESTRING
· POLYGON
GEOMETRY能夠保存任何類型的幾何值。其他的單值類型POINT、LINESTRING以及POLYGON只能保存特定幾何類型的值。
其他數據類型能保存多個值:
· MULTIPOINT
· MULTILINESTRING
· MULTIPOLYGON
· GEOMETRYCOLLECTION
GEOMETRYCOLLECTION能保存任意類型的對象集合。對於其他集合類型,MULTIPOINT、MULTILINESTRING、MULTIPOLYGON和GEOMETRYCOLLECTION,僅限於具有特定幾何類型的集合成員。
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值。
使用其WKT資料表示和SRID構造POINT值。
PolyFromText(wkt[,srid]) , PolygonFromText(wkt[,srid])
使用其WKT資料表示和SRID構造POLYGON值。
OpenGIS規範還介紹了用於構造Polygon或MultiPolygon值的可選函數,這些值基於環和封閉LineString值集合的WKT資料表達式。這些值可以相交。MySQL未實施下述函數:
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值。
使用其WKB資料表示和SRID構造POINT值。
PolyFromWKB(wkb[,srid]) , PolygonFromWKB(wkb[,srid])
使用其WKB資料表示和SRID構造POLYGON值。
OpenGIS規範還介紹了用於構造Polygon或MultiPolygon值的可選函數,這些值基於環和封閉LineString值集合的WKB資料表達式。這些值可以相交。MySQL未實施下述函數:
註釋:MySQL未實施本節所列的函數。
MySQL為建立幾何WKB資料表達式提供了有用的函數集合。本節介紹的函數是對OpenGIS規範的MySQL延伸。這些函數的結果是包含幾何值(無SRID)的BLOB值。這些函數的結果可被GeomFromWKB()函數系列中任意函數的第1個參量取代。構造WKB GeometryCollection。如果任何參量不是構造良好的幾何對像WKB資料表達式,返回值為NULL。
從多個WKB Point參量構造WKB LineString值。如果任何參量不是WKB Point,返回值為NULL。如果Point參量的數目小於2,返回值為NULL。
使用WKB LineString參量構造WKB MultiLineString值。如果任何參量不是WKB LineString,返回值為NULL。
使用WKB Point參量構造WKB MultiPoint值。如果任何參量不是WKB Point,返回值為NULL。
從一組WKB Polygon參量構造WKB MultiPolygon值。如果任何參量不是WKB Polygon,返回值為NULL。
使用其坐標構造WKB Point。
從多個WKB LineString參量構造WKB Polygon值。如果任何參量未資料表示為LinearRing的WKB形式(即,非封閉和簡單LineString),返回值為NULL。
· 使用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
建立了空間列後,可用空間數據填充它們。
值應以內部幾何格式保存,但您也能將其從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()」MySQL支援下述用於在內部格式和WKT或WKB格式間轉換幾何值的函數:
將採用內部幾何格式的值轉換為其WKB資料表示,並返回二進制結果。
SELECT AsBinary(g) FROM geom;
將採用內部幾何格式的值轉換為其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) | +--------------------------+
將字串值從其WKT資料表示轉換為內部幾何格式,並返回結果。也支援多種與類型相關的函數,如PointFromText()和LineFromText(),請參見19.4.2.1節,「使用WKT函數建立Geometry(幾何)值」。
將二進制值從其WKB資料表示轉換為內部幾何格式,並返回結果。也支援多種與類型相關的函數,如PointFromWKB()和LineFromWKB(),請參見19.4.2.2節,「使用WKB函數建立Geometry(幾何)值」。
本節列出的函數不限制其參量,可接受任何類型的幾何值。
返回幾何值g的固有維數。結果可以是-1、0、1或2。(關於這些值的含義,請參見19.2.2節,「類Geometry」)。
mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)')); +------------------------------------------------+ | Dimension(GeomFromText('LineString(1 1,2 2)')) | +------------------------------------------------+ | 1 | +------------------------------------------------+
返回幾何值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)) | +-------------------------------------------------------+
以字串形式返回幾何類型的名稱,幾何實例g是幾何類型的成員。該名稱與可實例化幾何子類之一對應。
mysql> SELECT GeometryType(GeomFromText('POINT(1 1)')); +------------------------------------------+ | GeometryType(GeomFromText('POINT(1 1)')) | +------------------------------------------+ | POINT | +------------------------------------------+
返回指明了幾何值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未實施這類函數:
Point由X和Y坐標構成,可使用下述函數獲得它們:
以雙精度數值返回點p的X坐標值。
mysql> SELECT X(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | X(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 56.7 | +--------------------------------------+
以雙精度數值返回點p的Y坐標值。
mysql> SELECT Y(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | Y(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 53.34 | +--------------------------------------+
LineString由Point值組成。您可以提取LineString的特定點,計數它所包含的點數,或獲取其長度。
返回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) | +-------------------------------------+
以雙精度數值返回LineString值1s在相關的空間參考系中的長度。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT GLength(GeomFromText(@ls)); +----------------------------+ | GLength(GeomFromText(@ls)) | +----------------------------+ | 2.8284271247462 | +----------------------------+
返回LineString值1s中的點數。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT NumPoints(GeomFromText(@ls)); +------------------------------+ | NumPoints(GeomFromText(@ls)) | +------------------------------+ | 3 | +------------------------------+
返回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) | +-------------------------------------+
返回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尚未實施這些函數:
以雙精度數值形式返回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 | +-----------------------------+
如果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 | +------------------------------+
以雙精度數值形式返回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 | +---------------------------+
以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) | +-------------------------------------------+
以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) | +----------------------------------------------+
返回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 | +---------------------------------------+
以雙精度數值形式返回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未實施這類函數:
返回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) | +----------------------------------------+
返回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.2節,「Geometry函數」中,我們討論了一些可從已有幾何對像構造新幾何對象的函數:
Envelope(g)
StartPoint(ls)
EndPoint(ls)
PointN(ls,n)
ExteriorRing(poly)
InteriorRingN(poly,n)
GeometryN(gc,n)
OpenGIS建議了很多可生成幾何對象的其他函數。它們是為實施空間操作符而設計的。
在MySQL中未實施這些函數。它們或許會在未來的版本中出現。
MySQL提供了一些可測試兩個幾何對像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 | +----------------------+----------------------+
返回1或0以指明兩個幾何變數g1和g2的最小邊界矩形是否不相交。
返回1或0以指明兩個幾何變數g1和g2的最小邊界矩形是否相同。
返回1或0以指明兩個幾何變數g1和g2的最小邊界矩形是否相交。
返回1或0以指明兩個幾何變數g1和g2的最小邊界矩形是否交迭。
返回1或0以指明兩個幾何變數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 | +--------------------+--------------------+
OpenGIS規範定義了下述函數。目前在MySQL尚未按照規範實施它們。對於那些已實施的函數,它們返回的結果與對應的基於MBR的函數返回的相同。包括下面列出的函數,但Distance()和Related()除外。
在未來的版本中,可能會實施這些函數,為空間分析提供全部支援,而不僅僅是基於MBR的支援。
這些函數作用在2個幾何值g1和g2上。
返回1或0以指明g1是否完全包含g2。
如果g1在空間上與g2相交,返回1。如果g1為Polygon或MultiPolygon,返回NULL,或如果g2為Point或MultiPoint返回NULL。否則,返回0。
術語「空間上交叉」指的是2個給定幾何對像之間的空間關係,它具有下述屬性:
o 2個結合對像交叉。
o 其交叉結果將導致其維數小於兩個給定幾何對像最大維數的幾何對象。
o 其交叉不等於兩個幾何對像中的任何1個。
返回1或0以指明g1是否與g2從空間上不相交。
以雙精度數值形式返回2個幾何對像中2點間的最短距離。
返回1或0以指明g1是否從空間上等同於g2。
返回1或0以指明g1是否從空間上與g2相交。
返回1或0以指明g1是否從空間上與g2交迭。如果2個幾何對像交叉而且其交叉將導致具有相同維數但並不等同於任一幾何對象的幾何對象,將使用術語「空間交迭」。
返回1或0以指明由pattern_matrix指定的空間關係是否在g1和g2間存在。如果參量為NULL返回-1。模式矩形為字串。如果實施了該函數,其規範將在此給出。
返回1或0以指明g1是否從空間上與g2接觸。如果幾何對象的內部不交叉,但1個幾何對象的邊界與另一個的邊界或內部交叉,這兩個幾何對象是從空間上接觸的。
返回1或0以指明g1是否從空間上位於g2內。
· 搜索包含給定點的所有對象的Point查詢。
· 搜索與給定地區交迭的所有對象的地區查詢。
MySQL採用了具有2次分裂特性的R-Trees來為空間列編製索引。使用幾何對象的MBR來建立空間索引。對於大多數幾何對象,MBR是包圍幾何對象的最小矩形。對於水平或垂直linestring,MBR退化為linestring的矩形。對於點,MBR是退化為點的矩形。
此外,還能在空間列上建立正常索引。需要為除POINT列之外的空間列上的任何索引(非空間)聲明前綴。
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
最佳化程式將調查可用的空間索引是否能包含在使用某些函數的查詢搜索中,如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節,「測試幾何對像間空間關係的函數」。
這是MySQL參考手冊的翻譯版本,關於MySQL參考手冊,請訪問dev.mysql.com。原始參考手冊為英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。