SSMS и sp_OAMethod: существует ли тип данных больше, чем VARCHAR (8000)? - PullRequest
0 голосов
/ 01 октября 2018

Вызов службы REST через SSMS - действительно не лучшая идея.

Кстати, с тех пор как Microsoft создала хранимую процедуру sp_OAMethod и даже Фил Фактор из Red Gate показывает нам, как ее использовать Я хотел попробовать.

Я хотел импортировать некоторые данные из OpenStreetMap непосредственно в MSSQL, поэтому я скопировал хороший запрос отсюда и адаптировал его к своему желанию.

В этом примере я возвращаю все кинотеатры в Нельсон :

DECLARE @obj AS INT
DECLARE @Uri AS NVARCHAR(4000)
DECLARE @Response AS VARCHAR(8000)

SET @Uri = 'http://overpass-api.de/api/interpreter?data=area[name="Nelson"]->.a;(node(area.a)[amenity=cinema];way(area.a)[amenity=cinema];rel(area.a)[amenity=cinema];);out;'
EXEC sp_OACreate 'MSXML2.ServerXMLHttp.3.0', @obj OUT
EXEC sp_OAMethod @obj, 'open', NULL, 'GET', @Uri, false
EXEC sp_OAMethod @obj, 'send'
EXEC sp_OAGetProperty @obj, 'ResponseText', @Response OUTPUT

SELECT @Response [response] 
EXEC sp_OADestroy @obj

Легко и просто, я вижу ответ на вызов REST в Почтальоне, а также вSSMS:

enter image description here

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

DECLARE @obj AS INT
DECLARE @Uri AS NVARCHAR(4000)
DECLARE @Response AS VARCHAR(8000)

SET @Uri = 'http://overpass-api.de/api/interpreter?data=area[name="Auckland"]->.a;(node(area.a)[amenity=cinema];way(area.a)[amenity=cinema];rel(area.a)[amenity=cinema];);out;'
EXEC sp_OACreate 'MSXML2.ServerXMLHttp.3.0', @obj OUT
EXEC sp_OAMethod @obj, 'open', NULL, 'GET', @Uri, false
EXEC sp_OAMethod @obj, 'send'
EXEC sp_OAGetProperty @obj, 'ResponseText', @Response OUTPUT

SELECT @Response [response] 
EXEC sp_OADestroy @obj

Вызов REST извлекает дополнительные данные, и переменная @Response AS VARCHAR(8000) не может содержать все данные:

enter image description here

Конечно, я пытался использоватьDECLARE @Response AS VARCHAR(MAX) но это тоже не поможет.

Разве VARCHAR(MAX) не должны содержать 65 535 символов и до 2ГБ данных?

Что я должен использовать вместо этого?

Есть ли способ разделить данные и объединить позже?

РЕДАКТИРОВАТЬ: Я думаю, что я все ближе: я могу использовать OPENJSON таким образом , но я все еще не знаю, как структурировать запрос ...любая помощь будет оценена

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

Я хлопаю в ладоши.

Признаюсь, это кошмарное решение, но оно добивается цели.Решением было установить:

Declare @Response as table(Json_Table nvarchar(max))

Таким образом, я создал таблицу с типом данных, который имеет nvarchar(max) и теперь да, он может содержать 65 535 символов и до 2 ГБ данных.

Declare @Object as Int;
DECLARE @hr  int
Declare @Response as table(Json_Table nvarchar(max))

Exec @hr=sp_OACreate 'MSXML2.ServerXMLHTTP.6.0', @Object OUT;
Exec @hr=sp_OAMethod @Object, 'open', NULL, 'get',
                 'http://overpass-api.de/api/interpreter?data=[out:json];area[name="Auckland"]->.a;(node(area.a)[amenity=cinema];way(area.a)[amenity=cinema];rel(area.a)[amenity=cinema];);out;', --Your Web Service Url (invoked)
                 'false'
Exec @hr=sp_OAMethod @Object, 'send'
Exec @hr=sp_OAMethod @Object, 'responseText', @Response OUTPUT

INSERT into @Response (Json_Table) exec sp_OAGetProperty @Object, 'responseText'

select * from @Response

EXEC sp_OADestroy @Object

Пожалуйста, напишите, если вы найдете лучшее решение, оно будет высоко ценится.

0 голосов
/ 03 октября 2018

Неверный код:

DECLARE @str varchar(max)
SET @str = REPLICATE('A', 4000) + REPLICATE('B', 4000) + REPLICATE('C', 4000)
PRINT LEN(@str)

С REPLICATE в SQL Server документы

Если выражение string_expression не относится к типу varchar (max) или nvarchar (max)), REPLICATE усекает возвращаемое значение до 8000 байт.Чтобы вернуть значения, превышающие 8000 байт, выражение string_expression должно быть явно приведено к соответствующему типу данных большого значения.

Правильный код:

DECLARE @str varchar(max)
DECLARE @seed varchar(max) = 'A'

SET @str = REPLICATE(@seed, 4000) + REPLICATE(@seed, 4000) + REPLICATE(@seed, 4000)
PRINT LEN(@str)

--12000

Другие ответы см. Для Nvarchar (Max) я получаю только 4000 символов в TSQL?

...