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

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

Related

API Request from SQL Server unable to use OPENJSON

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

OLE Procedures, query executed succesfully; No File Extracted

I am trying to extract a blob file from SQL Server. I was able to get it to execute successfully but when I look in my Desktop\consol\output directory, the file isn't there (refreshed, still nothing). Here is the code:
SELECT * FROM FileWarehouse
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
DECLARE #SQLIMG VARCHAR(MAX),
#File VARBINARY(MAX),
#OpPath VARCHAR(MAX),
#ObjectToken INT
SELECT #File = StoredFile FROM [dbo].[FileWarehouse] WHERE Id= 157994
SET #OpPath = 'C:\Users\Nick\Desktop\consol\output\marksheet.doc'
EXEC sp_OACreate 'ADODB.Stream', #ObjectToken OUTPUT
EXEC sp_OASetProperty #ObjectToken, 'Type', 1
EXEC sp_OAMethod #ObjectToken, 'Open'
EXEC sp_OAMethod #ObjectToken, 'Write', NULL, #File
EXEC sp_OAMethod #ObjectToken, 'SaveToFile', NULL, #OpPath, 2
EXEC sp_OAMethod #ObjectToken, 'Close'
EXEC sp_OADestroy #ObjectToken
GO
In the SELECT statement, dbo.[FileWarehouse] and StoredFile are both underlined, saying 'Invalid Object Name' and 'Invalid Column Name', respectively. They are definitely valid, so I'm not sure it's saying that. Here is the tutorial I was following https://www.youtube.com/watch?v=8g7_F3Ice6E .
Any help would be greatly appreciated. Thank You.
While Dan's answer is correct (use Powershell or SQL CLR instead), the reason your COM automation isn't working, is that you've failed to capture and inspect the return codes from the extended stored procedures.
Here's an example:
--exec sp_configure 'Show Advanced Options', 1
--reconfigure
--exec sp_configure 'Ole Automation Procedures', 1
--reconfigure
declare #url varchar(2000) = 'http://www.bing.com'
declare #hr int;
declare #win int;
begin try
EXEC #hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',#win OUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win, 'Open',NULL,'GET',#url,'false'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win,'Send'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
declare #status int
EXEC #hr=sp_OAGetProperty #win,'Status', #status out
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
if #status <> 200
begin;
declare #msg varchar(2000) = concat('web request failed ', #status);
throw 60000, #msg, 1;
end;
declare #response table(text nvarchar(max));
insert into #response(text)
EXEC #hr=sp_OAGetProperty #win,'ResponseText';
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
select * from #response;
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
end try
begin catch
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
throw;
end catch
The IntelliSense error is erroneous if the script runs.
I suggest you generally avoid the ole automation procs for new development. If you don't really need to use T-SQL to create the file, consider a simple PowerShell script. This is more robust and flexible for ad-hoc needs. Below is an example that uses the standard ADO.NET objects.
$connection = New-Object System.Data.SqlClient.SQLConnection("Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI")
$command = New-Object System.Data.SqlClient.SqlCommand("SELECT StoredFile FROM [dbo].[FileWarehouse] WHERE Id= 157994;", $connection)
$connection.Open()
$blob = $connection.ExecuteScalar()
$connection.Close()
[System.IO.File]::WriteAllBytes("C:\Users\Nick\Desktop\consol\output\marksheet.doc", $blob)

Verify data integrity for varbinary column

I am inserting a .jpg into a varbinary(max) column in SQL Server 2012 using the following command:
INSERT INTO Employees
VALUES(5, (SELECT * FROM OPENROWSET(BULK N'C:\4.jpg',SINGLE_BLOB) AS image))
It inserts a record in the table.
Then I used the following command to restore the file from db to file system.
BCP "SELECT pic FROM Employees where id=5" queryout "C:\51.jpg" -N -T
When I try to view the downloaded file using image viewer, I get an error
File is damaged.
Any ideas?
This worked for me: How to export image field to file?
The short version without the cursor looks like this:
DECLARE #ImageData VARBINARY(max)
DECLARE #FullPathToOutputFile NVARCHAR(2048);
SELECT #ImageData = pic FROM Employees WHERE id=5
SET #FullPathToOutputFile = 'C:\51.jpg'
DECLARE #ObjectToken INT
EXEC sp_OACreate 'ADODB.Stream', #ObjectToken OUTPUT;
EXEC sp_OASetProperty #ObjectToken, 'Type', 1;
EXEC sp_OAMethod #ObjectToken, 'Open';
EXEC sp_OAMethod #ObjectToken, 'Write', NULL, #ImageData;
EXEC sp_OAMethod #ObjectToken, 'SaveToFile', NULL, #FullPathToOutputFile, 2;
EXEC sp_OAMethod #ObjectToken, 'Close';
EXEC sp_OADestroy #ObjectToken;
Before you can do that you have execute this only once in your database:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
All credits belong to #mathijsuitmegen :) thanks for this working solution

How to email query output

