Go to the first, previous, next, last section, table of contents.


11 Spatial Extensions in MySQL

MySQL 4.1 introduces spatial extensions to allow the generation, storage, and analysis of geographic features. This chapter covers the following topics:

11.1 Introduction

MySQL implements spatial extensions following the specification of the Open GIS Consortium (OGC). This is an international consortium of more than 250 companies, agencies, and universities participating in the development of publicly available conceptual solutions that can be useful with all kinds of applications that manage spatial data. The OGC maintains a web site at http://www.opengis.org/.

In 1997, the Open GIS Consortium published the OpenGIS (R) Simple Features Specifications For SQL, a document that proposes several conceptual ways for extending an SQL RDBMS to support spatial data. This specification is available from the Open GIS web site at http://www.opengis.org/techno/implementation.htm. It contains additional information relevant to this chapter.

MySQL implements a subset of the SQL with Geometry Types environment proposed by OGC. This term refers to an SQL environment that has been extended with a set of geometry types. A geometry-valued SQL column is implemented as a column that has a geometry type. The specifications describe a set of SQL geometry types, as well as functions on those types to create and analyse geometry values.

A geographic feature is anything in the world that has a location. A feature can be:

You can also find documents that use term geospatial feature to refer to geographic features.

Geometry is another word that denotes a geographic feature. The original meaning of the word geometry denotes a branch of mathematics. Another meaning comes from cartography, referring to the geometric features that cartographers use to map the world.

This chapter uses all of these terms synonymously: geographic feature, geospatial feature, feature, or geometry. The term most commonly used here is geometry.

Let's define a geometry as a point or an aggregate of points representing anything in the world that has a location.

11.2 The OpenGIS Geometry Model

The set of geometry types proposed by OGC's SQL with Geometry Types environment is based on the OpenGIS Geometry Model. In this model, each geometric object has the following general properties:

11.2.1 The Geometry Class Hierarchy

The geometry classes define a hierarchy as follows:

Some of these classes are abstract (non-instantiable). That is, it is not possible to create an object of these classes. Other classes are instantiable and objects may be created of them. Each class has properties and instantiable classes may have assertions (rules that define valid class instances).

Geometry is the base class. It's an abstract class. The instantiable subclasses of Geometry are restricted to zero-, one-, and two-dimensional geometric objects that exist in two-dimensional coordinate space. All instantiable geometry classes are defined so that valid instances of a geometry class are topologically closed (that is, all defined geometries include their boundary).

The base Geometry class has subclasses for Point, Curve, Surface and GeometryCollection:

Geometry, Curve, Surface, MultiCurve, and MultiSurface are defined as non-instantiable classes. They define a common set of methods for their subclasses and are included for the reason of extensibility.

Point, LineString, Polygon, GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon are instantiable classes.

11.2.2 Class Geometry

Geometry is the root class of the hierarchy. It is a non-instantiable class but has a number of properties that are common to all geometry values created from any of the Geometry subclasses. These properties are described in the following list. (Particular subclasses have their own specific properties, described later.)

11.2.3 Geometry properties

A geometry value has the following properties:

11.2.4 Class Point

A Point is a geometry that represents a single location in coordinate space.

11.2.5 Point Examples

11.2.6 Point Properties

11.2.7 Class Curve

A Curve is a one-dimensional geometry, usually represented by a sequence of points. Particular subclasses of Curve define the type of interpolation between points. Curve is a non-instantiable class.

11.2.8 Curve Properties

11.2.9 Class LineString

A LineString is a Curve with linear interpolation between points.

11.2.10 LineString Examples

11.2.11 LineString Properties

11.2.12 Class Surface

A Surface is a two-dimensional geometry. It is a non-instantiable class. Its only instantiable subclass is Polygon.

11.2.13 Surface Properties

11.2.14 Class Polygon

A Polygon is a planar Surface representing a multisided geometry. It is defined by a single exterior boundary and zero or more interior boundaries, where each interior boundary defines a hole in the Polygon.

11.2.15 Polygon Examples

11.2.16 Polygon Assertions

In the above assertions, polygons are simple geometries. These assertions make a Polygon a simple geometry.

11.2.17 Class GeometryCollection

A GeometryCollection is a geometry that is a collection of one or more geometries of any class.

