Как преобразовать BLOB-объект SQL Server в геометрию другого объекта?

14

У меня есть файл данных CSV от стороннего производителя, который является экспортированной таблицей SQL Server. Они просто сделали select * from fooи вывели результат в текстовый файл и отправили его.

В их таблице есть столбец типа Geometry, поэтому в моем исходном тексте у меня есть что-то вроде «0xE610000010C47 ...» и т. Д. На данный момент я загрузил его в таблицу в SQL Server как nvarchar.

Я ожидал, что смогу вернуться обратно в поле Geometry с моей стороны, но это не так просто. STGeomFromWKBне работает, потому что это на самом деле не WKB. Я не могу привести строку как Geometry, потому что она жалуется, что это не WKT.

Итак, есть ли способ получить это значение в SQL Server, как если бы это был обычный BLOB-объект Geometry? Могу ли я сказать, чтобы SQL Server рассматривал его как таковой?

Я нашел эту ссылку, которая, по крайней мере, помогла мне ответить на мой вопрос о том, что находится в SQL Server, но не дошла до конца : каков формат данных Geometry в SQLServer 2008

Питер
источник
Похоже, WKB (хорошо известный двоичный файл ) есть описание Esri edndoc.esri.com/arcsde/9.1/general_topics/… но формат OGC (Open Geospatial Consortium) функции, как описано в приведенной ссылке или в списке msdn.microsoft.com/en-AU/library/bb933960.aspx Я думаю, что проблема заключается в том, что вы импортировали шестнадцатеричную строку как текст, а не как двоичный файл - но я могу Мне там не очень помогали, я не имел ничего общего с бэкэндом SQL. Возможно, вы могли бы спросить у суперпользователя или администратора БД о stackexchange.
Майкл Стимсон
@ Питер, вы когда-нибудь находили какое-либо из этих решений для вашей проблемы?
DPSSpatial

Ответы:

9

Когда вы импортируете данные в SQL Server, поместите их в столбец VARBINARY (MAX). Затем вы должны быть в состоянии CAST это как геометрия или география, как требуется. Вам нужно быть осторожным, чтобы строка 0xE6 ... не изменялась во время импорта.

Другой вариант - выполнить динамический запрос, чтобы получить выбор. Я положил пару примеров преобразования ниже.

-- 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)')
MickyT
источник
6

Основываясь на ответе @ MickyT, так как у вас будет таблица со значениями, уже находящимися в WKB (или как мы ее называем), вы захотите написать sql, который преобразует все записи в геометрию, а не объявить переменную и т. д.

Поэтому, если вы начнете с простой временной таблицы, которая будет дублировать WKB в одной записи, это будет выглядеть так:

select 0x3D0B0000010C80BAE380AE064841005149CD6EFD3941 as wkb

Теперь, если вы рассматриваете это как временную таблицу и оборачиваете вокруг нее некоторый SQL, у вас есть столбец с WKB, и вы можете преобразовать его в varbinary, как предложено выше:

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

где temp.wkb может быть столбцом в вашей большой таблице, содержащим значения WKB из CSV

Наконец, используйте метод, описанный MickyT, и конвертируйте varbinary в геометрию:

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

Который возвращает геометрию и пространственный результат:

введите описание изображения здесь

РЕДАКТИРОВАТЬ, где SRID объявляется? Как ответил MickyT, он находится в двоичном файле, и вы можете проверить еще 1 sql-запрос, чтобы проверить:

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

который дает, и правильно в моем примере, 2877 (штат Колорадо):

введите описание изображения здесь

DPSSpatial
источник
1
SRID встроен в двоичный файл Geometry. Предоставляется двоичный файл не WKB, а фактическое двоичное представление геометрии SQL Servery.
MickyT
@ MickyT ах да! Я опубликую еще один фрагмент для проверки ... Спасибо !!!
DPSSpatial
Можно ли добавить столбец Geometry в исходную таблицу и обновить этот столбец с помощью Geometry?
Питер Хорсбёлл Мёллер
1
@ PeterHorsbøllMøller Я думаю, что это правильный ход ... как только он будет преобразован. Я буду работать над этим и отправлю позже.
DPSSpatial
3

Оригинальный постер, когда я пытался завершить регистрацию, он не связывал подпись с оригинальным постом. Так или иначе....

Спасибо за помощь! Я буду одобрять каждый ответ, как только смогу, и, возможно, если я смогу выяснить, как связать этот аккаунт с оригиналом, я смогу пометить ответ. Кроме того, после ваших указателей я не могу поверить, что я пропустил использование CONVERTвместо CAST. Это делает это намного проще.

Я думаю, что моей главной проблемой было получение необработанной двоичной «строки», которую я мог бы использовать. Вот пример того, как я решил это:

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
user57679
источник
выглядит неплохо!!! Хорошо, что все это задокументировано ... это пригодится однажды!
DPSSpatial
это пригодилось - сотрудник нашего отдела BI независимо нашел этот пост и использовал его, чтобы заставить SQL Server Integration Services (SSIS) передавать геометрию между серверами, которая на данный момент отсутствует в SSIS !! !
DPSSpatial