I have a basic query, and i'd like to email the results. How can I do this at the query level? So if my query is:
SELECT
Store_Id, Paid_Out_Amount, Paid_Out_Comment,
Paid_Out_Datetime, Update_UserName
FROM Paid_Out_Tb
WHERE (Store_Id = 1929) OR
(Paid_Out_Amount > 50) AND
(Paid_Out_Datetime BETWEEN
CONVERT(DATETIME, '2012-06-01 00:00:00', 102) AND
CONVERT(DATETIME, '2012-06-30 00:00:00', 102))
How would I email the output? I have a procedure to send email via SMTP and the parameters are #From, #To, #Subject and #body... which works.. How would I make the body the outcome of the query?
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[sp_SQLNotify]
#From varchar(100) ,
#To varchar(100) ,
#Subject varchar(100)=" ",
#Body varchar(4000) = "Test"
/*********************************************************************
This stored procedure takes the above parameters and sends an e-mail.
All of the mail configurations are hard-coded in the stored procedure.
Comments are added to the stored procedure where necessary.
Reference to the CDOSYS objects are at the following MSDN Web site:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_messaging.asp
***********************************************************************/
AS
Declare #iMsg int
Declare #hr int
Declare #source varchar(255)
Declare #description varchar(500)
Declare #output varchar(1000)
--************* Create the CDO.Message Object ************************
EXEC #hr = sp_OACreate 'CDO.Message', #iMsg OUT
--***************Configuring the Message Object ******************
-- This is to configure a remote SMTP server.
-- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_schema_configuration_sendusing.asp
EXEC #hr = sp_OASetProperty #iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value','2'
-- This is to configure the Server Name or IP address.
-- Replace MailServerName by the name or IP of your SMTP Server.
EXEC #hr = sp_OASetProperty #iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value', '10.1.1.10'
-- Save the configurations to the message object.
EXEC #hr = sp_OAMethod #iMsg, 'Configuration.Fields.Update', null
-- Set the e-mail parameters.
EXEC #hr = sp_OASetProperty #iMsg, 'To', #To
EXEC #hr = sp_OASetProperty #iMsg, 'From', #From
EXEC #hr = sp_OASetProperty #iMsg, 'Subject', #Subject
-- If you are using HTML e-mail, use 'HTMLBody' instead of 'TextBody'.
EXEC #hr = sp_OASetProperty #iMsg, 'TextBody', #Body
EXEC #hr = sp_OAMethod #iMsg, 'Send', NULL
-- Sample error handling.
IF #hr <>0
select #hr
BEGIN
EXEC #hr = sp_OAGetErrorInfo NULL, #source OUT, #description OUT
IF #hr = 0
BEGIN
SELECT #output = ' Source: ' + #source
PRINT #output
SELECT #output = ' Description: ' + #description
PRINT #output
END
ELSE
BEGIN
PRINT ' sp_OAGetErrorInfo failed.'
RETURN
END
END
-- Clean up the objects created.
EXEC #hr = sp_OADestroy #iMsg
PRINT 'Mail Sent!'
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
This is the procedure i'm using to send the mail... which works... I just want to add a spot in it to send the results of the query above it... Can this be done easily within in the procedure?
Use the SQL Server Powershell pack. An example (with detailed explanation) of using it to obtain output is here.
(The above is taken from this SO answer, but to clarify something s/he says: SQL Server 2008 client components is required (Express should be fine), but it can work with SQL Server 2000 databases (source).)
You can also use a variable for a direct loop concatenation. See https://stackoverflow.com/a/4447564/1180926 (although you would use tab and newline delimiters instead of HTML code).
You would then just change your query accordingly, store it in #Body, and you're done!

Webservice From SQL

Can I call a remote webservice from a Stored Procedure and use the values that areretuned?
If you're using SQL 2005/2008, you could do this from a CLR stored procedure if you have the ability to install and run these. For more info:
http://msdn.microsoft.com/en-us/library/ms190790.aspx
Service Broker might provide the sort of functionality you're looking for here.
As The AntiSanta says, using a CLR stored procedure this is possible. The real question is whether you can avoid it altogether. It feels upside-down to call a web service from a stored procedure. Ideally you'd have some other service/app/layer that calls both the stored procedure and a web service. Possibly the stored proc returns parameter values for the web service, and you commit your local transaction after the WS call is complete.
This would make both debugging, deployment and support much more simple in the long run, and decouples the direct reference between the stored proc and the web service.
On SQL Server 2000 and up (if CLR is not enabled), you can use COM through stored procedures (sp_OACreate, sp_OAMethod, etc) if you have an existing COM wrapper for your web service.
Here is my code that works.
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
if #hr < 0 begin Raiserror('sp_OACreate MSXML2.ServerXMLHttp failed',16,1)
return end
exec #hr = sp_OAMethod #obj, 'Open', NULL, 'GET', #UrlString, false
if #hr <0 begin set #msg = 'sp_OAMethod Open failed' goto eh end
exec #hr = sp_OAMethod #obj, 'send'
if #hr <0 begin set #msg = 'sp_OAMethod Send failed' goto eh end
exec #hr = sp_OAGetProperty #obj, 'status', #status OUT
if #hr <0 begin set #msg = 'sp_OAMethod read status failed' goto eh end
if #status <> 200 begin set #msg = 'sp_OAMethod http status ' +str(#status) goto eh end
exec #hr = sp_OAGetProperty #obj, 'responseText', #response OUT
if #hr <0 begin set #msg = 'sp_OAMethod read response failed' goto eh end
exec #hr = sp_OADestroy #obj
select #response
......
eh:
exec #hr = sp_OADestroy #obj
Raiserror(#msg, 16, 1)
Return