在SQL数据库中存储纬度和经度数据时要使用的数据类型是什么?

What datatype to use when storing latitude and longitude data in SQL databases?

本问题已经有最佳答案,请猛点这里访问。

在ANSI SQL兼容数据库中存储纬度或经度数据时,哪种数据类型最合适? 应该float,还是decimal,还是......?

我知道Oracle,MySql和SQL Server已经添加了一些专门用于处理地理数据的特殊数据类型,但我对如何将信息存储在"普通的"SQL数据库中感兴趣。


Decimal(9,6)

如果你不习惯精度和比例参数,这里有一个格式字符串visual:

###.######


我们使用float,但任何带有6位小数的数字风格也应该有效。


好吧,你问过如何存储纬度/经度,我的答案是:不要,你可以考虑使用WGS 84(欧洲ETRS 89),因为它是地理参考的标准。

但除了那个细节,我在SQL 2008之前的几天使用了用户定义类型,最后包括地理支持。


您可以轻松地将lat / lon十进制数存储在无符号整数字段中,而不是将它们拆分为整数和小数部分,并使用以下转换算法分别存储这些内容:

作为存储的mysql函数:

1
2
3
4
5
CREATE DEFINER=`r`@`l` FUNCTION `PositionSmallToFloat`(s INT)
RETURNS DECIMAL(10,7)
DETERMINISTIC
RETURN IF( ((s > 0) && (s >> 31)) , (-(0x7FFFFFFF -
(s & 0x7FFFFFFF))) / 600000, s / 600000)

然后回来

1
2
3
4
CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7))
RETURNS INT(10)
DETERMINISTIC
RETURN s * 600000

这需要存储在unsigned int(10)中,这适用于mysql以及无类型的sqlite。

通过经验,我发现这个工作真的很快,如果你需要的只是存储坐标并检索那些做数学的。

在PHP中这两个函数看起来像

1
2
3
4
5
FUNCTION LatitudeSmallToFloat($LatitudeSmall){
   IF(($LatitudeSmall>0)&&($LatitudeSmall>>31))
     $LatitudeSmall=-(0x7FFFFFFF-($LatitudeSmall&0x7FFFFFFF))-1;
   RETURN (FLOAT)$LatitudeSmall/(FLOAT)600000;
}

又回来了:

1
2
3
4
5
FUNCTION LatitudeFloatToSmall($LatitudeFloat){
   $Latitude=round((FLOAT)$LatitudeFloat*(FLOAT)600000);
   IF($Latitude<0) $Latitude+=0xFFFFFFFF;
   RETURN $Latitude;
}

这在创建例如具有整数的memcached唯一键方面具有一些额外的优点。 (例如:缓存地理编码结果)。希望这为讨论增添价值。

另一个应用程序可能是当你没有GIS扩展并且只想保留几百万个lat / lon对时,你可以在mysql中的那些字段上使用分区以从它们是整数的事实中受益:

1
2
3
4
5
6
7
8
9
CREATE TABLE: CREATE TABLE `Locations` (
  `lat` INT(10) UNSIGNED NOT NULL,
  `lon` INT(10) UNSIGNED NOT NULL,
  `location` text,
  PRIMARY KEY (`lat`,`lon`) USING BTREE,
  KEY `index_location` (`locationText`(30))
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY KEY ()
PARTITIONS 100 */

在vanilla Oracle中,名为LOCATOR(Spatial的残缺版本)的功能要求使用NUMBER(无精度)数据类型存储坐标数据。当您尝试创建基于函数的索引来支持空间查询时,否则会窒息。


您应该看一下SQL Server 2008中引入的新的Spatial数据类型。它们专门设计了这种任务,使索引和查询数据更加容易和高效。

http://msdn.microsoft.com/en-us/library/bb933876(v=sql.105).aspx

http://blogs.technet.com/andrew/archive/2007/11/26/sql-server-2008-spatial-data-types.aspx


我认为这取决于您最需要做的操作。

如果您需要十进制数的完整值,则使用具有适当精度和比例的十进制。我相信Float超出了你的需求。

如果您经常转换为/来自degomin'sec"分数表示法,我会考虑将每个值存储为整数类型(smallint,tinyint,tinyint,smallint?)。


我会使用具有适当精度的十进制数据。