All the elements in a GeometryCollection must be in the same Spatial Reference System (that is, in the same coordinate system). GeometryCollection places no other constraints on its elements, although the subclasses of GeometryCollection described in the following sections may restrict membership. Retrictions may be based on:

11.2.18 Class MultiPoint

A MultiPoint is a geometry collection composed of Point elements. The points are not connected or ordered in any way.

11.2.19 MultiPoint Examples

11.2.20 MultiPoint Properties

11.2.21 Class MultiCurve

A MultiCurve is a geometry collection composed of Curve elements. MultiCurve is a non-instantiable class.

11.2.22 MultiCurve Properties

11.2.23 Class MultiLineString

A MultiLineString is a MultiCurve geometry collection composed of LineString elements.

11.2.24 MultiLineString Examples

11.2.25 Class MultiSurface

A MultiSurface is a geometry collection composed of surface elements. MultiSurface is a non-instantiable class. Its only instantiable subclass is MultiPolygon.

11.2.26 MultiSurface Assertions

11.2.27 Class MultiPolygon

A MultiPolygon is a MultiSurface object composed of Polygon elements.

11.2.28 MultiPolygon Examples

11.2.29 MultiPolygon Assertions

11.2.30 MultiPolygon Properties

11.3 Supported Spatial Data Formats

This section describes the standard spatial data formats that are used to represent geometry objects in queries. They are:

Internally, MySQL stores geometry values in a format that is not identical to either WKT or WKB format.

11.3.1 Well-Known Text (WKT) Format

The Well-Known Text (WKT) representation of Geometry is designed to exchange geometry data in ASCII form.

Examples of WKT representations of geometry objects are:

A Backus-Naur grammer that specifies the formal production rules for writing WKT values may be found in the OGC specification document referenced near the beginning of this chapter.

11.3.2 Well-Known Binary (WKB) Format

The Well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specifications. It is also defined in the ISO ``SQL/MM Part 3: Spatial'' standard.

WKB is used to exchange geometry data as binary streams represented by BLOB values containing geometric WKB information.

WKB uses 1-byte unsigned integers, 4-byte unsigned integers, and 8-byte double-precision numbers (IEEE 754 format). A byte is 8 bits.

For example, a WKB value that corresponds to POINT(1 1) consists of this sequence of 21 bytes (each represented here by two hex digits):

0101000000000000000000F03F000000000000F03F

The sequence may be broken down into these components:

Byte order : 01
WKB type   : 01000000
X          : 000000000000F03F
Y          : 000000000000F03F

Component representation is as follows:

WKB values for more complex geometry values are represented by more complex data structures, as detailed in the OpenGIS specification.

11.4 Creating a Spatially Enabled MySQL Database

This section describes the datatypes you can use for representing spatial data in MySQL, and the functions available for creating and retrieving spatial values.

11.4.1 MySQL Spatial Datatypes

MySQL provides a set of datatypes that correspond to classes in the class hierarchy of the OpenGIS Geometry Model. Some of these types hold single geometry values:

GEOMETRY is the most general of these single-value types; it can store geometry values of any type. The others restrict their values to a particular geometry type.

The other datatypes hold collections of values:

GEOMETRYCOLLECTION can store a collection of objects of any type. The other collection types restrict collection members to those having a particular geometry type.

11.4.2 Creating Spatial Values

This section describes how to create spatial values using Well-Known Text and Well-Known Binary functions that are defined in the OpenGIS standard, and using MySQL-specific functions.

11.4.2.1 Creating Geometry Values Using WKT Functions

MySQL provides a number of functions that take as input parameters a Well-Known Text representation (and, optionally, a spatial reference system identifier (SRID)), and return the corresponding geometry.

GeomFromText() accepts a WKT of any geometry type as its first argument. An implementation also provides type-specific construction functions for construction of geometry values of each geometry type.

