¿Cómo convertir de BLOB de geometría de SQL Server a otra cosa?


14

Tengo un archivo de datos CSV de un tercero que es una tabla de SQL Server exportada. Simplemente hicieron select * from fooy enviaron el resultado a un archivo de texto y lo enviaron.

En su tabla hay una columna de tipo Geometry, así que en mi texto sin formato tengo algo como "0xE610000010C47 ...", etc. En este momento lo he cargado en una tabla en SQL Server como un nvarchar.

Anticipé que podría volver a un campo de Geometría en mi extremo, pero eso no parece ser tan fácil. STGeomFromWKBno funciona porque en realidad no es un WKB. No puedo convertir la cadena como Geometría porque se queja de que no es un WKT.

Entonces, ¿hay alguna forma de obtener este valor en SQL Server como si fuera un BLOB de Geometría normal? ¿Puedo decirle a SQL Server que lo trate como tal?

Encontré este enlace que al menos me ayudó a responder mi pregunta sobre lo que hay en SQL Server, pero no me llegó hasta allí: ¿cuál es el formato del tipo de datos Geometry de SQLServer 2008?


Parece que WKB (Well Known Binary) hay una descripción de Esri edndoc.esri.com/arcsde/9.1/general_topics/… pero el formato es OGC (Open Geospatial Consortium). Creo que sería un poco más fácil usar el incorporado funciona como se describe en el enlace proporcionado o en uno de los listados msdn.microsoft.com/en-AU/library/bb933960.aspx. Creo que el problema radica en que ha importado una cadena hexadecimal como texto y no realmente como binario, pero puedo No ayudo allí. No he tenido mucho que ver con el backend de SQL. Tal vez podría preguntar sobre Superusuario o Administrador de base de datos en stackexchange.
Michael Stimson

@ Peter ¿Alguna vez encontraste alguna de estas soluciones para tu problema?
DPSSpatial

Respuestas:


9

Cuando importe los datos a SQL Server, colóquelos en una columna VARBINARIA (MAX). A continuación, debe poder CASTAR esto como Geometría o Geografía según sea necesario. Deberá tener cuidado de que la cadena 0xE6 ... no se cambie durante la importación.

Otra opción es hacer una consulta dinámica para obtener la selección. Pongo un par de ejemplos de conversión a continuación.

-- As a varchar and binary
DECLARE @NV AS NVARCHAR(MAX) = '0xE610000001040E0000002AA57BA76F5446C027B8FD971024654007517714795446C00C42473D1624654094CFCDE3795446C0D3F576B91624654068507E9C7A5446C0D7BE805E18246540F2FC444A7C5446C0E93DDF6019246540B4CA4C697D5446C0D5DF5C0D1A2465401A0923AC7C5446C08183DE3F1A2465407599E1907B5446C0E2A8818B1A24654058B4805A7A5446C0A70261DE1A24654089729F5C775446C072080BDD1B2465401AAC24A8745446C057CB10FE1C2465403D16A5446E5446C05A20FEE21A246540658BA4DD685446C00907FFA3172465402AA57BA76F5446C027B8FD971024654001000000020000000001000000FFFFFFFF0000000003' 
DECLARE @NB AS VARBINARY(MAX) = 0xE610000001040E0000002AA57BA76F5446C027B8FD971024654007517714795446C00C42473D1624654094CFCDE3795446C0D3F576B91624654068507E9C7A5446C0D7BE805E18246540F2FC444A7C5446C0E93DDF6019246540B4CA4C697D5446C0D5DF5C0D1A2465401A0923AC7C5446C08183DE3F1A2465407599E1907B5446C0E2A8818B1A24654058B4805A7A5446C0A70261DE1A24654089729F5C775446C072080BDD1B2465401AAC24A8745446C057CB10FE1C2465403D16A5446E5446C05A20FEE21A246540658BA4DD685446C00907FFA3172465402AA57BA76F5446C027B8FD971024654001000000020000000001000000FFFFFFFF0000000003

-- Failing conversions
SELECT CAST(@NV AS Geometry)
SELECT CAST(CAST(@NV AS VARBINARY(MAX)) AS Geometry)
-- Correct conversion
SELECT CAST(@NB AS Geometry)
EXEC('SELECT CAST(' + @NV + ' AS Geometry)')

6

Basándose en la respuesta de @ MickyT, dado que va a tener una tabla con sus valores ya en WKB (o como sea que la llamemos), querrá escribir sql que convierta todos los registros a geometría, en lugar de tener que declarar una variable, etc. etc.

