SQL Server Export Blob Corrupts All Files - sql

I am exporting blobs with this code:
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
DECLARE #outout_path varchar(50) = 'D:\blob',
#i bigint,
#init int,
#data varbinary(max),
#file_path varchar(max),
#folder_path varchar(max)
DECLARE #Doctable TABLE (id int identity(1,1) , [FileName] varchar(100), file_data varBinary(max) )
INSERT INTO #Doctable([FileName],file_data)
Select top 10 thefilename, file_data FROM schm.table_with_blobs
SELECT #i = COUNT(1) FROM #Doctable
WHILE #i >= 1
BEGIN
SELECT #data = [file_data],
#file_path = #outout_path + '\'+ cast(id as varchar) + '\' + [FileName],
#folder_path = #outout_path + '\'+ cast(id as varchar)
FROM #Doctable
WHERE id = #i
EXEC [dbo].[CreateFolder] #folder_path
EXEC sp_OACreate 'ADODB.Stream', #init OUTPUT;
EXEC sp_OASetProperty #init, 'Type', 1;
EXEC sp_OAMethod #init, 'Open';
EXEC sp_OAMethod #init, 'Write', NULL, #data;
EXEC sp_OAMethod #init, 'SaveToFile', NULL, #file_path, 2;
EXEC sp_OAMethod #init, 'Close';
EXEC sp_OADestroy #init;
print 'Document Generated at - '+ #file_path
SELECT #data = NULL,
#init = NULL,
#file_path = NULL,
#folder_path = NULL;
SET #i -= 1;
END
All the files are exported as expected with the proper file format. However, all of the files are corrupted and cannot be opened, regardless of file format. What can I tweak to avoid this? Do I need to more explicitly call out the file type (available in thefilename field)?

I had a similar problem but was exporting with BCP rather than using ADODB.
I had to do two things :
convert the varbinary to varchar or nvarchar
make BCP export as
RAW
This is the BCP solution I came up with:
Declare #patient int, #mincount int, #maxcount int,#filename varchar(200), #script varchar(2000),#fileid varchar(10)
Set #patient=2;
set #mincount=1;
Declare #mydocs as table
(filename varchar(255), filebody image, drank int, file_id int)
insert into #mydocs
Select taf.Attachment_File_Name, taf.Attachment_File_Body, DENSE_RANK() OVER (ORDER BY taf.attachment_file_id) as drank, taf.Attachment_File_ID FROM [CNGSTT].[dbo].[tblAttachment] ta
left join [CNGSTT].[dbo].[tblAttachmentFile] taf
on taf.Attachment_ID=ta.Attachment_ID where ta.Patient_ID=#patient
Set #maxcount=(select MAX(drank) from #mydocs)
WHILE #mincount<=#maxcount
BEGIN
Set #filename = (select fle.FileName from #mydocs fle where drank=#mincount)
Set #fileid =(select fle.File_id from #mydocs fle where drank=#mincount)
set #script = 'bcp "SELECT cast(cast(Attachment_File_Body as varbinary(max)) as varchar(max)) from [tblattachmentfile] fle where Attachment_File_ID='+#fileid+'" queryout D:\temp\' + #filename + ' -T -c -C RAW'
exec master..xp_cmdshell #script
Set #mincount=#mincount+1
END

Related

Saving the BLOB data to a file via OLE processes

