API Request from SQL Server unable to use OPENJSON - sql

I'm having an issue with certain JSON responses every time I make a GET call to MercadoLibre API. So far what I have found is that when response is too large, I get a null value, but i was able to solve it. This is my code:
SET TEXTSIZE 2147483647
DECLARE #url VARCHAR(8000) = 'https://api.mercadolibre.com/products/MLA18648076'
DECLARE #token as int;
DECLARE #respuesta as VARCHAR(8000);
DECLARE #ret INT;
DECLARE #respuesTabla table(respuestaTxt nvarchar(max))
EXEC sp_OACreate 'MSXML2.XMLHTTP', #token OUT;
IF #ret <> 0 RAISERROR('Unable to open HTTP connection.', 10, 1);
EXEC #ret = sp_OAMethod #token, 'open', NULL, 'GET', #url, 'false';
EXEC #ret = sp_OAMethod #token, 'send'
insert into #respuesTabla (respuestaTxt)
EXEC #ret = sp_OAMethod #token, 'responseText'
select #respuesta = respuestaTxt from #respuesTabla
select #respuesta
EXEC sp_OADestroy #token
Now, response looks ok but if i try to open with OPENJSON i get the error that Json format isnt ok.
BUT,if i download the response to txt and use OPENROWSET i actually can read the json file. So...what's the problem?

Change DECLARE #respuesta as VARCHAR(8000) to
DECLARE #respuesta as NVARCHAR(MAX)
But yes, don't use SQL Server for this. You can create simple java or python or even powershell script that calls some URL and fetches products

Related

Writing nvarchar to a text file

I have a problem with writing in a text file. Everything works fine when my text is ASCII:
DECLARE #OLE INT
DECLARE #FileId INT
DECLARE #File VARCHAR(max) = 'D:\test.txt'
DECLARE #Text NVARCHAR(max) = N'no problem when writing in english!'
EXECUTE sp_OACreate 'Scripting.FileSystemObject',#OLE OUT
EXECUTE sp_OAMethod #OLE, 'OpenTextFile', #FileId OUT, #File,2,1
EXECUTE sp_OAMethod #FileId, 'WriteLine', Null, #Text
But nothing will be appeared in the file when my text has Unicode characters:
DECLARE #Text NVARCHAR(max) = N'من نمایش داده نمیشم'
I also tried sp_OASetProperty but that did not work (mentioned here):
EXECUTE sp_OASetProperty #OLE, 'Charset', 'UTF-8'
Any idea to fix this or using other T-SQL procedures?
According to the Scripting.FileSystemObject documentation, the CreateTextFile method takes a Boolean value to create a Unicode file. You could change the T-SQL code to use that method instead of OpenTextFile.
EDIT:
Below is an example using OpenTextFile per Tom's comment. I change the iomode value in your original code from 1 to 8 to match the documentation and added the close and destroy in case your full code is missing those important tasks.
DECLARE #OLE INT;
DECLARE #FileId INT;
DECLARE #File VARCHAR(max) = 'c:\test.txt';
DECLARE #Text NVARCHAR(max) = N'من نمایش داده نمیشم';
EXECUTE sp_OACreate 'Scripting.FileSystemObject',#OLE OUT;
EXECUTE sp_OAMethod #OLE, 'OpenTextFile', #FileId OUT, #File,8,1,-1;
EXECUTE sp_OAMethod #FileId, 'WriteLine', Null, #Text;
EXECUTE sp_OAMethod #FileId, 'Close';
EXECUTE sp_OADestroy #FileId OUT;
EXECUTE sp_OADestroy #OLE OUT;
EXECUTE #HR = sp_OACreate 'ADODB.Stream', #OLE OUTPUT
EXECUTE sp_OASetProperty #OLE, 'Type', 2
EXECUTE sp_OASetProperty #OLE, 'Mode', 3
EXECUTE sp_OASetProperty #OLE, 'Charset', 'Windows-1256'
EXECUTE sp_OASetProperty #OLE, 'LineSeparator', 'adLF'
EXECUTE sp_OAMethod #OLE, 'Open'
EXECUTE sp_OAMethod #OLE, 'WriteText', NULL, #String
--Commit data and close text stream
EXECUTE sp_OAMethod #OLE,'SaveToFile', NULL, #FileAndPath, 2
EXECUTE sp_OAMethod #OLE, 'Close'
EXECUTE sp_OADestroy #OLE

SQL - Create XML - How to set Unicode UTF-8

