代码之家  ›  专栏  ›  技术社区  ›  dthrasher

在SQL数据库中存储纬度和经度数据时使用什么数据类型?[复制品]

  •  273
  • dthrasher  · 技术社区  · 15 年前

    在符合ANSISQL的数据库中存储纬度或经度数据时,哪种数据类型最合适?应该 float 被使用,或 decimal ,还是…?

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

    8 回复  |  直到 9 年前
        1
  •  382
  •   dotjoe    9 年前

    Decimal(9,6)

    如果您不习惯精确和缩放参数,这里有一个可视的格式字符串:

    ###.######

        2
  •  6
  •   Keith    15 年前

    我们使用浮点数,但是任何带有6位小数的数字都可以。

        3
  •  3
  •   Kasper    15 年前

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

    但撇开这些细节不谈,我在SQL 2008最终包括地理支持之前使用了一个用户定义的类型。

        4
  •  2
  •   Larry    15 年前

    在Vanilla Oracle中,名为locator(空间的残缺版本)的特性要求使用数字数据类型(无精度)存储坐标数据。当你试图创建基于函数的索引来支持空间查询时,它会被阻塞。

        5
  •  2
  •   Glenn Plas    12 年前

    您可以很容易地在无符号整数字段中存储lat/lon十进制数,而不是将它们拆分为整数和十进制部分,并使用以下转换算法按照这里的建议单独存储它们:

    作为存储的mysql函数:

    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)
    

    又回来

    CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7)) 
    RETURNS int(10)
    DETERMINISTIC
    RETURN s * 600000
    

    需要存储在 无符号整数(10) 这在MySQL和无类型的sqlite中都有效。

    通过经验,我发现这个方法非常快速,如果你只需要存储坐标并检索它们来做一些数学运算的话。

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

    function LatitudeSmallToFloat($LatitudeSmall){
       if(($LatitudeSmall>0)&&($LatitudeSmall>>31)) 
         $LatitudeSmall=-(0x7FFFFFFF-($LatitudeSmall&0x7FFFFFFF))-1;
       return (float)$LatitudeSmall/(float)600000;
    }
    

    然后又回来:

    function LatitudeFloatToSmall($LatitudeFloat){
       $Latitude=round((float)$LatitudeFloat*(float)600000);
       if($Latitude<0) $Latitude+=0xFFFFFFFF;
       return $Latitude;
    }
    

    这在创建例如memcached的整数唯一键方面也有一些额外的优势。(例如:缓存地理代码结果)。希望这能增加讨论的价值。

    另一个应用程序可能是,当您没有GIS扩展并且只想保留几百万个这样的lat/lon对时,您可以使用MySQL中这些字段上的分区来受益于它们是整数:

    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 */
    
        6
  •  1
  •   Sam    15 年前

    我会为您的数据使用适当精度的小数。

        7
  •  1
  •   jpj625    15 年前

    我认为这取决于你最经常需要做的手术。

    如果需要将整数值作为十进制数,则使用具有适当精度和小数位数的十进制。我相信漂浮物远远超出你的需要。

    如果要经常转换为/从deg_:min'sec“分数表示法,我会考虑将每个值存储为整数类型(smallint、tinyint、tinyint、smallint?).

        8
  •  1
  •   syed Ahsan Jaffri    12 年前

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

    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