web-dev-qa-db-fra.com

Quel est le meilleur moyen de stocker des coordonnées (longitude/latitude, à partir de Google Maps) dans SQL Server?

Je conçois une table dans SQL Server 2008 qui stockera une liste d'utilisateurs et une coordonnée Google Maps (longitude et latitude).

Aurai-je besoin de deux champs ou est-ce possible avec 1?

Quel type de données est le meilleur (ou le plus courant) à utiliser pour stocker ce type de données?

98
Jonathan

Jetez un coup d'œil aux nouveaux types de données Spatial introduits dans SQL Server 2008. Ils sont conçus pour ce type de tâche et facilitent et optimisent l'indexation et les requêtes.

Plus d'information:

52
Craig Bovis

Avertissement juste! Avant de suivre le conseil d'utiliser le type GEOGRAPHY, assurez-vous de ne pas utiliser Linq ou Entity Framework pour accéder aux données, car elles ne sont pas prises en charge (en novembre 2010) et vous serez triste! 

Mise à jour juil 2017  

Pour ceux qui lisent cette réponse maintenant, elle est obsolète, car elle fait référence à une pile technologique rétroactive. Voir les commentaires pour plus de détails.

61
dan90266

_ {Je ne connais pas la réponse pour SQL Server mais ...} _

Dans MySQL, enregistrez-le sous le nom FLOAT( 10, 6 )

C’est la recommandation officielle de la documentation pour les développeurs Google .

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

Je déteste être à l’opposé de ceux qui ont dit "voici un nouveau type, utilisons-le". Les nouveaux types spatiaux SQL Server 2008 ont quelques avantages: l'efficacité, mais vous ne pouvez pas dire aveuglément que vous utilisez toujours ce type. Cela dépend vraiment de certains problèmes plus généraux.

À titre d'exemple, l'intégration. Ce type a un type équivalent dans .Net - mais qu’en est-il de l’interopérabilité? Qu'en est-il de soutenir ou d'étendre les anciennes versions de .Net? Pourquoi ne pas exposer ce type de la couche de service à d’autres plateformes? Qu'en est-il de la normalisation des données? Peut-être êtes-vous intéressé par une information autonome ou longue. Vous avez peut-être déjà écrit une logique métier complexe pour gérer long/lat.

Je ne dis pas que vous ne devriez pas utiliser le type spatial - dans de nombreux cas, vous devriez. Je dis simplement que vous devriez poser des questions plus critiques avant de s'engager dans cette voie. Pour que je puisse répondre à votre question avec plus de précision, il me faudrait en savoir plus sur votre situation particulière.

Stocker long/lat séparément ou dans un type spatial est une solution viable, et l’une peut être préférable à l’autre en fonction de votre situation.

21
R. Lawson

La façon dont je le fais: je stocke la latitude et la longitude et puis j'ai une troisième colonne qui est un type de géographie dérivé automatique des deux premières colonnes. Le tableau ressemble à ceci:

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

Cela vous donne la flexibilité des requêtes spatiales sur la colonne geoPoint et vous pouvez également récupérer les valeurs de latitude et de longitude selon vos besoins pour l'affichage ou l'extraction à des fins de csv.

17
jaxxbo

Ce que vous voulez faire est de stocker la latitude et la longitude dans le nouveau type spatial SQL2008 -> GEOGRAPHIE.

Voici une capture d'écran d'un tableau, que j'ai.

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

Dans ce tableau, nous avons deux champs qui stockent des données géographiques.

  • Limite: c'est le polygone qui est la limite du code postal
  • CentrePoint: c'est le point de latitude/longitude qui représente le point central visuel de ce polygone.

La raison principale pour laquelle vous voulez l'enregistrer dans la base de données en tant que type GEOGRAPHY est que vous pouvez ensuite utiliser toutes les méthodes SPATIAL pour l'utiliser -> par exemple. Point en Poly, Distance entre deux points, etc.

BTW, nous utilisons également l’API Google Maps pour récupérer des données lat/long et les stocker dans notre base de données SQL 2008 - pour que cette méthode fonctionne.

15
Pure.Krome

SQL Server prend en charge les informations relatives à l'espace. Vous pouvez en voir plus sur http://www.Microsoft.com/sqlserver/2008/en/us/spatial-data.aspx

Alternativement, vous pouvez stocker les informations dans deux champs de base. Généralement, un type flottant est le type de données standard indiqué par la plupart des périphériques. 

11
Rosstified

NOTE: réponse récente basée sur un serveur SQL récent, mises à jour de la pile .NET

latitute et longitude de Google Maps doivent être stockés sous forme de données de points (note capitale P) dans le serveur SQL sous le type de données geography.

En supposant que vos données actuelles soient stockées dans une table Sample en tant que varchar sous les colonnes lat et lon, la requête ci-dessous vous aidera à convertir en données géographiques.

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

PS: La prochaine fois que vous effectuerez une sélection dans ce tableau avec des données géographiques, en plus de l'onglet Résultats et messages, vous obtiendrez également un onglet Résultats spatiaux, comme ci-dessous, pour la visualisation.

 SSMS geo results tab

1
DhruvJoshi

Si vous utilisez Entity Framework 5 <, vous pouvez utiliser DbGeography. Exemple de 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

Quelque chose avec lequel j'ai eu du mal à ensuite utiliser DbGeography était le coordinateSystemId. Voir la réponse ci-dessous pour une excellente explication et une source pour le code ci-dessous.

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

0
Ogglas