I have a problem with creating an XML file from inside a SQL PROCEDURE.
The XMLs get created and placed in the correct folder. Although when I open the file in XMLSpy, it says the following error:
Your file contains 3 character(s) that should not be present in a file using the Unicode UTF-8 encoding...
The offending characters are è (0xE8), ü (0xFC), é (0xE9)
When I open the XML file in Notepad++ and check for encoding (via menu Encoding on top), it says it is in ANSI and not in UTF-8.
So my question is: How do I get it to turn into UTF-8? Any suggestions?
The code of my procedure can be found below:
#File VARCHAR(2000) // parameter
AS
BEGIN
DECLARE #OLE INT
DECLARE #FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', #OLE OUT
EXECUTE sp_OAMethod #OLE, 'OpenTextFile', #FileID OUT, #File, 8, 1
DECLARE #Text XML
SET #Text = (SELECT TOP(1) [xml] from VW_WARP_LEVERANCIERS_XML)
EXECUTE sp_OAMethod #FileID, 'WriteLine', Null, #Text
EXECUTE sp_OADestroy #FileID
EXECUTE sp_OADestroy #OLE
END
EDIT 1
Changed my code, exporting to ASCII instead of Unicode (as suggested below by Wolf), but this didn't help too. But here is that part of code:
DECLARE #OLE INT
DECLARE #FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', #OLE OUT
EXECUTE sp_OAMethod #OLE, 'CreateTextFile', #FileID OUT, #File, 2, False
DECLARE #Text XML
SET #Text = (SELECT TOP(1) [xml] from VW_WARP_LEVERANCIERS_XML)
EXECUTE sp_OAMethod #FileID , 'Write', Null, #Text
EXECUTE sp_OAMethod #FileID , 'Close'
EXECUTE sp_OADestroy #FileID
EXECUTE sp_OADestroy #OLE
END
I found a solution via another way. (don't remember which website I found it)
See code below. This code will export my file in UTF-8-BOM encoding.
#File VARCHAR(2000)
AS
BEGIN
DECLARE #OLE INT
EXECUTE sp_OACreate 'ADODB.Stream', #OLE OUTPUT
DECLARE #Text XML
SET #Text = (SELECT TOP(1) [xml] from VW_WARP_LEVERANCIERS_XML)
DECLARE #Converted NVARCHAR(MAX)
SET #Converted = CONVERT(nvarchar(MAX), #Text)
EXECUTE sp_OASetProperty #OLE, 'Type', 2 --1 = binary, 2 = text
EXECUTE sp_OASetProperty #OLE, 'Mode', 3 --0 = not set, 1 read, 2 write, 3 read/write
EXECUTE sp_OASetProperty #OLE, 'Charset', 'UTF-8' --'ISO-8859-1'
EXECUTE sp_OASetProperty #OLE, 'LineSeparator', 'adLF'
EXECUTE sp_OAMethod #OLE, 'Open'
EXECUTE sp_OAMethod #OLE, 'WriteText', NULL, #Converted --text method
--Commit data and close text stream
EXECUTE sp_OAMethod #OLE, 'SaveToFile', NULL, #File, 2 --1 = notexist 2 = overwrite
EXECUTE sp_OAMethod #OLE, 'Close'
EXECUTE sp_OADestroy #OLE
EXECUTE sp_OADestroy #OLE
END
Generally, SQL Server does not support UTF-8 by itself. However, I'm not sure about FSO, maybe it does.
The OpenTextFile documentation states that you can determine the file format, i.e. ASCII or Unicode. Try:
EXECUTE sp_OAMethod #OLE, 'OpenTextFile', #FileID OUT, #File, 8, 0;
This should give you an ASCII file format.

rolling back exec and sp_OA methods

We have an instance where an old vb6 dll needs to be implemented and forces us to use sp_OACreate and sp_OAMethod. Given that the code will be inside a transaction, does anyone know whether or not the rollback will work for the code in that assembly? The assembly will access and make changes to the data.
Or will the sp_OAMethod call and the db code inside the assembly create it's own independent session outside of the transaction?
Thank you.
begin tran
declare #hr int
declare #Object int
declare #Return int
declare #Output varchar(255)
exec #hr= sp_OACreate 'DIssues32.Iclass',#object out
IF #hr <> 0
BEGIN
EXEC sp_Getoaerrorinfo #object, #hr,#output out
select #output
END
else
begin
exec #hr = sp_OAMethod #object,'Transfer', #Return , #LOCATION_NAME,
#TO_LOCATION_NAME, #QTY_REQUESTED, #SYSUSER_ID, '', #CONNSTRING, True, '', False, True
IF #hr <> 0
BEGIN
EXEC sp_Getoaerrorinfo #object, #hr,#output out
select #output
rollback
END
exec #hr= sp_OADestroy #object out
print #return
end
commit
You have to use sp_bindsession for the second connection (from VB6 component) to join the main lock space and share the transaction.
You can use sp_getbindtoken to get the token and pass it along the connection string but obviously the VB6 code will have to be tweaked to bind the session if token is found at the end of #CONNSTRING

How can I to read a XML from a URL using T-SQL?

Have xml file in url :
<response>
<sum>0</sum>
<result>0</result>
<comment>sel*1.9488|buy*1.9453</comment>
</response>
Now want stored procedure where i can parse this xml file from url and update into columns values which is in <comment>sel*1.9488|buy*1.9453</comment> want add buy*1.9453 to my table. How do it ?
To get the XML from a URL you need to do the following:
Enable Ole Automation Procedures
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
Then to get the XML from a url, (answer based on an updated version from here), the following creates a temp table to store the value so you can then process the results using an xpath and substring.
This is a working example using a google maps xml, you will need to update the url and xpath to your specific requirements.
USE tempdb
GO
IF OBJECT_ID('tempdb..#xml') IS NOT NULL DROP TABLE #xml
CREATE TABLE #xml ( yourXML XML )
GO
DECLARE #URL VARCHAR(8000)
DECLARE #QS varchar(50)
-- & or ? depending if there are other query strings
-- Use this for when there is other query strings:
SELECT #QS = '&date='+convert(varchar(25),getdate(),126)
-- Use this for when there is NO other query strings:
-- SELECT #QS = '?date='+convert(varchar(25),getdate(),126)
SELECT #URL = 'http://maps.google.com/maps/api/geocode/xml?latlng=10.247087,-65.598409&sensor=false' + #QS
DECLARE #Response varchar(8000)
DECLARE #XML xml
DECLARE #Obj int
DECLARE #Result int
DECLARE #HTTPStatus int
DECLARE #ErrorMsg varchar(MAX)
EXEC #Result = sp_OACreate 'MSXML2.XMLHttp', #Obj OUT
EXEC #Result = sp_OAMethod #Obj, 'open', NULL, 'GET', #URL, false
EXEC #Result = sp_OAMethod #Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
EXEC #Result = sp_OAMethod #Obj, send, NULL, ''
EXEC #Result = sp_OAGetProperty #Obj, 'status', #HTTPStatus OUT
INSERT #xml ( yourXML )
EXEC #Result = sp_OAGetProperty #Obj, 'responseXML.xml'--, #Response OUT
SELECT yourXML.value('(//GeocodeResponse/status)[1]','VARCHAR(MAX)') from #xml
In order to insert the substring you will need to do something like this to return everything after the pipe and add into your table:
INSERT tableDestination (valueDestination)
SELECT substring(yourXML.value('(//response/comment)[1]','VARCHAR(MAX)'),charindex('|',yourXML.value('(//response/comment)[1]','VARCHAR(MAX)'),1)+1,len(yourXML.value('(//response/comment)','VARCHAR(MAX)'))) from #xml
How about somethine like
DECLARE #xml XML =
'<response>
<sum>0</sum>
<result>0</result>
<comment>sel*1.9488|buy*1.9453</comment>
</response>'
SELECT #xml.value('(//response/comment)[1]','VARCHAR(MAX)')
From value() Method (xml Data Type)
Performs an XQuery against the XML and returns a value of SQL type.
This method returns a scalar value.
You typically use this method to extract a value from an XML instance
stored in an xml type column, parameter, or variable. In this way, you
can specify SELECT queries that combine or compare XML data with data
in non-XML columns.
SQL Fiddle DEMO

How to call webservice from TSQL? (SQL SERVER 2000)

I want to call a webservice from TSQL in SQL Server 2000. I tried with the following code:
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get','http://server/ws/service1.asmx/Test', 'false';
Exec sp_OAMethod #Object, 'send';
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT;
Select #ResponseText Resultado;
Exec sp_OADestroy #Object;
For this to work I had to enable Ole Automation:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
In my test server works fine, the problem is that on the production server to run
sp_configure 'Ole Automation Procedures', 1;
I get the following error:
The configuration option 'Ole Automation Procedures' does not exist, or it may be an advanced option.
When running
exec sp_configure
on the test server brings the record "Ole Automation Procedures" on the production server not.
Update
I modify the code to catch the error:
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get','http://server/ws/service1.asmx/Test', 'false';
Exec sp_OAMethod #Object, 'send';
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT;
EXEC sp_OAGetErrorInfo #Object
Select #ResponseText Resultado;
Exec sp_OADestroy #Object;
The instruction "sp_OAGetErrorInfo EXEC # Object" return: (0x8004271A
) Error in srv_convert.
According to Microsoft (link) is a problem of SqlServer. Since in my case the result of the webservice exceed 4000 characters.
How I can call a webservice from TSQL?
I just stumbled upon same error - "(0x8004271A ) Error in srv_convert."
To overcome char limitations, use #tmp table like below:
Create table #tmp(dt nvarchar(max))
insert into #tmp
exec #hr =sp_OAGetProperty #objWinHttp, 'ResponseText'
Select dt from #tmp -- single column/single row.
Drop Table #tmp -- clean up
Solution Source
heey i have maybe some help for you if you want to call to call a HTTP web service from T-SQL (no SQLCLR) You can automate the XMLHTTP server object using the Object Automation extended stored procedures.
Example
I suggest you use the CLR or an SSIS package though.
I solved it the following way:
Create a VBScript file (callWS.vbs) with the following code:
if WScript.Arguments.Count = 1 then
Set http = CreateObject("Microsoft.XmlHttp")
http.open "GET", WScript.Arguments(0), FALSE
http.send ""
WScript.Echo http.responseText
else
WScript.Echo "Not was provided the WS address."
end if
Then in TSQL:
declare #Command varchar(100)
declare #RetInfo varchar(8000)
select #Command = 'cscript c:\callWS.vbs "http://server/ws/service1.asmx/Test"'
print #Command
exec #RetInfo = master.dbo.xp_cmdshell #Command
print #RetInfo