GeomFromText(wkt[,srid])
GeometryFromText(wkt[,srid])
Constructs a geometry value of any type using its WKT representation and SRID.
PointFromText(wkt[,srid])
Constructs a POINT value using its WKT representation and SRID.
LineFromText(wkt[,srid])
LineStringFromText(wkt[,srid])
Constructs a LINESTRING value using its WKT representation and SRID.
PolyFromText(wkt[,srid])
PolygonFromText(wkt[,srid])
Constructs a POLYGON value using its WKT representation and SRID.
MPointFromText(wkt[,srid])
MultiPointFromText(wkt[,srid])
Constructs a MULTIPOINT value using its WKT representation and SRID.
MLineFromText(wkt[,srid])
MultiLineStringFromText(wkt[,srid])
Constructs a MULTILINESTRING value using its WKT representation and SRID.
MPolyFromText(wkt[,srid])
MultiPolygonFromText(wkt[,srid])
Constructs a MULTIPOLYGON value using its WKT representation and SRID.
GeomCollFromText(wkt[,srid])
GeometryCollectionFromText(wkt[,srid])
Constructs a GEOMETRYCOLLECTION value using its WKT representation and SRID.

The OpenGIS specification also describes optional functions for constructing Polygon or MultiPolygon values based on the WKT representation of a collection of rings or closed LineString values. These values may intersect. MySQL does not yet implement these functions:

BdPolyFromText(wkt,srid)
Constructs a Polygon value from a MultiLineString value in WKT format containing an arbitrary collection of closed LineString values.
BdMPolyFromText(wkt,srid)
Constructs a MultiPolygon value from a MultiLineString value in WKT format containing an arbitrary collection of closed LineString values.

11.4.2.2 Creating Geometry Values Using WKB Functions

MySQL provides a number of functions that take as input parameters a BLOB containing a Well-Known Binary representation (and, optionally, a spatial reference system identifier (SRID)), and return the corresponding geometry.

GeomFromWKT() accepts a WKB of any geometry type as its first argument. An implementation also provides type-specific construction functions for construction of geometry values of each geometry type.

GeomFromWKB(wkb[,srid])
GeometryFromWKB(wkt[,srid])
Constructs a geometry value of any type using its WKB representation and SRID.
PointFromWKB(wkb[,srid])
Constructs a POINT value using its WKB representation and SRID.
LineFromWKB(wkb[,srid])
LineStringFromWKB(wkb[,srid])
Constructs a LINESTRING value using its WKB representation and SRID.
PolyFromWKB(wkb[,srid])
PolygonFromWKB(wkb[,srid])
Constructs a POLYGON value using its WKB representation and SRID.
MPointFromWKB(wkb[,srid])
MultiPointFromWKB(wkb[,srid])
Constructs a MULTIPOINT value using its WKB representation and SRID.
MLineFromWKB(wkb[,srid])
MultiLineStringFromWKB(wkb[,srid])
Constructs a MULTILINESTRING value using its WKB representation and SRID.
MPolyFromWKB(wkb[,srid])
MultiPolygonFromWKB(wkb[,srid])
Constructs a MULTIPOLYGON value using its WKB representation and SRID.
GeomCollFromWKB(wkb[,srid])
GeometryCollectionFromWKB(wkt[,srid])
Constructs a GEOMETRYCOLLECTION value using its WKB representation and SRID.

The OpenGIS specification also describes optional functions for constructing Polygon or MultiPolygon values based on the WKB representation of a collection of rings or closed LineString values. These values may intersect. MySQL does not yet implement these functions:

BdPolyFromWKB(wkb,srid)
Constructs a Polygon value from a MultiLineString value in WKB format containing an arbitrary collection of closed LineString values.
BdMPolyFromWKB(wkb,srid)
Constructs a MultiPolygon value from a MultiLineString value in WKB format containing an arbitrary collection of closed LineString values.

11.4.2.3 Creating Geometry Values Using MySQL-Specific Functions

Note: MySQL does not yet implement the functions listed in this section.

MySQL provides a set of useful functions for creating geometry WKB representations. The functions described in this section are MySQL extensions to the OpenGIS specifications. The results of these functions are BLOB values containing WKB representations of geometry values with no SRID. The results of these functions can be substituted as the first argument for any function in the GeomFromWKB() function family.