I am trying to export data from SQL Server to a file. The data is a .jpg. I found a script that would do so however whenever i run it I get a not any error message. and file not create in folder Please help me
DECLARE xArgsEntryImg CURSOR FOR
SELECT TOP 1
CONVERT(varbinary(max), E.ENTRY_IMAGE, 1) AS img1,
CONVERT(varchar(50), E.TKT_NO) + 'IMG1.jpg' AS img,
T.TicketNo
FROM
ITNLTCS_IMAGE.dbo.ICS_ENTRY_IMAGE E
INNER JOIN
fms25.dbo.tblTagTransaction T ON E.TKT_NO = T.TicketNo
INNER JOIN
FMS25.dbo.ReqPayViolationMessage m ON (T.TagTransactionPk = m.TagTransactionPk)
WHERE
NOT EXISTS (SELECT TOP 1 1
FROM tblImgUploadLog I
WHERE ImgType = 1
AND T.TicketNo = I.TicketNo)
DECLARE #PathForEntryImg nvarchar(max);
DECLARE #ImageDataForEntryImg varbinary(max);
DECLARE #FilenameForEntryImg NVARCHAR(max);
DECLARE #TicketNoForEntryImg bigint;
OPEN xArgsEntryImg
FETCH xArgsEntryImg INTO #ImageDataForEntryImg, #FilenameForEntryImg, #TicketNoForEntryImg
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRY
DECLARE #FullPathToOutputFileforEntryImg NVARCHAR(max);
DECLARE #FileName varchar(4000) = 'D:\FMS\IMAGES\CURRENT\a.jpg'
DECLARE #ObjectTokenEntryImg INT
EXEC sp_OACreate 'ADODB.Stream', #ObjectTokenEntryImg OUTPUT; -- Create Object
EXEC sp_OASetProperty #ObjectTokenEntryImg, 'Type', 1;
EXEC sp_OAMethod #ObjectTokenEntryImg, 'Open';
EXEC sp_OAMethod #ObjectTokenEntryImg, 'Write', NULL, #ImageDataForEntryImg;
EXEC sp_OAMethod #ObjectTokenEntryImg, 'SaveToFile', NULL, #FileName, 2;
EXEC sp_OAMethod #ObjectTokenEntryImg, 'Close';
EXEC sp_OADestroy #ObjectTokenEntryImg;
END TRY
BEGIN CATCH
END CATCH
FETCH NEXT From xArgsEntryImg INTO #ImageDataForEntryImg, #FilenameForEntryImg, #TicketNoForEntryImg
END
CLOSE xArgsEntryImg
DEALLOCATE xArgsEntryImg

Exporting table parameter result as .txt file using stored procedure