Entonces, si comienza con una tabla temporal simple que replicaría el WKB en un registro, se vería así:

select 0x3D0B0000010C80BAE380AE064841005149CD6EFD3941 as wkb

Ahora, si trata eso como una tabla temporal y ajusta un poco de SQL a su alrededor, tiene una columna con el WKB allí y puede convertirlo a varbinary como se sugirió anteriormente:

select 
cast(temp.wkb as varbinary(max)) as geombinary
from 
(
select 0x3D0B0000010C80BAE380AE064841005149CD6EFD3941 as wkb
) as temp

donde temp.wkb puede ser la columna en su tabla más grande que contiene los valores WKB del CSV

Finalmente, use el método descrito por MickyT y convierta el varbinary a geometry:

select 
cast(geomconvert.geombinary as geometry) as geom
 from (
select 
cast(temp.wkb as varbinary(max)) as geombinary
from 
(
select 0x3D0B0000010C80BAE380AE064841005149CD6EFD3941 as wkb
) as temp
) as geomconvert

Que devuelve geometría y un resultado espacial:

ingrese la descripción de la imagen aquí

EDITAR ¿ dónde se declara el SRID? Como respondió MickyT, está en el binario, y puede ajustar 1 consulta sql más por allí para probar:

select top 1 getsrid.geom.STSrid from (

select 
cast(geomconvert.geombinary as geometry) as geom
 from (
select 
cast(temp.wkb as varbinary(max)) as geombinary
from 
(
select 0x3D0B0000010C80BAE380AE064841005149CD6EFD3941 as wkb
) as temp
) as geomconvert

) as getsrid

que produce, y es correcto en mi ejemplo, 2877 (plano del estado de Colorado):

ingrese la descripción de la imagen aquí


1
El SRID está integrado en el binario Geometry. El binario que se proporciona no es WKB, sino la representación binaria real de SQL Servery de Geometry.
MickyT

@MickyT ¡ah sí! Publicaré un fragmento más para probar ... ¡Gracias!
DPSSpatial

¿Sería posible agregar una columna de Geometría a la tabla original y actualizar esa columna con la Geometría?
Peter Horsbøll Møller

1
@ PeterHorsbøllMøller Creo que ese es el movimiento correcto ... una vez que se convierte. Trabajaré en eso y publicaré más adelante.
DPSSpatial

3

El póster original aquí, cuando intenté finalizar el registro, no vinculaba el inicio de sesión para la publicación original. De todas formas....

¡Gracias por toda la ayuda! Votaré cada respuesta una vez que pueda y tal vez si puedo descubrir cómo vincular esta cuenta y la original, puedo marcar una respuesta. Además, después de sus punteros, no puedo creer que me perdí el uso en CONVERTlugar de CAST. Lo hace mucho más fácil.

Creo que mi principal problema era conseguir que la "cadena" binaria en bruto se convirtiera en algo que pudiera usar. Aquí hay una muestra de cómo lo resolví:

DECLARE @data TABLE (
  ID nvarchar(1024),
  ImportedGeometry nvarchar(max),
  FinalGeometry geometry
  )

  INSERT INTO @data (ID, ImportedGeometry) values ('1', '0xE6100000010C4703780B24B855C061C3D32B65093540')
  INSERT INTO @data (ID, ImportedGeometry) values ('2', '0xE6100000010C96438B6CE7D359C0BD5296218E853440')

select 
d.ID,
d.ImportedGeometry,
CONVERT(varbinary(max), d.ImportedGeometry, 1) as ConvertedGeometryBin,
(cast(CONVERT(varbinary(max), d.ImportedGeometry, 1) as geometry)) as FinalGeometry
from @data d

UPDATE @data
SET FinalGeometry = (cast(CONVERT(varbinary(max), ImportedGeometry, 1) as geometry))

select 
d.ID,
d.FinalGeometry,
d.FinalGeometry.STAsText(),
d.FinalGeometry.STSrid
from @data d

¡¡¡se ve bien!!! Es bueno tener todo esto documentado ... ¡será útil algún día!
DPSSpatial

esto fue útil: un compañero en nuestro departamento de BI encontró esta publicación de forma independiente y la usó para que SQL Server Integration Services (SSIS) pasara la geometría de un lado a otro entre servidores, lo que en este momento no se encuentra de forma nativa en SSIS. !
DPSSpatial
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.