How to invoke webservice from SQL Server stored procedure - sql-server

I would like to know how to use a web service from a SQL Server stored procedure. I have a table in which the columns specify the city and state of the user. I want to pass this address as a parameter to Google Geocoding API web service and get the latitude and longitude.
I have successfully made use of this geocoding api in c#. But now, I want to use it in a stored procedure.
Can any one please suggest how to get this done? Or please provide me any links?
Any help will be appreciated!!
Thanks.

For something like this, you don't need a full web service implementation. You can use SQLCLR (SQL Server's .NET Integration) to submit the request to the URL, get the response back in XML (unless you can find a JSON library that will work without being set to UNSAFE), and then parse that response.
Look at the following MSDN pages:
HttpWebRequest
HttpWebResponse
XmlDocument
To escape the address:
If you are using SQL Server 2005, 2008, or 2008 R2, then use Uri.EscapeDataString as it was available prior to .NET Framework v4.5
If you are using SQL Server 2012, 2014, or newer, then you can use either Uri.EscapeDataString or, if the server has been updated to at least .NET Framework v4.5, then you can alternatively use WebUtility.UrlEncode
According to the Google Geocoding API documentation, the API URI should be formatted similarly to the following:
https://maps.googleapis.com/maps/api/geocode/xml?address={EscapedAddress}&key={API_KEY}
Just submit that with those 2 variables substituted with their proper values via HttpWebRequest, then call HttpWebRequest.GetResponse, then call HttpWebResponse.GetResponseStream. And do not forget to call the Close and Dispose methods of HttpWebResponse (or instantiate it in a using block)!!
Additional notes:
If not already done, you will have to enable (one time) "CLR Integration" at the server level: Enabling CLR Integration
Do not take the easy road and set the database to TRUSTWORTHY ON. Just sign the assembly with a password, then create an asymmetric key in the master database by pointing to your signed DLL, then create a login from that asymmetric key, and finally grant that login the UNSAFE ASSEMBLY permission. Then you can set the assembly WITH PERMISSION_SET = EXTERNAL_ACCESS.
Do not use the SP_OA* procedures as advocated by user3469363. Those OLE Automation procedures have been deprecated since SQL Server 2005 and will (hopefully) be removed someday (hopefully soon). They are also less efficient and less secure than SQLCLR.
Even more notes can be found in my answer to a similar question on DBA.StackExchange: Bringing web service data into SQL server

Omar Frometa has an example on how to do this. go this link
http://www.codeproject.com/Articles/428200/How-to-invoke-a-Web-Service-from-a-Stored-Procedur
In summary, use these extended stored procedures: SP_OACreate and SP_OAMethod to access objects such as MSXML2.ServerXMLHttp.

Related

call webservice with SQL Server 2012

We have a webservice with these methods :
NOCR_Send(datatable personInfo, string code, string username, string password) returns GUID;
NOCR_Get(GUID code, string code, string username, string password) returns DataTable;
I want to consume these methods in sql server. Is it a way to create datatable in TSQL?
SQLCLR isn't really meant for this - it's ok for simple functions that are better done in CLR (like needing to run a RegEx on something for example), but even then it creates dependencies and management issues it shouldn't have to (your DBA shouldn't need to know .NET, your .NET developer shouldn't have to be a DBA, etc.).
What you should do here is create an ADO.NET application that consumes the webservice and then passes the relevant data to SQL server, or consumes data from SQL server and passes the relevant data to your web service. You want to keep your web service abstracted from SQL Server and vice versa - don't try to make SQL Server a WCF client (it will do poorly), just give it the data from a well written WCF client.
In other words: let SQL Server handle data and .NET handle WCF.

Can SQL server send message to external JMS based application?

I want SQL server to send message to external application, Is that possible with SQL server?
I did google a lot but don't find useful material/Link. Any appropriate answer would be appreciated.
You can use RAISERROR for what you want.
RAISERROR('My Error Message',0,1)
This will work if the external application runs a query (like a stored procedure) and the query has this line. So for instance if you know the application runs sp_sample, then in sp_sample :
ALTER PROCEDURE sp_sample
AS
BEGIN
--Procedure normal code
RAISERROR('My Error Message',0,1)
END
This will execute the code (an INSERT for instance) and then send the message back to the application.
In theory is possible, because SQL Server can host CLR procedures and these procedures, if granted EXTERNAL_ACCESS permisssion, can do pretty much anything they please, including calling web services or JMS apps.
But is not recommend, for many reasons (performance, security, maintenability, deployment and configuration, troubleshooting and many more) . Use an external application to do your communication and let SQL Server just manage data.