Is there a way that I could use for me to export the table parameter into .txt file in SQL Server?
Sample code that I did for trying to print out the
DECLARE #testTable TABLE (fld_Name VARCHAR(12), fld_Number VARCHAR(11))
DECLARE #fileTimeStamp varchar(200) = convert(varchar,getDate(), 112 )+'_'+ Replace(convert(varchar,getDate(), 114 ),':','') -- select convert(varchar, getdate(), 121)
DECLARE #fileExtension varchar(5) = 'txt'
INSERT INTO #testTable
SELECT [fld_Name] AS fld_Name,
[fld_Number] AS fld_Number
FROM TableBA tblBA
INNER JOIN TableCAS tblCAS ON
tblCAS.fld_Code = tblBA.fld_AccountNumber
WHERE [fld_Name] NOT IN (SELECT [fld_Name] FROM TableLeads)
declare #fn varchar(500) = 'D:/Test/Leads_'+#fileTimeStamp+'.'+#fileExtension;
declare #cmd varchar(8000) = concat('echo ', #testTable, ' > "', #fn, '"');
print #cmd
exec xp_cmdshell #cmd, no_output
set #cmd = concat('type "', #fn, '"');
print #cmd
exec xp_cmdshell #cmd;
Using that gives me an error of:
"Must declare the scalar variable "#testTable"
Is there a way that I could print the SELECT * results from the table parameter I created?
Try Like this:
declare #tablename varchar(100)='#testTable'
DECLARE #fileTimeStamp varchar(200) = convert(varchar,getDate(), 112 )+'_'+ Replace(convert(varchar,getDate(), 114 ),':','') -- select convert(varchar, getdate(), 121)
DECLARE #fileExtension varchar(5) = 'txt'
EXEC ('DECLARE '+#tablename+' TABLE (fld_Name VARCHAR(12), fld_Number VARCHAR(11)) ;
INSERT INTO '+#tablename+'
SELECT [fld_Name] AS fld_Name,
[fld_Number] AS fld_Number
FROM TableBA tblBA
INNER JOIN TableCAS tblCAS ON
tblCAS.fld_Code = tblBA.fld_AccountNumber
WHERE [fld_Name] NOT IN (SELECT [fld_Name] FROM TableLeads);
')
declare #fn varchar(500) = 'D:/Test/Leads_'+#fileTimeStamp+'.'+#fileExtension;
declare #cmd varchar(8000) = concat('echo ', #tablename, ' > "', #fn, '"');
print #cmd

Issue with Filestream Filetable not computing file_type column on insert

I am having a problem with my filestream filetable, when I run an insert statement on it the file saves, but the file_type column is null (and obviously cannot be updated manually given that it's a computed column)
DECLARE #counter INT, #maxPolicySectionId INT
DECLARE #name NVARCHAR(128)
DECLARE #file_stream VARBINARY(MAX)
DECLARE #path NVARCHAR(256)
DECLARE #command NVARCHAR(MAX)
DECLARE #fileTable TABLE(
name NVARCHAR(50),
filePath NVARCHAR(128),
polSecId INT
);
--...Populate #fileTable from database table...--
SELECT #counter = MIN(policySectionId), #maxPolicySectionId = MAX(policySectionId) FROM tblPolicySection
SET #name = (SELECT name FROM #fileTable WHERE polSecId = #counter)
SET #path = (SELECT filePath FROM #fileTable WHERE polSecId = #counter)
SET #path = REPLACE(#path, '192.168.0.6', 'meta-filesrv')
--SET #file_type in Filetable somehow.. unable to perform UPDATE because it's a computed column
SET #command = N'SELECT #file_stream1 = CAST(bulkcolumn AS varbinary(MAX))
from OPENROWSET(BULK ''' + #path + ''',
SINGLE_BLOB) AS x'
EXEC sp_executesql #command, N'#file_stream1 VARBINARY(MAX) OUTPUT',#file_stream1 = #file_stream OUTPUT
IF #path IS NOT NULL AND #name IS NOT NULL
BEGIN
INSERT INTO BlobDocStore(
name,
file_stream
)
SELECT
#name,
#file_stream
END
SET #counter = #counter + 1
As you can see I am passing a stream into the insert statement which should work to the best of my understanding. I'm hoping someone has had some experience with this in the past. Thanks.
The file_type is derived from the specified file name. If the file_type column is NULL, this suggests the #name value does not have a file extension.

Stored Procedure to import data into SQL Server database... Error

I have a text file file1.txt in the below format. Column 1 is AGUSR1 & Column 2 is AGUSR2. There are 3 records in the file:
"AGUSR1"|"AGUSR2"
"JASON "|"DEBBIE "
"JOY "|"JASON "
"ANNA "|"JOHN "
I have written a stored procedure to upload this text file into a SQL Server database like this:
CREATE PROCEDURE sp_Import
#TableName varchar(200),
#FilePath varchar(200)
AS
DECLARE #SQL varchar(5000)
SET #SQL = 'BULK INSERT ' + #TableName + ' FROM ''' + #FilePath +
''' WITH (FIELDTERMINATOR = ''|'', ROWTERMINATOR = ''{CR}{LF}'')'
EXEC (#SQL)
To execute it, I have used this statement:
EXEC sp_Import '[DB_DEMO].[dbo].[file1]' , '\\kacl1tsp048\DEMO\file1.txt'
Note : kacl1tsp048 is a remote server the input text file is at.
On execution, I am getting the below error -
Msg 4863, Level 16, State 1, Line 1
Bulk load data conversion error (truncation) for row 1, column 2 (AGUSR2).
The import into table schema is
CREATE TABLE [dbo].[file1]
(
[AGUSR1] [varchar](10) NULL,
[AGUSR2] [varchar](10) NULL
)
For ad-hoc style data imports I sometimes dispense with using BULK INSERTS in favor of selecting from the file itself to then process it. You could do something similar by creating a procedure to read your file as a table:
CREATE FUNCTION [dbo].[uftReadfileAsTable]
(
#Path VARCHAR(255),
#Filename VARCHAR(100)
)
RETURNS
#File TABLE
(
[LineNo] int identity(1,1),
line varchar(8000))
AS
BEGIN
DECLARE #objFileSystem int
,#objTextStream int,
#objErrorObject int,
#strErrorMessage Varchar(1000),
#Command varchar(1000),
#hr int,
#String VARCHAR(8000),
#YesOrNo INT
select #strErrorMessage='opening the File System Object'
EXECUTE #hr = sp_OACreate 'Scripting.FileSystemObject' , #objFileSystem OUT
if #HR=0 Select #objErrorObject=#objFileSystem, #strErrorMessage='Opening file "'+#path+'\'+#filename+'"',#command=#path+'\'+#filename
if #HR=0 execute #hr = sp_OAMethod #objFileSystem , 'OpenTextFile'
, #objTextStream OUT, #command,1,false,0--for reading, FormatASCII
WHILE #hr=0
BEGIN
if #HR=0 Select #objErrorObject=#objTextStream,
#strErrorMessage='finding out if there is more to read in "'+#filename+'"'
if #HR=0 execute #hr = sp_OAGetProperty #objTextStream, 'AtEndOfStream', #YesOrNo OUTPUT
IF #YesOrNo<>0 break
if #HR=0 Select #objErrorObject=#objTextStream,
#strErrorMessage='reading from the output file "'+#filename+'"'
if #HR=0 execute #hr = sp_OAMethod #objTextStream, 'Readline', #String OUTPUT
INSERT INTO #file(line) SELECT #String
END
if #HR=0 Select #objErrorObject=#objTextStream,
#strErrorMessage='closing the output file "'+#filename+'"'
if #HR=0 execute #hr = sp_OAMethod #objTextStream, 'Close'
if #hr<>0
begin
Declare
#Source varchar(255),
#Description Varchar(255),
#Helpfile Varchar(255),
#HelpID int
EXECUTE sp_OAGetErrorInfo #objErrorObject,
#source output,#Description output,#Helpfile output,#HelpID output
Select #strErrorMessage='Error whilst '
+coalesce(#strErrorMessage,'doing something')
+', '+coalesce(#Description,'')
insert into #File(line) select #strErrorMessage
end
EXECUTE sp_OADestroy #objTextStream
-- Fill the table variable with the rows for your result set
RETURN
END
Now you have a proc to convert your file to a table. You would still have to deal with the formatting of your delimiters so you could run something like this to populate [dbo].[file1]:
;WITH Split_Names (Value,Name, xmlname)
AS
(
SELECT
[LineNo],
line,
CONVERT(XML,'<Lines><line>'
+ REPLACE(line,'"|"', '</line><line>') + '</line></Lines>') AS xmlname
from [dbo].[uftReadfileAsTable]('\\kacl1tsp048\DEMO\file1.txt')
where line not like '"AGUSR1"%'
)
SELECT
Value,
RTRIM(REPLACE(xmlname.value('/Lines[1]/line[1]','varchar(100)'),'"', '')) AS AGUSR1,
RTRIM(REPLACE(xmlname.value('/Lines[1]/line[2]','varchar(100)'),'"', '')) AS AGUSR2
INTO [dbo].[file1]
FROM Split_Names
Hope that helps a little?!

How to attach a file to an email using SQL stored procedure?

Can't seem to find much information about how to attach a file that's been stored as a BLOB as part of an email.
I know you can attach files from the file system (C:\temp...) to email that are being setup in DBMAIL or custom stored procedures. However, I haven't seen any references to attaching something such as a PDF that's been stored as a binary object in a table.
I see where you can attach a query as a file, but I don't think that's what I'm looking for.
We would do this programatically via the application, but we need to be able to kick this SP via triggers or the application's server side code.
Is this possible or should i be asking other questions, since usually a binary object also needs to have a content type associated with it for browsers or mail objects to know how to handle?
The solution can not attach binary object stored in db field, you may change your schema a little bit store the path to the binary file. if you could enable .net clr in your database server, you will have more options.
use master
go
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[usp_send_cdosysmail]')
and objectproperty(id, N'isprocedure') = 1)
drop procedure [dbo].[usp_send_cdosysmail]
go
create procedure usp_send_cdosysmail
#from varchar(500) ,
#to varchar(500) ,
#subject varchar(500),
#body nvarchar(max) ,
#smtpserver varchar(25),
#bodytype varchar(10) ,
#attachment varchar(100)= ' '
as
declare #imsg int
declare #hr int
declare #source varchar(255)
declare #description varchar(500)
declare #output varchar(1000)
exec #hr = sp_oacreate 'cdo.message', #imsg out
exec #hr = sp_oasetproperty #imsg,
'configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusing").value','2'
exec #hr = sp_oasetproperty #imsg, 'configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").value', #smtpserver
exec #hr = sp_oamethod #imsg, 'configuration.fields.update', null
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, #bodytype, #body
-- Attachments...
IF #attachment IS NOT NULL AND LEN(#attachment) > 0 BEGIN
Declare #files table(fileid int identity(1,1),[file] varchar(255))
Declare #file varchar(255)
Declare #filecount int ; set #filecount=0
Declare #counter int ; set #counter = 1
DECLARE #outVar INT
SET #outVar = NULL
INSERT #files SELECT cValue FROM master..fn_split(#attachment,',')
SELECT #filecount=##ROWCOUNT
WHILE #counter<(#filecount+1)
BEGIN
SELECT #file = [file]
FROM #files
WHERE fileid=#counter
EXEC #hr = sp_OAMethod #imsg, 'AddAttachment',#outVar OUT, #file
SET #counter=#counter+1
END
END
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
exec #hr = sp_oadestroy #imsg
go
set quoted_identifier off
go
set ansi_nulls on
go
sp_configure 'Ole Automation Procedures', 1
RECONFIGURE
GO