quote: Originally posted by spirit1
could you create a CLR sproc to do this? it is prefered way to do custom disk read/write activity in sql server 2005.
I might be able to but I won't :). In my situation, I do not want to open the avenue of developers coding CLR on my databases for obvious reasons. Here is a method I use for standard text files:
SET NOCOUNT ON
DECLARE @ErrorNumber INT
DECLARE @ErrorSeverity INT
DECLARE @ErrorState INT
DECLARE @ErrorProcedure NVARCHAR(126)
DECLARE @ErrorLine INT
DECLARE @ErrorMessage NVARCHAR(2048)
--For OLE Automation.
DECLARE @ObjectReturn INT
DECLARE @ObjectToken INT
DECLARE @ErrorSource VARCHAR(255)
DECLARE @ErrorDesc VARCHAR(255)
DECLARE @FileHandle INT
DECLARE @ObjectTargetFileName VARCHAR(1000)
DECLARE @Buffer VARCHAR(4000)
DECLARE @BufferPos INT
DECLARE @BufferSize INT; SET @BufferSize = 4000
DECLARE @ScheduleData XML
/* Get the schedule data */
--custom code went here to return XML datatype into @ScheduleData - so assume @ScheduleData is valid XML.
BEGIN TRY
/* Create a file system object. */
EXEC @ObjectReturn = sp_OACreate 'Scripting.FileSystemObject', @ObjectToken OUTPUT
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @ObjectToken, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('Create Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Open the file. */
SET @ObjectTargetFileName = '\\SERVERNAME\SHARENAME\SYSMAINT.XML'
EXEC @ObjectReturn = sp_OAMethod @ObjectToken, 'OpenTextFile', @FileHandle OUTPUT, @FileName=@ObjectTargetFileName, @IOMode=2, @Create=1
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @ObjectToken, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('OpenTextFile Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Write the file */
/* Since the writing of the file gets truncated at 4000 characters, buffer the writes. */
SET @BufferPos = 0
WHILE (@BufferPos < LEN(CAST(@ScheduleData AS NVARCHAR(MAX))))
BEGIN
SET @Buffer = SUBSTRING(CAST(@ScheduleData AS NVARCHAR(MAX)), @BufferPos + 1, @BufferSize)
SET @BufferPos = @BufferPos + @BufferSize
EXEC @ObjectReturn = sp_OAMethod @FileHandle, 'Write', NULL, @Text=@Buffer
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @FileHandle, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('Write Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
END
/* Close the file. */
EXEC @ObjectReturn = sp_OAMethod @FileHandle, 'Close'
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @FileHandle, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('Close Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Destroy the text stream object. */
EXEC @ObjectReturn = sp_OADestroy @FileHandle
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @FileHandle, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('TextStream Destroy Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Destroy the file system object. */
EXEC @ObjectReturn = sp_OADestroy @ObjectToken
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @ObjectToken, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('FileSystemObject Destroy Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
END TRY
BEGIN CATCH
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorProcedure = ERROR_PROCEDURE(),
@ErrorLine = ERROR_LINE(),
@ErrorMessage = ERROR_MESSAGE();
RAISERROR('Procedure ''%s'' failed on line number ''%u'' with message ''%s'' - (error number: ''%u'', severity: ''%u'', state: ''%u'').', 15, 1, @ErrorProcedure, @ErrorLine, @ErrorMessage, @ErrorNumber, @ErrorSeverity, @ErrorState)
END CATCH
Now when I tailor this for an image datatype, the write always fails. The error message is very vague unfortunately but I have to assume it's due to the file being binary. Here is a similar script I have at this point for binary data (note the line in red that failes):
DECLARE @ErrorNumber INT
DECLARE @ErrorSeverity INT
DECLARE @ErrorState INT
DECLARE @ErrorProcedure NVARCHAR(126)
DECLARE @ErrorLine INT
DECLARE @ErrorMessage NVARCHAR(2048)
--For OLE Automation.
DECLARE @ObjectReturn INT
DECLARE @ObjectToken INT
DECLARE @ErrorSource VARCHAR(255)
DECLARE @ErrorDesc VARCHAR(255)
DECLARE @FileHandle INT
DECLARE @ObjectTargetFileName VARCHAR(1000)
DECLARE @Buffer VARBINARY(4000)
DECLARE @BufferPos INT
DECLARE @BufferSize INT; SET @BufferSize = 4000
DECLARE @Image VARBINARY(MAX)
--custom code went here to retrieve an IMAGE column into variable @Image from an IMAGE datatype in a table.
--SELECT @Image = assume valid query is here.
BEGIN TRY
/* Create a file system object. */
EXEC @ObjectReturn = sp_OACreate 'Scripting.FileSystemObject', @ObjectToken OUTPUT
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @ObjectToken, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('Create Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Open the file. */
SET @ObjectTargetFileName = '\\SQLPRODVIRTUAL\SQLUPLOAD\TEMP\' + 'BEN01.JPG'
EXEC @ObjectReturn = sp_OAMethod @ObjectToken, 'OpenTextFile', @FileHandle OUTPUT, @FileName=@ObjectTargetFileName, @IOMode=2, @Create=1
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @ObjectToken, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('OpenTextFile Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
SET @BufferPos = 0
WHILE (@BufferPos < DATALENGTH(@Image))
BEGIN
SET @Buffer = SUBSTRING(@Image, @BufferPos + 1, @BufferSize)
SET @BufferPos = @BufferPos + @BufferSize
EXEC @ObjectReturn = sp_OAMethod @FileHandle, 'Write', NULL, @Text=@Buffer
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @FileHandle, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('Write Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
END
/* Close the file. */
EXEC @ObjectReturn = sp_OAMethod @FileHandle, 'Close'
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @FileHandle, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('Close Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Destroy the text stream object. */
EXEC @ObjectReturn = sp_OADestroy @FileHandle
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @FileHandle, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('TextStream Destroy Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
/* Destroy the file system object. */
EXEC @ObjectReturn = sp_OADestroy @ObjectToken
IF (@ObjectReturn <> 0)
BEGIN
EXEC sp_OAGetErrorInfo @ObjectToken, @ErrorSource OUTPUT, @ErrorDesc OUTPUT
RAISERROR('FileSystemObject Destroy Error (return: ''%u'', source: ''%s'', description: ''%s'')', 15, 1, @ObjectReturn, @ErrorSource, @ErrorDesc)
END
END TRY
BEGIN CATCH
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorProcedure = ERROR_PROCEDURE(),
@ErrorLine = ERROR_LINE(),
@ErrorMessage = ERROR_MESSAGE();
RAISERROR('Procedure ''%s'' failed on line number ''%u'' with message ''%s'' - (error number: ''%u'', severity: ''%u'', state: ''%u'').', 15, 1, @ErrorProcedure, @ErrorLine, @ErrorMessage, @ErrorNumber, @ErrorSeverity, @ErrorState)
END CATCH
The error I get back is Msg 50000, Level 15, State 1, Line 105 Procedure '(null)' failed on line number '69' with message 'Write Error (return: '2148139013', source: '(null)', description: '(null)')' - (error number: '50000', severity: '15', state: '1'). |