【问题标题】:What's the best way to store co-ordinates (longitude/latitude, from Google Maps) in SQL Server?在 SQL Server 中存储坐标(经度/纬度,来自谷歌地图)的最佳方式是什么?
【发布时间】:2010-10-07 19:17:47
【问题描述】:

我正在 SQL Server 2008 中设计一个表,该表将存储用户列表和 Google 地图坐标(经度和纬度)。

我需要两个字段,还是可以用 1 个字段完成?

用于存储此类数据的最佳(或最常见)数据类型是什么?

【问题讨论】:

    标签: sql-server sql-server-2008 latitude-longitude spatial


    【解决方案1】:

    公平警告! 在接受使用 GEOGRAPHY 类型的建议之前,请确保您不打算使用 Linq 或实体框架来访问数据,因为它不受支持(截至 2010 年 11 月)并且你会难过的!

    2017 年 7 月更新

    对于那些现在阅读此答案的人来说,它已经过时了,因为它指的是过时的技术堆栈。有关详细信息,请参阅 cmets。

    【讨论】:

    【解决方案2】:

    查看 SQL Server 2008 中引入的新空间数据类型。它们专为此类任务而设计,使索引和查询更加容易和高效。

    更多信息:

    【讨论】:

      【解决方案3】:

      我不知道 SQL Server 的答案,但是...

      MySQL中保存为FLOAT( 10, 6 )

      这是来自Google developer documentation的官方推荐。

      CREATE TABLE `coords` (
        `lat` FLOAT( 10, 6 ) NOT NULL ,
        `lng` FLOAT( 10, 6 ) NOT NULL ,
      ) ENGINE = MYISAM ;
      

      【讨论】:

      • 这个问题清楚地说明了 SQL Server,而不是 MySQL。而且您当然不会想要这样一张只有经纬度的表格。
      • 同意 - 不好的答案。使用新的 GEOGRAPHY 空间类型。
      • 由于精度问题,我不会使用浮点数。使用小数(9,6)。
      • 存在latlng 优于georgraphy 的实际情况,即使在SQL 2014 中使用高密度索引也是如此。例如:find all point is with a rectangle。只是我不确定,我看到 Google 地图现在使用 7 位而不是 6 位?
      【解决方案4】:

      我这样做的方式:我存储 latitudelongitude,然后我有第三列,它是第一列的自动派生地理类型。该表如下所示:

      CREATE TABLE [dbo].[Geopoint]
      (
          [GeopointId] BIGINT NOT NULL PRIMARY KEY IDENTITY, 
          [Latitude] float NOT NULL, 
          [Longitude] float NOT NULL, 
          [ts] ROWVERSION NOT NULL, 
          [GeographyPoint]  AS ([geography]::STGeomFromText(((('POINT('+CONVERT([varchar](20),[Longitude]))+' ')+CONVERT([varchar](20),[Latitude]))+')',(4326))) 
      )
      

      这使您可以灵活地对 geoPoint 列进行空间查询,并且您还可以根据需要检索纬度和经度值,以用于显示或提取以用于 csv 目的。

      【讨论】:

      • 非常适合我正在寻找的东西,你有任何关于曲目/线条的东西
      • 另一种可行的方法,根据您的情况,存储经纬度,然后在运行时动态创建地理对象。
      • 好主意,但请注意,如果这是某人的意图,您不能在计算列上创建空间索引。
      • @hvaughan3 我认为如果你将它设为 persisted 计算列,你可以做到。
      • 谢谢+1,您的回答帮助了我。但我认为使用Point 而不是STGeomFromText 会更好。例如:[geography]::Point([Latitude], [Longitude], 4326).
      【解决方案5】:

      我讨厌与那些说“这是一种新类型,让我们使用它”的人相反。新的 SQL Server 2008 空间类型有一些优点 - 即效率,但是您不能盲目地说总是使用该类型。这实际上取决于一些更大的问题。

      例如,集成。这种类型在 .Net 中有一个等价的类型——但是互操作呢?支持或扩展旧版本的 .Net 怎么样?将这种跨服务层的类型暴露给其他平台怎么样?数据的规范化怎么样 - 也许您对 lat 或 long 作为独立的信息片段感兴趣。也许您已经编写了复杂的业务逻辑来处理 long/lat。

      我并不是说您不应该使用空间类型 - 在许多情况下您应该使用。我只是说你应该在走这条路之前问一些更关键的问题。为了最准确地回答您的问题,我需要更多地了解您的具体情况。

      单独存储 long/lat 或以空间类型存储都是可行的解决方案,根据您自己的情况,一种可能比另一种更可取。

      【讨论】:

      • 至少从 2000 年代开始,GIS 和空间数据处理就有了悠久的历史和标准的文本、二进制表示。如果你使用空间类型和标准表示,你最终会遇到你提到的所有问题
      【解决方案6】:

      您要做的是将纬度和经度存储为新的 SQL2008 空间类型 -> GEOGRAPHY。

      这是一张桌子的屏幕截图,我有。

      alt text http://img20.imageshack.us/img20/6839/zipcodetable.png

      在这个表中,我们有两个存储地理数据的字段。

      • 边界:这是作为邮政编码边界的多边形
      • CentrePoint:这是表示该多边形视觉中点的纬度/经度点。

      您想要将其作为 GEOGRAPHY 类型保存到数据库的主要原因是,您可以利用所有 SPATIAL 方法关闭它 -> 例如。多边形中的点、两点之间的距离等。

      顺便说一句,我们还使用 Google 的 Maps API 来检索经纬度数据并将其存储在我们的 Sql 2008 DB 中——所以这种方法确实有效。

      【讨论】:

      • 如果您还没有使用 2008,或者您使用 SQLCE 怎么办?后者不支持 GEOGRAPHY 类型...
      • 如果 SqlCE 或 一些问题的可能解决方案。 (用于 sql 空间的 nuget .. 获取该 dll)。
      • urgh :( 什么都不感谢 imageshack。我已经好几年没用 IS 了 :(imgur.com 一路!
      • -1,没有图像,这个答案是不完整的。请考虑将其替换为新图像或文本表格描述,或删除此答案。
      【解决方案7】:

      SQL Server 支持空间相关信息。您可以在http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx 看到更多信息。

      或者,您可以将信息存储为两个基本字段,通常浮点数是大多数设备报告的标准数据类型,并且在 1 英寸或 2 英寸范围内足够准确 - 对于 Google 地图来说已经足够了。

      【讨论】:

        【解决方案8】:

        注意:这是基于最近的 SQL 服务器、.NET 堆栈更新的最新答案

        谷歌地图中的纬度和经度应在地理数据类型下存储为 SQL 服务器中的点(注意大写 P)数据。

        假设您当前的数据以 varchar 形式存储在表 Sample 中,列在 latlon 下,下面的查询将帮助您转换为地理

        alter table Sample add latlong geography
        go
        update Sample set latlong= geography::Point(lat,lon,4326)
        go
        

        PS:下次当您使用地理数据在此表上进行选择时,除了“结果”和“消息”选项卡外,您还将获得如下所示的“空间结果”选项卡以进行可视化

        【讨论】:

          【解决方案9】:

          如果您使用的是 Entity Framework 5 DbGeography。来自 MSDN 的示例:

          public class University  
          { 
              public int UniversityID { get; set; } 
              public string Name { get; set; } 
              public DbGeography Location { get; set; } 
          }
          
          public partial class UniversityContext : DbContext 
          { 
              public DbSet<University> Universities { get; set; } 
          }
          
          using (var context = new UniversityContext ()) 
          { 
              context.Universities.Add(new University() 
                  { 
                      Name = "Graphic Design Institute", 
                      Location = DbGeography.FromText("POINT(-122.336106 47.605049)"), 
                  }); 
          
              context. Universities.Add(new University() 
                  { 
                      Name = "School of Fine Art", 
                      Location = DbGeography.FromText("POINT(-122.335197 47.646711)"), 
                  }); 
          
              context.SaveChanges(); 
          
              var myLocation = DbGeography.FromText("POINT(-122.296623 47.640405)"); 
          
              var university = (from u in context.Universities 
                                  orderby u.Location.Distance(myLocation) 
                                  select u).FirstOrDefault(); 
          
              Console.WriteLine( 
                  "The closest University to you is: {0}.", 
                  university.Name); 
          }
          

          https://msdn.microsoft.com/en-us/library/hh859721(v=vs.113).aspx

          我开始使用DbGeography 时遇到的问题是coordinateSystemId。有关以下代码的出色解释和来源,请参阅下面的答案。

          public class GeoHelper
          {
              public const int SridGoogleMaps = 4326;
              public const int SridCustomMap = 3857;
          
              public static DbGeography FromLatLng(double lat, double lng)
              {
                  return DbGeography.PointFromText(
                      "POINT("
                      + lng.ToString() + " "
                      + lat.ToString() + ")",
                      SridGoogleMaps);
              }
          }
          

          https://stackoverflow.com/a/25563269/3850405

          【讨论】:

            【解决方案10】:

            如果您只是要将它替换为一个 URL,我想一个字段会这样做 - 这样您就可以形成一个类似的 URL

            http://maps.google.co.uk/maps?q=12.345678,12.345678&z=6
            

            但由于它是两条数据,我会将它们存储在单独的字段中

            【讨论】:

            • 这是我的情况。我只需要将坐标存储在一个字段中并用逗号分隔。我认为可以使用 TEXT 作为字段类型。你怎么看?
            【解决方案11】:

            将两者都存储为浮点数,并在它们上使用唯一的关键字。i.em

            create table coordinates(
            coord_uid counter primary key,
            latitude float,
            longitude float,
            constraint la_long unique(latitude, longitude)
            );
            

            【讨论】:

            • 确保只有一组唯一的经纬度对。您不想在表中存储坐标 {0,0} 两次,不是吗?
            • 您可能根本不希望有这样一个单独的坐标表,尤其是在唯一性约束下,处理两个位置指向同一点的情况是维护的噩梦,更不用说清洁了向上未引用的行。
            • > 您可能根本不希望有这样一个单独的坐标表 - 一点也不?绝不?您将如何将其存储在 1 个字段中?数百万人不使用 SQL 2008 Spatial 类型呢?
            • 有这样的限制是一个糟糕的决定。假设 Bob 住在 House A,并将搬到 House B,即 Alice 曾经居住的房子。很快 Bob 将无法保存他的地址(位置),因为 Alice 还没有更新她的地址(或者永远不会更新)。
            • @Sally - 他不是这么说的。阅读他的评论。他说没有理由将一对值存储在单独的中。只需将 lat/long 放在原始表上,并节省第二个表和所有 JOINS 的开销。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-18
            • 2011-08-01
            • 2018-02-17
            • 2012-02-18
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多