Writing nvarchar to a text file - sql

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

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)

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.

How to save many pdf files into a folder in sql server

I have many pdf files in my database and I want to store them in a folder based on priority. When I use the code below I am unable to save all files; it just saves one file. :(
Declare
#File_Path_1 VARBINARY(MAX),
#FileName_1 VARCHAR(MAX),
#Timestamp_1 varchar(max),
#objectToken_1 int
DECLARE cFiles CURSOR FAST_FORWARD FOR
SELECT request_number from data where priority=1
OPEN cFiles
FETCH NEXT FROM cFiles INTO #FileName_1
WHILE ##FETCH_STATUS = 0 BEGIN
SET #FileName_1 = #FileName_1
set #Timestamp_1='c:\Dump\1.pdf'
EXEC sp_oacreate 'ADODB.Stream', #ObjectToken_1 OUTPUT
EXEC sp_oasetproperty #objecttoken_1, 'type', 1
EXEC sp_oamethod #objecttoken_1,'open'
EXEC sp_oamethod #objecttoken_1,'Write',Null,#File_Path_1
EXEC sp_oamethod #objecttoken_1,'Savetofile',Null,#Timestamp_1,2
EXEC sp_oamethod #objecttoken_1,'Close'
EXEC sp_oamethod #objecttoken_1,'open'
FETCH NEXT FROM cFiles INTO #FileName_1
END
CLOSE cFiles
DEALLOCATE cFiles
the code above fetches me just one record can any one please help in
DECLARE #SOURCEPATH VARBINARY(MAX),
#DESTPATH VARCHAR(MAX),
#ObjectToken INT,
#Request_Number varchar(30)
DECLARE PDFPATH CURSOR FAST_FORWARD FOR
SELECT ID from Table
OPEN PDFPATH
FETCH NEXT FROM PDFPATH INTO #SOURCEPATH, #Request_Number
WHILE ##FETCH_STATUS = 0
BEGIN
SET #DESTPATH = 'C:\path' + CAST(#Request_Number AS varchar) + '.pdf'
EXEC sp_OACreate 'ADODB.Stream', #ObjectToken OUTPUT
EXEC sp_OASetProperty #ObjectToken, 'Type', 1
EXEC sp_OAMethod #ObjectToken, 'Open'
EXEC sp_OAMethod #ObjectToken, 'Write', NULL, #SOURCEPATH
EXEC sp_OAMethod #ObjectToken, 'SaveToFile', NULL, #DESTPATH, 2
EXEC sp_OAMethod #ObjectToken, 'Close'
EXEC sp_OADestroy #ObjectToken
FETCH NEXT FROM PDFPATH INTO #SOURCEPATH, #Request_Number
END
I Hope this snippet helps people who are in need :) Thank you all for helping me :)
The main problem is that you are not dynamically creating the filename:
set #Timestamp_1='c:\Dump\1.pdf'
should be something like:
set #Timestamp_1='c:\Dump\' + CONVERT(VARCHAR(50), #FileName_1) + '.pdf'
And you don't seem to be getting the source data to write out; #File_Path_1 is never set. You need to add a field to the SELECT list and add the #File_Path_1 variable to the FETCH statement.
Also, this line doesn't do anything:
SET #FileName_1 = #FileName_1

sql server http request not working

I having facing an issue in sql server 2008 regarding http request using t-SQL. the url which i have used is working fine in url browser but when i include this url in code it gives "null". Please help me to solve the issue .
Declare #Object as Int;
Declare #ResponseText as NVARCHAR(MAX);
Exec sp_OACreate 'MSXML2.ServerXMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get', 'https://api.eancdn.com/ean-services/rs/hotel/v3/info?cid=55505&minorRev=99&apiKey=cbrzfta369qwyrm9t5b8y8kf&locale=en_US&currencyCode=USD&xml=%3CHotelInformationRequest%3E%0A%20%20%20%20%3ChotelId%3E122212%3C%2FhotelId%3E%0A%20%20%20%20%3Coptions%3E0%3C%2Foptions%3E%0A%3C%2FHotelInformationRequest%3E'
EXEC sp_OAMethod #object, 'setRequestHeader', null, 'Content-Type', 'application/x-www-form-urlencoded'
Exec sp_OAMethod #Object, 'send'
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
Select #ResponseText
Exec sp_OADestroy #Object