Point(x,y)
Constructs a WKB Point using its coordinates.
MultiPoint(pt1,pt2,...)
Constructs a WKB MultiPoint value using WKB Point arguments. If any argument is not a WKBPoint, the return value is NULL.
LineString(pt1,pt2,...)
Constructs a WKB LineString valeu from a number of WKB Point arguments. If any argument is not a WKB Point, the return value is NULL. If the number of Point arguments is less than two, the return value is NULL.
MultiLineString(ls1,ls2,...)
Constructs a WKB MultiLineString value using using WBK LineString arguments. If any argument is not a LineString, the return value is NULL.
Polygon(ls1,ls2,...)
Constructs a WKB Polygon value from a number of WKB LineString arguments. If any argument does not represent the WKB of a LinearRing (that is, not a closed and simple LineString) the return value is NULL.
MultiPolygon(poly1,poly2,...)
Constructs a WKB MultiPolygon value from a set of WKB Polygon arguments. If any argument is not a WKB Polygon, the rerurn value is NULL.
GeometryCollection(g1,g2,...)
Constucts a WKB GeometryCollection. If any argument is not a well-formed WKB representation of a geometry, the return value is NULL.

11.4.3 Creating Spatial Columns

MySQL provides a standard way of creating spatial columns for geometry types, for example, with CREATE TABLE or ALTER TABLE. Currently, spatial columns are supported only for MyISAM tables.

11.4.4 Populating Spatial Columns

After you have created spatial columns, you can populate them with spatial data.

Values should be stored in internal geometry format, but you can convert them to that format from either Well-Known Text (WKT) or Well-Known Binary (WKB) format. The following examples demonstrate how to insert geometry values into a table by converting WKT values into internal geometry format.

You can perform the conversion directly in the INSERT statement:

INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'));

SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (GeomFromText(@g));

Or conversion can take place prior to the INSERT:

SET @g = GeomFromText('POINT(1 1)');
INSERT INTO geom VALUES (@g);

The following examples insert more complex geometries into the table:

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));

The preceding examples all use GeomFromText() to create geometry values. You can also use type-specific functions:

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));

Note that if a client application program wants to use WKB representations of geometry values, it is responsible for sending correctly formed WKB in queries to the server. However, there are several ways of satisfying this requirement. For example:

11.4.5 Fetching Spatial Data

Geometry values stored in a table can be fetched with conversion in internal format. You can also convert them into WKT or WKB format.

11.4.5.1 Fetching Spatial Data in Internal Format

Fetching geometry values using internal format can be useful in table-to-table transfers:

CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;

11.4.5.2 Fetching Spatial Data in WKT Format

The AsText() function provides textual access to geometry values. It converts a geometry from internal format into a WKT string.

mysql> SELECT AsText(g) FROM geom;
+-------------------------+
| AsText(p1)              |
+-------------------------+
| POINT(1 1)              |
| LINESTRING(0 0,1 1,2 2) |
+-------------------------+

11.4.5.3 Fetching Spatial Data in WKB Format

The AsBinary() function provides binary access to geometry values. It converts a geometry from internal format into a BLOB containing the WKB value.

SELECT AsBinary(g) FROM geom;

11.5 Analysing Spatial Information

After populating spatial columns with values, you are ready to query and analyse them. MySQL provides a set of functions to perform various operations on spatial data. These functions can be grouped into four major categories according to the type of operation they perform:

Spatial analysis functions can be used in many contexts, such as:

11.5.1 Functions To Convert Geometries Between Formats

MySQL supports the following functions for converting geometry values between internal format and either WKT or WKB format:

GeomFromText(wkt[,srid])
Converts a string value from its WKT representation into internal geometry format and returns the result. A number of type-specific functions are also supported, such as PointFromText() and LineFromText(); see section 11.4.2.1 Creating Geometry Values Using WKT Functions.
GeomFromWKB(wkb[,srid])
Converts a binary value from its WKB representation into internal geometry format and returns the result. A number of type-specific functions are also supported, such as PointFromWKB() and LineFromWKB(); see section 11.4.2.2 Creating Geometry Values Using WKB Functions.
AsText(g)
Converts a value in internal geometry format to its WKT representation and returns the resulting string.
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)  |
+--------------------------+
AsBinary(g)
Converts a value in internal geometry format to its WKB representation and returns the resulting binary value.

11.5.2 Geometry Property Analysis Functions

Each function that belongs to this group takes a geometry value as its argument and returns some quantitive or qualitive property of the geometry. Some functions restrict their argument type. Such functions return NULL if the argument is of an incorrect geometry type. For example, Area() returns NULL if the object type is neither Polygon nor MultiPolygon.

11.5.2.1 General Geometry Property Analysis Functions

The functions listed in this ssection do not restrict their argument and accept a geometry value of any type.