how to ping a url from sql server 2008 stored proc

Hey guys, I want to ping a url over http from a sql server 2008 stored procedure.
What is the best and easiest way to do this?
UPDATE: To make it more clear, I just want to call an aspx page from a stored procedure to notify my aspx page that data has been modified and aspx needs to refresh the cache.
I know that I can do this via sql cache dependency but i want to use a push rather than a pull kind of notification.
You could write a CLR function that accepts a host/ip address string and returns the number of seconds it took to ping, or -1 if it was unable to ping.
If you have xp_cmdshell enabled then you can use:
EXEC sys.xp_cmdshell 'PING 127.0.0.1'
Make sure that you understand the security implications of enabling xp_cmdshell though. It's off by default for a reason.
SQL Cache dependency does use a push notification via SQL Service Broker. You just need to set up your application to subscribe to notifications. That would definitely be my first choice.
If for some reason that isn't suitable maybe this approach using Object Automation would work for you?
Edit Actually I was just reading the comments under the article and the original author suggests not using this in SQL2005 but using CLR instead if it is necessary to request a URL.

How to read SQL Server Report history programatically?

a SQL Reporting Services Question - for SQL Server 2008.
Given that SQL Server Reporting Services features a Scheduler which can be used to schedule the running of SQL Reports, does anyone know a way to programatically (via C#) read a report's history from the Report Server (and then perhaps retrieve the results of the report)?
So after some more digging, it looks like I need to generate a WSDL for the Report Server and then access information by using the ReportingService object - has anyone done this before (with 2008) and can provide some pointers?
Note: looks like (according to SQL 2008 books online) the WSDL address for SQL 2008 is:
http://server/reportserver/ReportService2005.asmx?wsdl
If I can get this working, I'll post an answer up with the basic steps to implementing it :) It's a little confusing as the documentation is a mixture of SQL 2000 and SQL 2005 references!
OK, so I've actually figured out how to accomplish this seemigly impossible task.
Before I begin, let me just say that if you are working with SQL Server Reporting Services 2008 (SSRS 08) and have (i.e. you have no choice) to use something like Basic auth, you'll only find a world of hurt with the WCF based Service Stubs & IIS. I'm going to blog about the configuration later.
The short answer is as follows:
Connect (e.g. new ReportingService2005() or ReportingService2005SoapClient())
Note: It's easier to use the old (pre-WCF) ASMX service, but not impossible to use the new CF version. The Authentication takes some configuring. There are also some slight syntactic changes between versions.
Find the report history you are looking for, e.g. ReportHistorySnapshot[] history = reportServer.ListReportHistory(#"/Reports/MyHandyReport");
Get the HistoryID from whichever snapshot you want (returned from the ListHistoryReport)
Now, use a ReportViewer to render the historic report, much like you would any other report, e.g.:
ReportViewer rv = new ReportViewer();
rv.ProcessingMode = ProcessingMode.Remote;
rv.ServerReport.ReportServerUrl = new Uri(#"http://localhost/reportserver");
rv.ServerReport.ReportPath = #"/Reports/MyHandyReport";
rv.ServerReport.HistoryId = historyId;
//...snip
byte[] bytes = rv.ServerReport.Render("Excel", null, out mimeType, out encoding, out extension, out streamids, out warnings);
Note: you can also use the second WCF Web Service (ReportExecution2005.asmx?wsdl) as well for Report Execution
Well it has soap and extensibility API, perhaps they can be used?

Problem calling stored procedure from another stored procedure via classic ASP

We have a classic ASP application that simply works and we have been loathe to modify the code lest we invoke the wrath of some long-dead Greek gods.
We recently had the requirement to add a feature to an application. The feature implementation is really just a database operation requires minimal change to the UI.
I changed the UI and made the minor modification to submit a new data value to the sproc call (sproc1).
In sproc1 that is called directly from ASP, we added a new call to another sproc that happens to be located on another server, sproc2.
Somehow, this does not work via our ASP app, but works in SQL Management Studio.
Here's the technical details:
SQL 2005 on both database servers.
Sql Login is authenticating from the ASP application to SQL 2005 Server 1.
Linked server from Server 1 to Server 2 is working.
When executing sproc1 from SQL Management Studio - works fine. Even when credentialed as the same user our code uses (the application sql login).
sproc2 works when called independently of sproc1 from SQL Management Studio.
VBScript (ASP) captures an error which is emitted in the XML back to the client. Error number is 0, error description is blank. Both from the ADODB.Connection object and from whatever Err.Number/Err.Description yields in VBScript from the ASP side.
So without any errors, nor any reproducibility (i.e. through SQL Mgmt Studio) - does anyone know the issue?
Our current plan is to break down and dig into the code on the ASP side and make a completely separate call to Server 2.sproc2 directly from ASP rather than trying to piggy-back through sproc1.
Have you got set nocount on set in both stored procedures? I had a similar issue once and whilst I can't remember exactly how I solved it at the moment, I know that had something to do with it!
You could be suffering from the double-hop problem
The double-hop issue is when the ASP/X page tries to use resources that are located on a server that is different from the IIS server.
Windows NT Challenge/Response does not support double-hop impersonations (in that once passed to the IIS server, the same credentials cannot be passed to a back-end server for authentication).
You should verify the attempted second connection using SQL Profiler.
Note that with your manual testing you are not authenticating via IIS. It's only when you initiate the sql via the ASP/X page that this problem manifests.
More resources:
http://support.microsoft.com/kb/910449
http://support.microsoft.com/kb/891031
http://support.microsoft.com/kb/810572
I had a similar problem and I solved it by setting nocount on and removing print commands.
My first reaction is that this might not be an issue of calling cross-server, but one of calling a second proc from a first, and that this might be what's acting differently in the two different environments.
My first question is this: what happens if you remove the cross-server aspect from the equation? If you could set up a test system where your first proc calls your second proc, but the second proc is on the same server and/or in the same database, do you still get the same problem?
Along these same lines: In my experience, when the application and SSMS have gotten different results like that, it has often been an issue of the stored procedures' settings. It could be, as Luke says, NOCOUNT. I've had this sort of thing happen from extraneous PRINT statements in the code, although I seem to remember the PRINTed value becoming part of the error description (very counterintuitively).
If anything is returned in the Messages window when you run this in SSMS, find out where it is coming from and make it stop. I would have to look up the technical terms, but my recollection is that different querying environments have different sensitivities to "errors", and that a default connection via SSSM will not throw an error at certain times when an ADO connection from a scripting language will.
One final thought: in case it is an environment thing, try different settings on your ASP page's connection string. E.g., if you have an OLEDB connection, try ODBC. Try the native and non-native SQL Server drivers. Check out what connection string options your provider supports, and try any of them that seem like they might be worth trying.
Example code might help :) Are you trying to return two tables from the stored procedure; I don't think ADO 2.6 can handle multiple tables being returned.
I did consider that (double-hop), but what is the difference between a sproc-in-a-sproc call like I am referring to vs. a typical cross-server join via INNER JOIN? Both would be executed on Server1, using the Linked Server credentials, and authenticating to Server 2.
Can anyone confirm that calling a sproc cross-server is different than doing a join on data tables? And why?
If the Linked Server config is a sql account - is that considered a double-hop (since what you refer to is NTLM double-hops?)
In terms of whether multiple resultsets are coming back - no. Both Server1.Sproc1 and Server2.Sproc2 would be "ExecuteNonQuery()" in the .net world and return nothing (no resultsets and no return values).
Try to check the permissions to the database for the user specified in the connection string.
Use the same user name in the connection string to log in to the database while using sql mgmt studio.
create some temporary table to write the intermediate values and exceptions since it can be a effective way of debugging your application.
Can I just check: You made the addition of sproc2? Prior to that it was working fine for ages.
Could you not change where you call sproc2 from? Rather than calling it from inside sproc1, can you call it from the ASP? That way you control the authentication to SQL in the code, and don't have to rely on setting up any trusts or shared remote authentication on the servers.
How is your linked server set up? You generally have some options as to how it authenticates to the remote server, which include logging in as the currently logged in user or specifying a SQL login to always use. Have you tried setting it to always use a specific account? That should eliminate any possible permissions issues in calling the remote procedure...

Resources