本教程将指导您在 SQL Anywhere 中试用某些空间要素。要试用空间要素,首先请将 ESRI shapefile 装载到示例数据库 (demo.db) 中以获得可供试用的有效空间数据。
教程分为以下几部分:
本部分教程将指导您使用 sa_install_feature 系统过程安装大量预定义的测量单位和空间参照系,在本教程后面的部分中将会用到它们。
使用 Interactive SQL,以 DBA 用户身份或 SYS_SPATIAL_ADMIN_ROLE 组成员身份打开并连接到示例数据库 (demo.db)。
示例数据库位于 /samples 目录中。关于 /samples 目录的缺省位置,请参见SQLANYSAMP 12 环境变量。
执行以下语句:
CALL sa_install_feature( 'st_geometry_predefined_srs' ); |
语句执行完成后,即成功安装了附加的测量单位和空间参照系。
另请参见:sa_install_feature 系统过程和CREATE SPATIAL REFERENCE SYSTEM 语句。
要确定数据库中所安装的测量单位,请执行以下查询:
SELECT * FROM SYSUNITOFMEASURE; |
另请参见: SYSUNITOFMEASURE 系统视图。
要确定数据库中所安装的空间参照系,可以在 Sybase Central 中查看 [空间参照系] 文件夹,或执行以下查询:
SELECT * FROM SYSSPATIALREFERENCESYSTEM; |
在本部分教程中,您将从美国人口普查局网站 ( www2.census.gov) 下载 ESRI shapefile。您下载的 shapefile 表示马萨诸塞州在 2002 年人口普查汇总期间使用的 5 位邮政编码信息。各邮政编码地区被视为多边形或多面。
创建名为 c:\temp\massdata 的本地目录。
转至以下 URL: http://www2.census.gov/cgi-bin/shapefiles2009/national-files
在页面右侧的 [State- and County-based Shapefiles](基于州和县的 Shapefile)下拉列表中,选择 [Massachusetts](马萨诸塞州),然后单击 [Submit](提交)。
在页面左侧选择 [5-Digit ZIP Code Tabulation Area (2002)](5 位邮政编码汇总地区 (2002)),然后单击 [Download Selected Files](下载所选文件)。
当出现提示时,将 zip 文件 multiple_tiger_files.zip 保存到 c:\temp\massdata 中,并解压缩其内容。这将创建一个名为 25_MASSACHUSETTS 的子目录,其中包含另一个名为 tl_2009_25_zcta5.zip 的 zip 文件。
将 tl_2009_25_zcta5.zip 中的内容解压到 C:\temp\massdata。
这将解压缩出五个文件,包括将用于向数据库中装载空间数据的 ESRI shapefile (.shp)。
本部分教程将指导您在 ESRI shapefile 中查找列,并使用该信息创建表以向其中装载数据。
由于空间数据与特定空间参照系相关联,因此向数据库中装载数据时,必须将其装载到同一空间参照系或者至少具有等效定义的空间参照系中。要查找 ESRI shapefile 的空间参照系信息,请在文本编辑器中打开项目文件 c:\temp\massdata\tl_2009_25_zcta5.prj。此文件中包含所需的空间参照系信息。
GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",
SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] |
字符串 GCS_North_American_1983 即为与数据相关联的空间参照系的名称。
对 SYSSPATIALREFERENCESYSTEM 视图执行快速查询后 (SELECT * FROM SYSSPATIALREFERENCESYSTEM WHERE srs_name='GCS_North_American_1983';
),查询结果表明此名称并未出现在预定义 SRS 列表中。但您可以查询具有相同定义的空间参照系并改为使用该空间参照系:
SELECT * FROM SYSSPATIALREFERENCESYSTEM WHERE definition LIKE '%1983%' AND definition LIKE 'GEOGCS%'; |
该查询返回单个空间参照系,即 SRID 为 4269 的 NAD83,该空间参照系具有相同的定义,且适合向其中装载数据。
接下来,您需要创建一个表以向其中装载空间数据。要执行此操作,必须先确定您的 ESRI shapefile 中包含哪些列。以下语句可返回列的说明。还可以向输出数据中添加一些格式设置信息,以帮助准备将包含在 CREATE TABLE 语句中的结果集。请注意上一步中查找到的 SRID 在调用该 sa_describe_shapefile 系统过程中的用法:
SELECT name || ' ' || domain_name_with_size || ', ' FROM sa_describe_shapefile('C:\temp\massdata\tl_2009_25_zcta5.shp', 4269) ORDER BY column_number; |
选择结果集中的所有行,然后右键单击并选择 [复制数据] » [单元格]。
在 Interactive SQL 的顶部窗格中,删除所执行的 SELECT 语句并输入 CREATE TABLE Massdata(,然后粘贴刚才复制的单元格。
将 record_number 列的定义更改为 PRIMARY KEY(即,将 record_number int,
更改为 record_number int PRIMARY KEY,
)。
将列名称 ZCTA5CE 更改为 ZIP。
对于列表中的最后一列,删除结尾逗号并依次添加右方括号和分号。
CREATE TABLE 语句应如下所示:
CREATE TABLE Massdata( record_number int PRIMARY KEY, geometry ST_Geometry(SRID=4269), ZIP varchar(5), CLASSFP varchar(2), MTFCC varchar(5), FUNCSTAT varchar(1), ALAND bigint, AWATER bigint, INTPTLAT varchar(11), INTPTLON varchar(12) ); |
执行 CREATE TABLE 语句创建表。
使用以下语句将 ESRI shapefile 文件中的空间数据装载到 Massdata 中。完成此过程可能需要几分钟。
LOAD TABLE Massdata USING FILE 'C:\temp\massdata\tl_2009_25_zcta5.shp' FORMAT SHAPEFILE; |
在 Massdata 表中,列 INTPTLON 和 INTPTLAT 分别表示邮政编码地区中心的 X 坐标和 Y 坐标。在此步骤中,将把值合并到名为 CenterPoint 的 ST_Point 列中。CenterPoint 列中的各个值(WKT 格式)即为几何列中所表示的邮政编码地区的中心点。本教程后面的某些示例中将会用到该列。
要创建该列,请执行以下语句:
ALTER TABLE Massdata ADD CenterPoint AS ST_Point(SRID=4269) COMPUTE( new ST_Point( CAST( INTPTLON AS DOUBLE ), CAST( INTPTLAT AS DOUBLE ), 4269 ) ); |
可通过在 Interactive SQL 中执行以下语句来查看该数据:
SELECT * FROM Massdata; |
结果中的每一行代表一个邮政编码地区。Massdata.geometry 以多边形(一个地区)或多面(两个或多个不相邻的地区)的形式保存邮政编码地区的形状信息。
要将单个几何(一个邮政编码地区)作为形状进行查看,请双击 Massdata.geometry 中的任一个值,然后单击 [列值] 窗口中的 [空间预览] 选项卡。
如果收到的错误消息指出值过大或建议您在结果中包括主键,那是因为为了在 Interactive SQL 中显示这些值,已将它们截断。要修复此错误,您可以修改查询以在结果中包括主键列,也可以调整 Interactive SQL 的 [截断长度] 设置。如果您不想每次查询几何时都必须在结果中包括主键以在 Interactive SQL 中查看几何,那么建议您更改 [截断长度] 设置。
要更改 Interactive SQL 的 [截断长度] 设置,请单击 [工具] » [选项] » [SQL Anywhere],然后将 [截断长度] 设置成较大的数字,如 100000。
要将整个数据集作为一个形状进行查看,请单击 [工具] » [空间查看器] 打开 SQL Anywhere [空间查看器],然后执行以下查询:
SELECT geometry FROM Massdata UNION ALL SELECT centerpoint FROM Massdata; |
本部分教程将以切合实际的示例来指导您使用某些空间方法查询数据。
将对 SpatialContacts(包含人员姓名和联系方式信息的表--其中大部分居住在马萨诸塞州)和 Massdata(您所创建的表)这两个表或其中任一个表执行查询。还将学习如何计算距离,其中将涉及向数据库中添加测量单位。
在接下来的步骤中,将使用邮政编码地区 01775。
创建名为 @Mass_01775
的变量,用于保存相关几何。
CREATE VARIABLE @Mass_01775 ST_Geometry; SELECT geometry INTO @Mass_01775 FROM Massdata WHERE ZIP = '01775'; |
假设您想要在 SpatialContacts 表中查找邮政编码地区 01775 及其周边邮政编码地区中的所有联系人信息。要达到这个目的,可以使用 ST_Intersects 方法,该方法可返回与指定的几何相交或与其完全相同的几何。将执行以下语句:
SELECT c.Surname, c.GivenName, c.Street, c.City, c.PostalCode, z.geometry FROM Massdata z, SpatialContacts c WHERE c.PostalCode = z.ZIP AND z.geometry.ST_Intersects( @Mass_01775 ) = 1; |
Massdata.geometry 中的所有行都与同一空间参照系 (SRID 4269) 相关联,这是因为创建几何列并将数据装载到其中时为列分配了 SRID 4269。
但您仍可以创建未声明的 ST_Geometry 列(即,未指派 SRID 的列)。有时,您可能需要在单个列中存储与不同 SRS 相关联的空间值。此时,在对这些值进行运算时,将分别使用与各个值相关联的空间参照系。
不过,使用未声明的列存在着一个风险,即:数据库服务器不会阻止您更改与未声明列中的数据相关联的空间参照系。
但如果列已具有声明的 SRID,则数据库服务器将不允许您修改与其中的数据相关联的空间参照系。必须先卸载数据,再截断声明列中的数据,然后再更改空间参照系,最后再重新装载数据。
无论列声明与否,都可通过 ST_SRID 方法来确定与列中的值相关联的 SRID。例如,以下语句可显示指派给 Massdata.geometry 列中各行的 SRID:
SELECT geometry.ST_SRID() FROM Massdata; |
可以使用 ST_CoveredBy 方法来检查某一几何是否完全位于另一几何中。例如,Massdata.CenterPoint(T_Point 类型)包含邮政编码地区中心的经度/纬度坐标,而 Massdata.geometry 则包含反映邮政编码地区的多边形。可通过执行以下查询进行快速检查,以确保所有 CenterPoint 值均已设置在其邮政编码地区之内:
SELECT * FROM Massdata WHERE NOT(CenterPoint.ST_CoveredBy(geometry) = 1); |
未返回任何行,说明所有 CenterPoint 值都包含在 Massdata.geometry 中的对应相关联几何中,当然,此项检查并不会验证这些值是否为真正的中心。如果想执行此验证,需要将数据投影到平面地球空间参照系,然后使用 ST_Centroid 方法检查 CenterPoint 值。有关如何将数据投影到另一空间参照系的信息,请参见第 6 部分:投影空间数据。
可以使用 ST_Distance 方法测量两个邮政编码地区中心点间的距离。例如,假设您希望得到邮政编码地区 01775 方圆 100 英里之内的邮政编码列表,则可执行以下查询:
SELECT c.PostalCode, c.City, z.CenterPoint.ST_Distance( ( SELECT CenterPoint FROM Massdata WHERE ZIP = '01775' ), 'Statute mile' ) dist, z.CenterPoint FROM Massdata z, SpatialContacts c WHERE c.PostalCode = z.ZIP AND dist <= 100 ORDER BY dist; |
如果是否知道确切的距离并不重要,则可改用 ST_WithinDistance 方法来构造查询,此方法对于某些数据集(尤其是对于大型几何)的性能更佳:
SELECT c.PostalCode, c.City, z.CenterPoint FROM Massdata z, SpatialContacts c WHERE c.PostalCode = z.ZIP AND z.CenterPoint.ST_WithinDistance( ( SELECT CenterPoint FROM Massdata WHERE ZIP = '01775' ), 100, 'Statute mile' ) = 1 ORDER BY c.PostalCode; |
可以导出 SVG 格式的几何,以在 Interactive SQL 或与 SVG 兼容的应用程序中查看该几何。在以下过程中,将创建一个 SVG 文档以查看以 WKT 表示的多面。
在 Interactive SQL 中,执行以下语句,为示例几何创建一个变量:
CREATE OR REPLACE VARIABLE @svg_geom ST_Polygon = (NEW ST_Polygon('Polygon ((1 1, 5 1, 5 5, 1 5, 1 1), (2 2, 2 3, 3 3, 3 2, 2 2))')); |
在 Interactive SQL 中,执行以下 SELECT 语句以调用 ST_AsSVG 方法:
SELECT @svg_geom.ST_AsSVG() AS svg; |
结果集中只有一行,该行即为 SVG 图像。可以在 Interactive SQL 中使用 [SVG 预览] 功能查看该图像。要执行此操作,请双击结果行,然后选择 [SVG 预览] 选项卡。
如果收到错误消息,指出无法从数据库读取完整值,则需要更改 Interactive SQL 的 [截断长度] 设置。要执行此操作,请在 Interactive SQL 中单击 [工具] » [选项] » [SQL Anywhere],然后将 [截断长度] 设置成较大的数字,如 100000。然后再次执行查询并查看几何。
上一步骤介绍了如何在 Interactive SQL 中预览 SVG 图像。但是,将得到的 SVG 写入到一个文件中可能更有用,因为这样外部应用程序便可读取该文件。可以使用 xp_write_file 系统过程或 WRITE_CLIENT_FILE 函数 [String] 将 SVG 写入到相对于数据库服务器或客户端计算机的文件中。在下一示例中,将使用 OUTPUT 语句 [Interactive SQL]。
在 Interactive SQL 中,执行以下 SELECT 语句以调用 ST_AsSVG 方法并将几何输出到名为 myPolygon.svg 的文件中:
SELECT @svg_geom.ST_AsSVG(); OUTPUT TO 'c:\\myPolygon.svg' QUOTE '' ESCAPES OFF FORMAT TEXT |
必须包括 QUOTE ''
和 ESCAPES OFF
子句,否则 XML 中将被插入回车符和单引号以保留空格,而这会导致输出的 SVG 文件无效。
在 Web 浏览器或支持查看 SVG 图像的应用程序中打开该 SVG 文件。也可以在文本编辑器中打开该 SVG,查看几何的 XML。
ST_AsSVG 方法可从单个几何生成 SVG 图像。某些情况下,您希望生成包括组中所有 shape 的 SVG 图像。ST_AsSVGAggr 方法正是这样一个可以将多个几何合并到单个 SVG 图像中的集合函数。首先,创建一个变量用以保存 SVG 图像,然后使用 ST_AsSVGAggr 方法生成 SVG 图像。
CREATE OR REPLACE VARIABLE @svg XML; SELECT ST_Geometry::ST_AsSVGAggr( geometry, 'attribute=fill="black"' ) INTO @svg FROM Massdata; |
此时,@svg
变量即保存了表示 Massdata 表中所有邮政编码地区的 SVG 图像。'attribute=fill="black"'
用于指定所生成图像的填充颜色。如果不指定,则数据库服务器将随机选择一种填充颜色。现在,您已经具有包含所需 SVG 图像的变量,接下来您便可将其写入到文件中,以便用其它应用程序进行查看。执行以下语句可将该 SVG 图像写入到相对于数据库服务器的文件中。
CALL xp_write_file( 'c:\\temp\\Massdata.svg', @svg ); |
也可以用 WRITE_CLIENT_FILE 函数写入相对于客户端应用程序的文件。但可能需要执行附加步骤以确保启用了相应权限。如果在支持 SVG 数据的应用程序中打开该 SVG 图像,则会显示如下所示的图像:
您会注意到,该图像并未均匀地呈现黑色;相邻邮政编码地区间存在细小的间隙。这些间隙实际上是各几何间的白线,这也是渲染 SVG 的特点。而数据间其实并不存在任何间隙。较大的白线是河流和湖泊。
另请参见:
本部分教程指导您如何将数据投影到使用平面地球模型的空间参照系中,以便计算面积和距离测量值。
从 ESRI shapefile 向数据库中装载数据时,已为 Massdata 中的空间值指派了 SRID 4269(NAD83 空间参照系)。SRID 4269 是球形地球空间参照系。然而,某些计算操作(例如,计算几何面积)和某些空间谓语在球形地球模型中不被支持。如果数据当前与球形地球空间参照系相关联,则可创建一个用于将数值投影到平面地球空间参照系的新空间列,然后对该列执行计算操作。
要测量表示邮政编码地区的多边形的面积,必须先将 Massdata.geometry 中的数据投影到平面地球空间参照系。
要选择合适的 SRID 以将 Massdata.geometry 中的数据投影到该 SRID,请按如下方式查询 SYSSPATIALREFERENCESYSTEM 系统视图以获得包含 "马萨诸塞州" 字样的 SRID:
SELECT * FROM SYSSPATIALREFERENCESYSTEM WHERE srs_name LIKE '%massachusetts%'; |
此查询可返回几个适用于马萨诸塞州数据的 SRID。本教程中将使用 3586。
接下来,必须创建一个名为 Massdata.proj_geometry 的列,然后用 ST_Transform 方法将几何投影到该列,进而投影到 3586 中:
ALTER TABLE Massdata ADD proj_geometry AS ST_Geometry(SRID=3586) COMPUTE( geometry.ST_Transform( 3586 ) ); |
可以使用 Massdata.proj_geometry 计算面积。例如,可执行以下语句:
SELECT zip, proj_geometry.ST_ToMultiPolygon().ST_Area('Statute Mile') AS area FROM Massdata ORDER BY area DESC; |
球形地球空间参照系不支持 ST_Area,但支持 ST_Distance,不过,仅限于计算点几何之间的距离。
要想了解投影至另一空间参照系对距离计算的影响,可使用以下查询在球形地球模型(更精确)或投影平面地球模型上计算邮政编码地区中心点间的距离。两种模型所得出的计算结果毫无差异,因为所选投影适合该数据集。
SELECT M1.zip, M2.zip, M1.CenterPoint.ST_Distance( M2.CenterPoint, 'Statute Mile' ) dist_round_earth, M1.CenterPoint.ST_Transform( 3586 ).ST_Distance( M2.CenterPoint.ST_Transform( 3586 ), 'Statute Mile' ) dist_flat_earth FROM Massdata M1, Massdata M2 WHERE M1.ZIP = '01775' ORDER BY dist_round_earth DESC; |
假设您想查找与邮政编码地区 01775 相毗邻的邮政编码地区。要达到此目的,需要使用 ST_Touches 方法。ST_Touches 方法用于对几何进行比较,以了解某一几何是否与另一几何相接触但不与之相重叠。注意,ST_Touches 返回的结果不包括与邮政编码 01775 相对应的行(这不同于 ST_Intersects 方法)。
DROP VARIABLE @Mass_01775; CREATE VARIABLE @Mass_01775 ST_Geometry; SELECT geometry INTO @Mass_01775 FROM Massdata WHERE ZIP = '01775'; SELECT record_number, proj_geometry FROM Massdata WHERE proj_geometry.ST_Touches( @Mass_01775.ST_Transform( 3586 ) ) = 1; |
可以使用 ST_UnionAggr 方法返回表示一组邮政编码地区联合的几何。例如,假设您想获得一个反映 01775 所毗邻的邮政编码区域(但不包括 01775 区域)联合的几何。
在 Interactive SQL 中,单击 [工具] » [空间查看器],然后执行以下查询:
SELECT ST_Geometry::ST_UnionAggr(proj_geometry) FROM Massdata WHERE proj_geometry.ST_Touches( @Mass_01775.ST_Transform( 3586 ) ) = 1; |
双击结果即可对其进行查看。
如果收到错误消息,指出无法从数据库读取整列内容,则需要增大 Interactive SQL 的 [截断长度] 设定值。要执行此操作,请在 Interactive SQL 中单击 [工具] » [选项] » [SQL Anywhere],然后将 [截断长度] 设置成较大的数字。然后再次执行查询并查看几何。
按照以下位置所述的步骤将示例数据库 (demo.db) 恢复至其初始状态: 重新创建示例数据库 (demo.db)。
![]() |
使用DocCommentXchange 讨论此页。
|
版权 © 2010, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.0 |