GeometryType(g)
Returns as a string the name of the geometry type of which the geometry instance g is a member. The name will correspond to one of the instantiable Geometry subclasses.
mysql> SELECT GeometryType(GeomFromText('POINT(1 1)'));
+------------------------------------------+
| GeometryType(GeomFromText('POINT(1 1)')) |
+------------------------------------------+
| POINT                                    |
+------------------------------------------+
Dimension(g)
Returns the inherent dimension of the geometry value g. The result can be -1, 0, 1, or 2. (The meaning of these values is given in section 11.2.2 Class Geometry.)
mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)'));
+------------------------------------------------+
| Dimension(GeomFromText('LineString(1 1,2 2)')) |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+
SRID(g)
Returns an integer indicating the Spatial Reference System ID for the geometry value g.
mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
+-----------------------------------------------+
| SRID(GeomFromText('LineString(1 1,2 2)',101)) |
+-----------------------------------------------+
|                                           101 |
+-----------------------------------------------+
Envelope(g)
Returns the Minimum Bounding Rectangle (MBR) for the geometry value g. The result is returned as a polygon value.
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))                        |
+-------------------------------------------------------+
The polygon is defined by the corner points of the bounding box:
POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))

The OpenGIS specification also defines the following functions, which MySQL does not yet implement:

Boundary(g)
Returns a geometry that is the closure of the combinatorial boundary of the geometry value g.
IsEmpty(g)
Returns 1 if the geomtry value g is the empty geometry, 0 if it is not empty, and -1 if the argument is NULL. If the geometry is empty, it represents the empty point set.
IsSimple(g)
Returns 1 if the geometry value g has no anomalous geometric points, such as self intersection or self tangency. IsSimple() returns 0 if the argument is not simple, and -1 if it is NULL. The description of each instantiable geometric class given earlier in the chapter includes the specific conditions that cause an instance of that class to be classified as not simple.

11.5.2.2 Point Property Analysis Functions

A Point consists of its X and Y coordinates, which may be obtained using the following functions:

X(p)
Returns the X-coordinate value for the point p as a double-precision number.
mysql> SELECT X(GeomFromText('Point(56.7 53.34)'));
+--------------------------------------+
| X(GeomFromText('Point(56.7 53.34)')) |
+--------------------------------------+
|                                 56.7 |
+--------------------------------------+
Y(p)
Returns the Y-coordinate value for the point p as a double-precision number.
mysql> SELECT Y(GeomFromText('Point(56.7 53.34)'));
+--------------------------------------+
| Y(GeomFromText('Point(56.7 53.34)')) |
+--------------------------------------+
|                                53.34 |
+--------------------------------------+

11.5.2.3 LineString Property Analysis Functions

A LineString consists of Point values. You can extract particular points of a LineString, count the number of points that it contains, or obtain its length.

EndPoint(ls)
Returns the Point that is the end point of the LineString value ls.
mysql> SELECT AsText(EndPoint(GeomFromText('LineString(1 1,2 2,3 3)')));
+------------------------------------------------------------+
| AsText(EndPoint(GeomFromText('LineString(1 1,2 2,3 3)')))  |
+------------------------------------------------------------+
| POINT(3 3)                                                 |
+------------------------------------------------------------+
GLength(ls)
Returns as a double-precision number the length of the LineString value ls in its associated spatial reference.
mysql> SELECT GLength(GeomFromText('LineString(1 1,2 2,3 3)'));
+--------------------------------------------------+
| GLength(GeomFromText('LineString(1 1,2 2,3 3)')) |
+--------------------------------------------------+
|                                  2.8284271247462 |
+--------------------------------------------------+
IsClosed(ls)
Returns 1 if the LineString value ls is closed (that is, it sStartPoint() and EndPoint() values are the same). Returns 0 if ls is not closed, and -1 if it is NULL.
mysql> SELECT IsClosed(GeomFromText('LineString(1 1,2 2,3 3)'));
+---------------------------------------------------+
| IsClosed(GeomFromText('LineString(1 1,2 2,3 3)')) |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
NumPoints(ls)
Returns the number of points in the LineString value ls.
mysql> SELECT NumPoints(GeomFromText('LineString(1 1,2 2,3 3)'));
+----------------------------------------------------+
| NumPoints(GeomFromText('LineString(1 1,2 2,3 3)')) |
+----------------------------------------------------+
|                                                  3 |
+----------------------------------------------------+
PointN(ls,n)
Returns the n-th point in the Linestring value ls. Point numbers begin at 1.
mysql> SELECT AsText(PointN(GeomFromText('LineString(1 1,2 2,3 3)'),2));
+-----------------------------------------------------------+
| AsText(PointN(GeomFromText('LineString(1 1,2 2,3 3)'),2)) |
+-----------------------------------------------------------+
| POINT(2 2)                                                |
+-----------------------------------------------------------+
StartPoint(ls)
Returns the Point that is the start point of the LineString value ls.
mysql> SELECT AsText(StartPoint(GeomFromText('LineString(1 1,2 2,3 3)')));
+-------------------------------------------------------------+
| AsText(StartPoint(GeomFromText('LineString(1 1,2 2,3 3)'))) |
+-------------------------------------------------------------+
| POINT(1 1)                                                  |
+-------------------------------------------------------------+

