Uploading a CSV file in sql using SP_OAMethod procedures to do a BULK sync with Salesforce using BULK API Version 2 - sql-server

My query is that I have a CSV file with data in the format as accepted by Salesforce and require to do a BULK sync using BULKApi Version 2. I now need to send this data from sql using SP_OAMethod procedures.
Tried to move this data into a DB table with a cursor on this table to concat the data and send it using the procedure, but unfortunately failed due to the string length limitation.
Request you to help me understand if there is a process to directly upload the CSV ( similar way we do in postman by selecting the Binary option and loading the CSV file from the path).
Any solution related to this would be greatly appreciated.
Thanking in advance.
I tried to use the below part of the code, and completed the job on Salesforce but did not process any records -
EXEC #ret = sp_OAMethod #token, 'open', NULL, 'PUT', #url, 'true';
EXEC #ret = sp_OAMethod #token, 'setRequestHeader', NULL, 'Authorization', #authHeader;
EXEC #ret = sp_OAMethod #token, 'setRequestHeader', NULL, 'Content-type', #contentType;
EXEC #ret = sp_OAMethod #token, 'setRequestHeader', NULL, 'content-disposition', "attachment; filename=<path of the csv file with filename.csv>";
I also tried to look for Failed records or successful records using the job id but it did not return anything.

Related

How Do I Find SSL Certificate Full Path And Use in a StoredProcedure to call an API

How do I find the ssl certificate path? That one installed by VisualStudio, to be more expecific when we use .NET Core and run "dotnet dev-certs https --trust" at the console...
Could you guys help me pls?
Everything I've tried drop me in the certificate name only. I could not see the path to set on that pattern 'LOCAL_MACHINE\My\'Certificate Name'.
I want to pass it ike a parameter on the SQL code below:
EXEC #hResult = sp_OAMethod
#Object,
'setOption',
NULL,
3,
'LOCAL_MACHINE\My\'Certificate Name';
Just because I'm trying to call a API using SQL Server and I need to use that SSL certificate to run my tests.
Could you guys help me pls?
The return message I've got untill now says that it's not a valid certificate but I think it's bacause I'm not finding the full path.
I don't know if I made this clear... Just summarazing... I need to do this by sql and I need to know how to use SSL certificate path as a parameter.
There follows the code I'm using:
begin
declare #test as int;
declare #Object as int;
declare #hResult as nvarchar(256)
declare #Response as nvarchar(256)
exec #test = sp_OACreate 'MSXML2.XMLHTTP', #Object out;
select #test, #Object;
EXEC #hResult = sp_OAMethod
#Object,
'setOption',
NULL,
3,
'LOCAL_MACHINE\My\'Certificate Name';
exec #test = sp_OAMethod #Object, 'open', null, 'get',
'https://localhost:44351/api/v1/account/3215', 'false'
select #test
exec #test = sp_OAMethod #Object, 'send'
IF #test <> 0
BEGIN
EXEC sp_OAGetErrorInfo #object
RETURN
END
exec sp_OAMethod #Object, 'responseText', #Response OUTPUT;
end
print #Response
I had the same problem using the same VS-generated cert. I could find the cert called "localhost" in the certmgr ("Personal"->"Certificates"->localhost), installed when I began the project. I added this line:
EXEC #hr = sp_OAMethod #Object,'setOption',NULL,3,'LOCAL_MACHINE\My\localhost';
and it worked.
However, i found I could change the line to anything and it still worked, ie:
EXEC #hr = sp_OAMethod #Object,'setOption',NULL,3,'LOCAL_MACHINE\My\bogusfake';
So I cannot promise that will work for you, nor explain how/why, but I am able to proceed with the project of posting from a stored procedure to a local api. The only difference I see between my code and yours is I didn't surround the cert name in quotes.

SQL Server web service requests on Fiddler

In SQL Server I call web service but can't see on the fiddler. How can I trace requests from sql server on fiddler?
PS: I tried setProxy but nothing changed.
This is my code:
--DROP PROCEDURE [dbo].[WS_IsEInvoiceUser]
CREATE PROCEDURE [dbo].[WS_IsEInvoiceUser]
#vkn varchar(20),
#username VARCHAR(50)='FreseniusMedikal',
#password VARCHAR(50)='xxxx',
#ResponseText as Varchar(8000) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Request INT
Declare #Body as varchar(8000) = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken>
<o:Username>'+#username+'</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">'+#password+'</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<IsEInvoiceUser xmlns="http://tempuri.org/">
<vknTckn>'+#vkn+'</vknTckn>
<alias/>
</IsEInvoiceUser>
</s:Body>
</s:Envelope>'
EXEC sp_OACreate 'MSXML2.ServerXMLHTTP', #Request OUT;
EXEC sp_OAMethod #Request, 'setProxy', NULL, '2', 'http://127.0.0.1:8888'
EXEC sp_OAMethod #Request, 'open', NULL, 'post','https://efatura.uyumsoft.com.tr/Services/Integration', 'false'
EXEC sp_OAMethod #Request, 'setRequestHeader', null, 'SOAPAction', 'http://tempuri.org/IIntegration/IsEInvoiceUser'
EXEC sp_OAMethod #Request, 'setRequestHeader', null, 'Content-Type', 'text/xml; charset=utf-8'
EXEC sp_OAMethod #Request, 'send', null, #body
EXEC sp_OAMethod #Request, 'responseText', #ResponseText OUTPUT
SELECT CHARINDEX('true', SUBSTRING(#ResponseText, CHARINDEX('IsSucceded="true" Value="', #ResponseText)+LEN('IsSucceded="true" Value="'), 5))
Exec sp_OADestroy #Request
END
First, you definitely do have to call setProxy or else your ServerXMLHTTPRequest won't route the traffic through Fiddler, so you're on the right track there. Having said that, I'm not sure your parameters are right, per this example they should be:
EXEC sp_OAMethod #Request, 'setProxy', '2', 'http://127.0.0.1:8888', ''
... which matches the declaration on MSDN.
For a HTTPS request to succeed, you will need to ensure that Fiddler's root certificate is trusted in the MACHINE's trusted root store. In Fiddler, choose Tools > Fiddler Options > HTTPS and click "Export root certificate to desktop." Then run MMC.exe and add the "Certificates" snapin. Choose "Computer account". Drag/drop the FiddlerRoot.cer from your desktop to the "Trusted Root Certification Authorities" folder in the mmc console and accept the prompts.

MYOB Data into SQL Server via API

I posted this question on the MYOB support forums and their support team responded to say that I'd be better contacting someone familiar with SQL server.
I am trying to get data from our MYOB file into SQL server. I have found the below code however it won't retrieve any data (I think I need to enter username and password as parameters but I'm not sure how).
Following is my code (with the company file information removed)
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Exec sp_OACreate 'MSXML2.XMLHTTP'
, #Object OUT;
Exec sp_OAMethod #Object
, 'open'
, NULL
, 'get'
, 'http://localhost:8080/AccountRight/fccce.....6e/GeneralLedger/TaxCode/?api-version=v2'
, 'false'
Exec sp_OAMethod #Object
, 'send'
Exec sp_OAMethod #Object
, 'responseText'
, #ResponseText OUTPUT
Select #ResponseText
Exec sp_OADestroy #Object
Can anyone assist me with this?
Thank you.
You're running this on the server so you ought to be instantiating an 'MSXML2.ServerXMLHTTP' object.
To authenticate to your company file, try Exec sp_OAMethod #Object, 'open', NULL, 'GET', 'http://localhost:8080/[Your URL]', 'false', 'Administrator', '[admin password]'
To get your response you might have to call sp_OAGetProperty rather than sp_OAMethod
The API returns JSON or HTML based on the format query string parameter (default is JSON). Since the API has an OData interface, and OData does support XML responses, you could try requesting an XML response. To do this you add an Accept header: Exec sp_OAMethod #Object, 'setRequestHeader' 'Accept', 'application/xml'.
The reason I'm flailing about a bit is while I understand what you're trying to achieve, the API wasn't designed with the MSXML2 library in mind. I agree that your URL is fine - if it wasn't the API team would have set you straight.
Normally what you'd do is define a DTO that you then initialise using the JSON returned from the API, and then map the DTO into your database. Check out http://developer.myob.com/api/accountright/code-samples-sdks/ They've got .Net, Java, PHP, Node and Ruby. Appreciate you're looking to cut out the code in the middle, so good luck with the Accept header.

Utilize xml-rpc from T-SQL code

Currently I have nice solutions for REST (via clr/assembly) and SOAP (via sp_OA based stored procedure) but XML-RPC is still a question to access directly from SQL Server T-SQL code.
Please advise which variants exist for this purpose.
I need to avoid application layer because all logic is already in a stored procedure inside the database, and just recordset is needed to be supplied.
I have consumed XML from an HTTP call within t-sql using the xmlhttp COM object, which looks something like:
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open',
NULL, 'get',
'http://www.webservicex.com /stockquote.asmx?symbol=MSFT', 'false'
Exec sp_OAMethod #Object, 'send'
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
Select #ResponseText
Exec sp_OADestroy #Object
The xml in #ResponseText can then be shredded via traditional tsql methods.
This isn't a particularly robust method; Using an SSIS package or CLR integration would most likely yield a better solution, but this is one way to keep it all within t-sql.
See: http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/eac9c027-db71-48ae-872d-381359d7fb51/

Can you call a webservice from TSQL code?

Is there a way to call out from a TSQL stored procedure or function to a webservice?
Yes , you can create like this
CREATE PROCEDURE CALLWEBSERVICE(#Para1 ,#Para2)
AS
BEGIN
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get', 'http://www.webservicex.com/stockquote.asmx/GetQuote?symbol=MSFT','false'
Exec sp_OAMethod #Object, 'send'
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
Select #ResponseText
Exec sp_OADestroy #Object
END
Sure you can, but this is a terrible idea.
As web-service calls may take arbitrary amounts of time, and randomly fail, depending on how many games of counterstrike are being played on your network at the time, you can't tell how long this is going to take.
At the bare minimum you're looking at probably half a second by the time it builds the XML, sends the HTTP request to the remote server, which then has to parse the XML and send a response back.
Whichever application did the INSERT INTO BLAH query which caused the web-service to fire is going to have to wait for it to finish. Unless this is something that only happens in the background like a daily scheduled task, your app's performance is going to bomb
The web service-invoking code runs inside SQL server, and uses up it's resources. As it's going to take a long time to wait for the HTTP request, you'll end up using up a lot of resources, which will again hurt the performance of your server.
Not in T-SQL code itself, but with SQL Server 2005 and above, they've enabled the ability to write CLR stored procedures, which are essentially functions in .NET code and then expose them as stored procedures for consumption. You have most of the .NET framework at your fingertips for this, so I can see consumption of a web service possible through this.
It is a little lengthy to discuss in detail here, but here's a link to an MSDN article on the topic.
I would not do this for heavy traffic or mission critical stuff, HOWEVER, if you do NOT need to receive feedback from a service, then it is actually a great thing to do.
Here is an example of what I have done.
Triggers Insert and Update on a Table
Trigger called Stored Proc that is passes the JSON data of the transaction to a Web Api Endpoint that then Inserts into a MongoDB in AWS.
Don't do old XML
JSON
EXEC sp_OACreate 'WinHttp.WinHttpRequest.5.1', #Object OUT;
EXEC sp_OAMethod #Object, 'Open', NULL, 'POST', 'http://server/api/method', 'false'
EXEC sp_OAMethod #Object, 'setRequestHeader', null, 'Content-Type', 'application/json'
DECLARE #len INT = len(#requestBody)
Full example:
Alter Procedure yoursprocname
#WavName varchar(50),
#Dnis char(4)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Object INT;
DECLARE #Status INT;
DECLARE #requestBody NVARCHAR(MAX) = '{
"WavName": "{WavName}",
"Dnis": "{Dnis}"
}'
SET #requestBody = REPLACE(#requestBody, '{WavName}', #WavName)
SET #requestBody = REPLACE(#requestBody, '{Dnis}', #Dnis)
EXEC sp_OACreate 'WinHttp.WinHttpRequest.5.1', #Object OUT;
EXEC sp_OAMethod #Object, 'Open', NULL, 'POST', 'http://server/api/method', 'false'
EXEC sp_OAMethod #Object, 'setRequestHeader', null, 'Content-Type', 'application/json'
DECLARE #len INT = len(#requestBody)
EXEC sp_OAMethod #Object, 'setRequestHeader', null, 'Content-Length', #len
EXEC sp_OAMethod #Object, 'send', null, #requestBody
EXEC sp_OAGetProperty #Object, 'Status', #Status OUT
EXEC sp_OADestroy #Object
In earlier versions of Sql, you could use either an extended stored proc or xp_cmdshell to shell out and call a webservice.
Not that either of these sound like a decent architecture - but sometimes you have to do crazy stuff.
You can do it with the embedded VB objects.
First you create one VB object of type 'MSXML2.XMLHttp', and you use this one object for all of your queries (if you recreate it each time expect a heavy performance penalty).
Then you feed that object, some parameters, into a stored procedure that invokes sp_OAMethod on the object.
Sorry for the inprecise example, but a quick google search should reveal how the vb-script method is done.
--
But the CLR version is much....MUCH easier.
The problem with invoking webservices is that they cannot keep pace with the DB engine. You'll get lots of errors where it just cannot keep up.
And remember, web SERVICES require a new connection each time. Multiplicity comes into play. You don't want to open 5000 socket connections to service a function call on a table. Thats looney!
In that case you'd have to create a custom aggregate function, and use THAT as an argument to pass to your webservice, which would return a result set...then you'd have to collate that. Its really an awkward way of getting data.
Here'a an example to get some data from a webservice. In this case parse a user agent string to JSON.
--first configure MSSQL to enable calling out to a webservice (1=true, 0=false)
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
CREATE PROCEDURE CallWebAPI_ParseUserAgent #UserAgent VARCHAR(512)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Object INT;
DECLARE #ResponseText AS VARCHAR(8000);
DECLARE #url VARCHAR(512)
SET #url = 'http://www.useragentstring.com/?getJSON=all&uas=' + #UserAgent;
EXEC sp_OACreate 'WinHttp.WinHttpRequest.5.1', #Object OUT;
EXEC sp_OAMethod #Object, 'Open', NULL, 'GET', #url, 'false'
EXEC sp_OAMethod #Object, 'setRequestHeader', NULL, 'Content-Type', 'application/json'
EXEC sp_OAMethod #Object, 'send'
EXEC sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
SELECT #ResponseText
EXEC sp_OADestroy #Object
END
--example how to call the API
CallWebAPI_ParseUserAgent 'Mozilla/5.0 (Windows NT 6.2; rv:53.0) Gecko/20100101 Firefox/53.0'
If you're working with sql 2000 compatibility levels and cannot do clr integration, see http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-using-MSXML.aspx
I been working for big/global companies around the world, using Oracle databases. We are consuming web services all time thru DB with store procedures and no issues, even those ones with heavy traffic. All of them for internal use, I mean with no access to internet, only inside the plant. I would recommend to use it but being really careful about how you design it

Resources