The OpenGIS specification also defines the following function, which MySQL does not yet implement:

IsRing(ls)
Returns 1 if the LineString value ls is closed (thatis, its StartPoint() and EndPoint() values are the same) and is simple (does not pass through the same point more than once). Returns 0 if ls is not a ring, and -1 if it is NULL.

11.5.2.4 MultiLineString Property Analysis Functions

GLength(mls)
Returns as a double-precision number the length of the MultiLineString value mls. The length of mls is equal to the sum of the lengths of its elements.
mysql> SELECT GLength(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))'));
+-------------------------------------------------------------------+
| GLength(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))')) |
+-------------------------------------------------------------------+
|                                                   4.2426406871193 |
+-------------------------------------------------------------------+
IsClosed(mls)
Returns 1 if the MultiLineString value mls is closed (that is, the StartPoint() and EndPoint() values are the same for each LineString in mls). Returns 0 if mls is not closed, and -1 if it is NULL.
mysql> SELECT IsClosed(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))'));
+--------------------------------------------------------------------+
| IsClosed(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))')) |
+--------------------------------------------------------------------+
|                                                                  0 |
+--------------------------------------------------------------------+

11.5.2.5 Polygon Property Analysis Functions

Area(poly)
Returns as a double-precision number the area of the Polygon value poly, as measured in its spatial reference system.
mysql> SELECT Area(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'));
+----------------------------------------------------------------------------+
| Area(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))')) |
+----------------------------------------------------------------------------+
|                                                                          8 |
+----------------------------------------------------------------------------+
NumInteriorRings(poly)
Returns the number of interior rings in the Polygon value poly.
mysql> SELECT NumInteriorRings(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'));
+----------------------------------------------------------------------------------------+
| NumInteriorRings(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))')) |
+----------------------------------------------------------------------------------------+
|                                                                                      1 |
+----------------------------------------------------------------------------------------+
ExteriorRing(poly)
Returns the exterior ring of the Polygon value poly as a LineString.
mysql> SELECT AsText(ExteriorRing(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))')));
+--------------------------------------------------------------------------------------------+
| AsText(ExteriorRing(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'))) |
+--------------------------------------------------------------------------------------------+
| LINESTRING(0 0,0 3,3 3,3 0,0 0)                                                            |
+--------------------------------------------------------------------------------------------+
InteriorRingN(poly,n)
Returns the n-th interior ring for the Polygon value poly as a LineString. Ring numbers begin at 1.
mysql> SELECT AsText(InteriorRingN(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'),1));
+-----------------------------------------------------------------------------------------------+
| AsText(InteriorRingN(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'),1)) |
+-----------------------------------------------------------------------------------------------+
| LINESTRING(1 1,1 2,2 2,2 1,1 1)                                                               |
+-----------------------------------------------------------------------------------------------+

The OpenGIS specification also defines the following functions, which MySQL does not yet implement:

Centroid(poly)
Returns the mathematical centroid for the Polygon value poly as a Point. The result is not guaranteed to be on the polygon.
PointOnSurface(poly)
Returns a Point value that is guaranteed to be on the Polygon value poly.

11.5.2.6 MultiPolygon Property Analysis Functions

Area(mpoly)
Returns as a double-precision number the area of the MultiPolygon value mpoly, as measured in its spatial reference system.
mysql> SELECT Area(GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'));
+-----------------------------------------------------------------------------------+
| Area(GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))')) |
+-----------------------------------------------------------------------------------+
|                                                                                 8 |
+-----------------------------------------------------------------------------------+

The OpenGIS specification also defines the following functions, which MySQL does not yet implement:

Centroid(mpoly)
Returns the mathematical centroid for the MultiPolygon value mpoly as a Point. The result is not guaranteed to be on the MultiPolygon.
PointOnSurface(mpoly)
Returns a Point value that is guaranteed to be on the MultiPolygon value mpoly.

11.5.2.7 GeometryCollection Property Analysis Functions

NumGeometries(gc)
Returns the number of geometries in the GeometryCollection value gc.
mysql> SELECT NumGeometries(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'));
+------------------------------------------------------------------------------------+
| NumGeometries(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))')) |
+------------------------------------------------------------------------------------+
|                                                                                  2 |
+------------------------------------------------------------------------------------+
GeometryN(gc,n)
Returns the n-th geometry in the GeometryCollection value gc. Geometry numbers begin at 1.
mysql> SELECT AsText(GeometryN(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'),1));
+------------------------------------------------------------------------------------------+
| AsText(GeometryN(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'),1)) |
+------------------------------------------------------------------------------------------+
| POINT(1 1)                                                                               |
+------------------------------------------------------------------------------------------+

11.5.3 Functions That Create New Geometries From Existing Ones

11.5.3.1 Geometry Functions That Produce New Geometries

In the section section 11.5.2 Geometry Property Analysis Functions, we've already discussed some functions that can construct new geometries from the existing ones:

11.5.3.2 Spatial Operators

OpenGIS proposes a number of other functions that can produce geometries. They are designed to implement Spatial Operators.

These functions are not yet implemented in MySQL. They should appear in future releases.

Intersection(g1,g2)
Returns a geometry that represents the point set intersection of the geometry values g1 with g2.
Union(g1,g2)
Returns a geometry that represents the point set union of the geometry values g1 and g2.
Difference(g1,g2)
Returns a geometry that represents the point set difference of the geometry value g1 with g2.
SymDifference(g1,g2)
Returns a geometry that represents the point set symmetric difference of the geometry value g1 with g2.
Buffer(g,d)
Returns a geometry that represents all points whose distance from the geometry value g is less than or equal to a distance of d.
ConvexHull(g)
Returns a geometry that represents the convex hull of the geometry value g.

11.5.4 Functions For Testing Spatial Relations Between Geometric Objects

The functions described in these sections take two geometries as input parameters and return a qualitive or quantitive relation between them.

11.5.5 Relations On Geometry Minimal Bounding Rectangles (MBRs)

MySQL provides some functions that can test relations between mininal bounding rectangles of two geometries g1 and g2. They include:

MBRContains(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangle of g1 contains the Minimum Bounding Rectangle of 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 |
+----------------------+----------------------+
MBRWithin(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangle of g1 is within the Minimum Bounding Rectangle of 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 |
+--------------------+--------------------+
MBRDisjoint(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries g1 and g2 are disjoint (do not intersect).
MBREquals(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries g1 and g2 are the same.
MBRIntersects(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries g1 and g2 intersect.
MBROverlaps(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries g1 and g2 overlap.
MBRTouches(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries g1 and g2 touch.

11.5.6 Functions That Test Spatial Relationships Between Geometries

The OpenGIS specification defines the following functions, which MySQL does not yet implement. They should appear in future releases. When implemented, they will provide full support for spatial analysis, not just MBR-based support.

The functions operate on two geometry values g1 and g2.

Contains(g1,g2)
Returns 1 or 0 to indicate whether or not g1 completely contains g2.
Crosses(g1,g2)
Returns 1 if g1 spatially crosses g2. Returns NULL if g1 is a Polygon or a MultiPolygon, or if g2 is a Point or a MultiPoint. Otherwise, returns 0. The term spatially crosses denotes a spatial relation between two given geometries that has the following properties:
Disjoint(g1,g2)
Returns 1 or 0 to indicate whether or not g1 is spatially disjoint from (does not intersect) g2.
Equals(g1,g2)
Returns 1 or 0 to indicate whether or not g1 is spatially equal to g2.
Intersects(g1,g2)
Returns 1 or 0 to indicate whether or not g1 spatially intersects g2.
Overlaps(g1,g2)
Returns 1 or 0 to indicate whether or not g1 spatially overlaps g2. The term spatially overlaps is used if two geometries intersect and their intersection results in a geometry of the same dimension but not equal to either of the given geometries.
Touches(g1,g2)
Returns 1 or 0 to indicate whether or not g1 spatially touches g2. Two geometries spatially touch if the interiors of the geometries do not intersect, but the boundary of one of the geometries intersects either the boundary or the interior of the other.
Within(g1,g2)
Returns 1 or 0 to indicate whether or not g1 is spatially within g2.
Distance(g1,g2)
Returns as a double-precision number the shortest distance between any two points in the two geometries.
Related(g1,g2,pattern_matrix)
Returns 1 or 0 to indicate whether or not the spatial relationship specified by pattern_matrix exists between g1 and g2. Returns -1 if the arguments are NULL. The pattern matrix is a string. Its specification will be noted here when this function is implemented.

11.6 Optimising Spatial Analysis

It is known that search operations in non-spatial databases can be optimised using indexes. This is true for spatial databases as well. With the help of a great variety of multi-dimensional indexing methods that have already been designed, it's possible to optimise spatial searches. The most typical of these are:

MySQL utilises R-Trees with quadratic splitting to index spatial columns. A spatial index is built using the MBR of a geometry. For most geometries, the MBR is a minimum rectangle that surrounds the geometries. For a horizontal or a vertical linestring, the MBR is a rectangle degenerated into the linestring. For a point, the MBR is a rectangle degenerated into the point.

11.6.1 Creating Spatial Indexes

MySQL can create spatial indexes using syntax similar to that for creating regular indexes, but extended with the SPATIAL keyword. Spatial columns that are indexed currently must be declared NOT NULL. The following examples demonstrate how to create spatial indexes.

To drop spatial indexes, use ALTER TABLE or DROP INDEX:

Example: Suppose that a table geom contains more than 32000 geometries, which are stored in the column g of type GEOMETRY. The table also has an AUTO_INCREMENT column fid for storing object ID values.

mysql> SHOW FIELDS FROM 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)

To add a spatial index on the column g, use this statement:

mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
Query OK, 32376 rows affected (4.05 sec)
Records: 32376  Duplicates: 0  Warnings: 0

11.6.2 Using a Spatial Index

The optimiser investigates whether available spatial indexes can be involved in the search for queries that use a function such as MBRContains() or MBRWithin() in the WHERE clause. For example, let's say we want to find all objects that are in the given rectangle:

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)

Now let's check the way this query is executed, using EXPLAIN:

mysql> EXPLAIN SELECT fid,AsText(g) FROM geom WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | geom  | range | g             | g    |      32 | NULL |   50 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

Now let's check what would happen if we didn't have a spatial index:

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);
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | geom  | ALL  | NULL          | NULL |    NULL | NULL | 32376 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

Let's execute the above query, ignoring the spatial key we have:

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)

When the index is not used, the execution time for this query rises from 0.00 seconds to 0.46 seconds.

In future releases, spatial indexes will also be used for optimising other functions. See section 11.5.4 Functions For Testing Spatial Relations Between Geometric Objects.

11.7 MySQL Conformance And Compatibility

11.7.1 GIS Features That Are Not Yet Implemented

Additional Metadata Views
OpenGIS specifications propose several additional metadata views. For example, a system view named GEOMETRY_COLUMNS contains a description of geometry columns, one row for each geometry column in the database.
Functions to add/drop spatial columns
OpenGIS assumes that columns can be added or dropped using special AddGeometryColumn() and DropGeometryColumn() functions. In MySQL, this is done using the ALTER TABLE, CREATE INDEX, and DROP INDEX statements instead.
Factors related to Spatial Reference Systems and their IDs (SRIDs):
The OpenGIS function Length() on LineString and MultiLineString currently should be called in MySQL as GLength()
The problem is that it conflicts with the existing SQL function Length() that calculates the length of string values, and sometimes it's not possible to distinguish whether the function is called in a textual or spatial context. We need either to solve this somehow, or decide on another function name.


Go to the first, previous, next, last section, table of contents.