Hola, chicos,
¡Buenas noches!
Recuerda el post que hice sobre Habilitación de la automatización OLE a través de T-SQL en SQL Server ¿Dónde dije que publicaría sobre algunas funciones interesantes que ejemplifican el uso de OLE Automation en SQL Server? Entonces esa es la publicación 🙂
Para evitar poner demasiados procedimientos y funciones almacenados aquí en la publicación y hacerla demasiado larga, creé un archivo comprimido con el código fuente de los scripts que están disponibles aquí y solo explicaré el uso de cada uno de ellos.
fncFile_Exists_FSOUso: SELECT CLR.dbo.fncArquivo_Exist_FSO('C:\Teste.txt')
Código fuente:
CREATE FUNCTION [dbo].[fncArquivo_Existe_FSO] (@strArquivo VARCHAR(1000))
RETURNS INT
AS
BEGIN
DECLARE
@hr INT,
@objFileSystem INT,
@retorno INT,
@source VARCHAR(250),
@description VARCHAR(2000)
EXEC @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
RETURN 0
END
EXEC @hr = sp_OAMethod
@objFileSystem,
'FileExists',
@retorno OUT,
@strArquivo
IF (@hr <> 0)
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
EXEC sp_OADestroy
@objFileSystem
RETURN 0
END
EXEC sp_OADestroy
@objFileSystem
RETURN @retorno
END
Uso: SELECT CLR.dbo.fncDiretorio_Existe_FSO(‘C:\Dirceu’)
Código fuente:
CREATE FUNCTION [dbo].[fncDiretorio_Existe_FSO] (@strDiretorio VARCHAR(1000))
RETURNS INT
AS
BEGIN
DECLARE
@hr INT,
@objFileSystem INT,
@retorno INT,
@source VARCHAR(250),
@description VARCHAR(2000)
EXEC @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
RETURN 0
END
EXEC @hr = sp_OAMethod
@objFileSystem,
'FolderExists',
@retorno OUT,
@strDiretorio
IF (@hr <> 0)
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
EXEC sp_OADestroy
@objFileSystem
RETURN 0
END
EXEC sp_OADestroy
@objFileSystem
RETURN @retorno
END
Uso: SELECT * FROM CLR.dbo.fncLer_Arquivo_FSO('C:\Teste.txt')
Código fuente:
CREATE FUNCTION [dbo].[fncLer_Arquivo_FSO] (@Ds_Arquivo VARCHAR(256))
RETURNS @Tabela_Final TABLE (Ds_Linha VARCHAR(8000))
AS
BEGIN
DECLARE @OLEResult INT
DECLARE @FileSystemObject INT
DECLARE @FileID INT
DECLARE @Message VARCHAR (8000)
DECLARE @Tabela TABLE ( Ds_Linha varchar(8000) )
EXECUTE @OLEResult = sp_OACreate 'Scripting.FileSystemObject', @FileSystemObject OUT
IF @OLEResult <> 0
BEGIN
SET @Message = 'Scripting.FileSystemObject - Error code: ' + CONVERT (VARCHAR, @OLEResult)
INSERT INTO @Tabela_Final SELECT @Message
RETURN
END
EXEC @OLEResult = sp_OAMethod @FileSystemObject, 'OpenTextFile', @FileID OUT, @Ds_Arquivo, 1, 1
IF @OLEResult <> 0
BEGIN
SET @Message = 'OpenTextFile - Error code: ' + CONVERT (VARCHAR, @OLEResult)
INSERT INTO @Tabela_Final SELECT @Message
RETURN
END
EXECUTE @OLEResult = sp_OAMethod @FileID, 'ReadLine', @Message OUT
WHILE (@OLEResult >= 0)
BEGIN
INSERT INTO @Tabela(Ds_Linha) VALUES( @Message )
EXECUTE @OLEResult = sp_OAMethod @FileID, 'ReadLine', @Message OUT
END
EXECUTE @OLEResult = sp_OADestroy @FileID
EXECUTE @OLEResult = sp_OADestroy @FileSystemObject
INSERT INTO @Tabela_Final
SELECT Ds_Linha FROM @Tabela
RETURN
END
Uso: EXEC CLR.dbo.stpDelete_Arquivo_FSO ‘C:\Teste.txt’
Código fuente:
CREATE PROCEDURE [dbo].[stpApaga_Arquivo_FSO] (@strArquivo VARCHAR(1000))
AS
BEGIN
DECLARE
@hr INT,
@objFileSystem INT,
@source VARCHAR(250),
@description VARCHAR(2000)
EXEC @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
END
IF (CLR.dbo.fncArquivo_Existe(@strArquivo) = 1)
BEGIN
EXEC @hr = sp_OAMethod
@objFileSystem,
'DeleteFile',
NULL,
@strArquivo
END
IF (@hr <> 0)
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
EXEC sp_OADestroy
@objFileSystem
END
EXEC sp_OADestroy
@objFileSystem
END
Uso: EXEC CLR.dbo.stpCopia_Arquivo_FSO ‘C:\Teste.txt’, ‘C:\Arquivos\Novo_Arquivo.log’, 1: se sobrescribirá si ya existe (tercer parámetro)
Código fuente:
CREATE PROCEDURE [dbo].[stpCopia_Arquivo_FSO] (
@strOrigem VARCHAR(MAX),
@strDestino VARCHAR(MAX),
@sobrescrever INT = 0
)
AS
BEGIN
IF (dbo.fncArquivo_Existe(@strOrigem) = 1 AND @strOrigem != @strDestino)
BEGIN
DECLARE
@hr INT,
@objFileSystem INT,
@source VARCHAR(250),
@description VARCHAR(2000)
EXEC @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
RAISERROR('Object Creation Failed 0x%x, %s, %s',16,1,@hr,@source,@description)
RETURN
END
IF (dbo.fncArquivo_Existe(@strDestino) = 1)
IF (@sobrescrever = 1)
EXEC dbo.stpApaga_Arquivo_FSO @strDestino
ELSE
BEGIN
PRINT 'O arquivo de destino já existe e o parâmetro sobrescrever foi definido como NÃO'
RETURN
END
EXEC @hr = sp_OAMethod
@objFileSystem,
'CopyFile',
NULL,
@strOrigem,
@strDestino
IF (@hr <> 0)
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
EXEC sp_OADestroy
@objFileSystem
RAISERROR('Method Failed 0x%x, %s, %s',16, 1, @hr, @source, @description)
PRINT @source
PRINT @description
RETURN
END
EXEC sp_OADestroy
@objFileSystem
END
ELSE
PRINT 'O arquivo de origem não existe ou é igual ao arquivo de destino'
END
GO
Uso: EXEC CLR.dbo.stpWrite_Arquivo_FSO('C:\Teste.txt', 'Prueba de escritura de archivo')
Código fuente:
CREATE PROCEDURE [dbo].[stpEscreve_Arquivo_FSO] (
@String VARCHAR(MAX),
@Ds_Arquivo VARCHAR(1501)
)
AS
BEGIN
DECLARE
@objFileSystem INT,
@objTextStream INT,
@objErrorObject INT,
@strErrorMessage VARCHAR(1000),
@Command VARCHAR(1000),
@hr INT
SET NOCOUNT ON
SELECT
@strErrorMessage = 'opening the File System Object'
EXECUTE @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @HR = 0
SELECT
@objErrorObject = @objFileSystem,
@strErrorMessage = 'Creating file "' + @Ds_Arquivo + '"'
IF @HR = 0
EXECUTE @hr = sp_OAMethod
@objFileSystem,
'CreateTextFile',
@objTextStream OUT,
@Ds_Arquivo,
2,
True
IF @HR = 0
SELECT
@objErrorObject = @objTextStream,
@strErrorMessage = 'writing to the file "' + @Ds_Arquivo + '"'
IF @HR = 0
EXECUTE @hr = sp_OAMethod
@objTextStream,
'Write',
NULL,
@String
IF @HR = 0
SELECT
@objErrorObject = @objTextStream,
@strErrorMessage = 'closing the file "' + @Ds_Arquivo + '"'
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, '')
RAISERROR (@strErrorMessage,16,1)
END
EXECUTE sp_OADestroy
@objTextStream
EXECUTE sp_OADestroy
@objTextStream
END
Uso: EXEC dbo.stpWrite_File_V2_FSO('C:\Teste.txt', 'Prueba de escritura de archivo')
Código fuente:
CREATE PROCEDURE [dbo].[stpEscreve_Arquivo_V2_FSO] (
@String VARCHAR(MAX),
@Ds_Arquivo VARCHAR(1501)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE
@objFileSystem INT,
@objTextStream INT,
@objFolderExists INT,
@objErrorObject INT,
@strErrorMessage VARCHAR(1000),
@Folder VARCHAR(500) = REVERSE(RIGHT(REVERSE(@Ds_Arquivo), (LEN(@Ds_Arquivo) - CHARINDEX('\', REVERSE(@Ds_Arquivo), 1)) + 1)),
@hr INT
SELECT
@strErrorMessage = 'opening the File System Object'
EXECUTE @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr = 0
SELECT
@objErrorObject = @objFileSystem,
@strErrorMessage = 'Checking if the directory "' + @Folder + '" exists'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objFileSystem,
'FolderExists',
@objFolderExists OUT,
@Folder
-- Folder does not exists. Need to create it
IF (@objFolderExists = 0)
BEGIN
IF @hr = 0
SELECT
@objErrorObject = @objFileSystem,
@strErrorMessage = 'Creating folder "' + @Folder + '"'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objFileSystem,
'CreateFolder',
@objFolderExists OUT,
@Folder
END
IF @hr = 0
SELECT
@objErrorObject = @objFileSystem,
@strErrorMessage = 'Creating file "' + @Ds_Arquivo + '"'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objFileSystem,
'CreateTextFile',
@objTextStream OUT,
@Ds_Arquivo,
2,
True
IF @hr = 0
SELECT
@objErrorObject = @objTextStream,
@strErrorMessage = 'writing to the file "' + @Ds_Arquivo + '"'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objTextStream,
'Write',
NULL,
@String
IF @hr = 0
SELECT
@objErrorObject = @objTextStream,
@strErrorMessage = 'closing the file "' + @Ds_Arquivo + '"'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objTextStream,
'Close'
EXECUTE sp_OADestroy
@objFileSystem
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, '')
RAISERROR (@strErrorMessage,16,1)
END
END
Uso: EXEC dbo.stpCria_Diretorio_FSO(‘C:\Dirceu’)
Código fuente:
CREATE PROCEDURE [dbo].[stpCria_Diretorio_FSO] (
@Folder VARCHAR(500)
)
AS
BEGIN
DECLARE
@objFileSystem INT,
@objFolderExists INT,
@objErrorObject INT,
@strErrorMessage VARCHAR(1000),
@hr INT
SET NOCOUNT ON
SELECT
@strErrorMessage = 'opening the File System Object'
EXECUTE @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr = 0
SELECT
@objErrorObject = @objFileSystem,
@strErrorMessage = 'Checking if the folder "' + @Folder + '" exists'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objFileSystem,
'FolderExists',
@objFolderExists OUT,
@Folder
IF (@objFolderExists = 0)
BEGIN
IF @hr = 0
SELECT
@objErrorObject = @objFileSystem,
@strErrorMessage = 'Creating folder "' + @Folder + '"'
IF @hr = 0
EXECUTE @hr = sp_OAMethod
@objFileSystem,
'CreateFolder',
@objFolderExists OUT,
@Folder
END
EXECUTE sp_OADestroy
@objFileSystem
EXECUTE sp_OADestroy
@objFolderExists
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, '')
EXECUTE sp_OADestroy
@objErrorObject
RAISERROR (@strErrorMessage,16, 1)
END
END
Uso: EXEC CLR.dbo.stpInformacoes_Arquivo_FSO('C:\Teste.txt')
Código fuente:
CREATE PROCEDURE [dbo].stpInformacoes_Arquivo_FSO(@strArquivo VARCHAR(255))
AS
BEGIN
DECLARE
@hr INT,
@objFileSystem INT,
@objFile INT,
@ErrorObject INT,
@ErrorMessage VARCHAR(255),
@Path VARCHAR(255),--
@ShortPath VARCHAR(255),
@Type VARCHAR(100),
@DateCreated DATETIME,
@DateLastAccessed DATETIME,
@DateLastModified DATETIME,
@Attributes INT,
@size INT
SET nocount ON
SELECT
@hr = 0,
@ErrorMessage = 'opening the file system object '
EXEC @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr = 0
SELECT
@ErrorMessage = 'accessing the file ''' + @strArquivo + '''',
@ErrorObject = @objFileSystem
IF @hr = 0
EXEC @hr = sp_OAMethod
@objFileSystem,
'GetFile',
@objFile OUT,
@strArquivo
IF @hr = 0
SELECT
@ErrorMessage = 'getting the attributes of ''' + @strArquivo + '''',
@ErrorObject = @objFile
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'Path',
@Path OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'ShortPath',
@ShortPath OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'Type',
@Type OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'DateCreated',
@DateCreated OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'DateLastAccessed',
@DateLastAccessed OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'DateLastModified',
@DateLastModified OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'Attributes',
@Attributes OUT
IF @hr = 0
EXEC @hr = sp_OAGetProperty
@objFile,
'size',
@size OUT
IF @hr <> 0
BEGIN
DECLARE
@Source VARCHAR(255),
@Description VARCHAR(255),
@Helpfile VARCHAR(255),
@HelpID INT
EXECUTE sp_OAGetErrorInfo
@ErrorObject,
@Source OUTPUT,
@Description OUTPUT,
@Helpfile OUTPUT,
@HelpID OUTPUT
SELECT
@ErrorMessage = 'Error whilst ' + @ErrorMessage + ', ' + @Description
RAISERROR (@ErrorMessage,16,1)
END
EXEC sp_OADestroy
@objFileSystem
EXEC sp_OADestroy
@objFile
SELECT
[Path] = @Path,
[ShortPath] = @ShortPath,
[Type] = @Type,
[DateCreated] = @DateCreated,
[DateLastAccessed] = @DateLastAccessed,
[DateLastModified] = @DateLastModified,
[Attributes] = @Attributes,
[Size] = @size
RETURN @hr
END
Uso: EXEC CLR.dbo.stpMove_Arquivo_FSO 'C:\Teste.txt', 'C:\Arquivos\Novo_Arquivo.log', 1: se sobrescribirá si ya existe (tercer parámetro)
Código fuente:
CREATE PROCEDURE [dbo].[stpMove_Arquivo_FSO] (
@strOrigem VARCHAR(MAX),
@strDestino VARCHAR(MAX),
@sobrescrever INT = 0
)
AS
BEGIN
IF (dbo.fncArquivo_Existe(@strOrigem) = 1 AND @strOrigem != @strDestino)
BEGIN
DECLARE
@hr INT,
@objFileSystem INT,
@source VARCHAR(250),
@description VARCHAR(2000)
EXEC @hr = sp_OACreate
'Scripting.FileSystemObject',
@objFileSystem OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
RAISERROR('Object Creation Failed 0x%x, %s, %s',16,1,@hr,@source,@description)
RETURN
END
IF (dbo.fncArquivo_Existe(@strDestino) = 1)
IF (@sobrescrever = 1)
EXEC dbo.stpApaga_Arquivo_FSO @strDestino
ELSE
BEGIN
PRINT 'O arquivo de destino já existe e o parâmetro sobrescrever foi definido como NÃO'
RETURN
END
EXEC @hr = sp_OAMethod
@objFileSystem,
'CopyFile',
NULL,
@strOrigem,
@strDestino
IF (@hr <> 0)
BEGIN
EXEC sp_OAGetErrorInfo
@objFileSystem,
@source OUT,
@description OUT
EXEC sp_OADestroy
@objFileSystem
RAISERROR('Method Failed 0x%x, %s, %s',16, 1, @hr, @source, @description)
PRINT @source
PRINT @description
RETURN
END
ELSE BEGIN
EXEC dbo.stpApaga_Arquivo_FSO @strOrigem
END
EXEC sp_OADestroy
@objFileSystem
END
ELSE
PRINT 'O arquivo de origem não existe ou é igual ao arquivo de destino'
END
¿Viste lo fácil y sencillo que es? Ahora puedes jugar con archivos sin tener que preocuparte por crear funciones y procedimientos almacenados usando C# y compilar la base de datos CLR (Si quieres usar el CLR para manipular archivos en lugar de OLE Automation, QUE TE RECOMIENDO, accede al post Cómo enumerar, leer, escribir, copiar y mover archivos con CLR (C#)).
Como beneficio adicional, les daré otro procedimiento almacenado, que tiene la función de, utilizando una ruta de archivo, separar el directorio y el archivo en dos variables distintas:
stpFile_Separates_Name_Directorio:
USE [CLR]
GO
CREATE PROCEDURE [dbo].[stpArquivo_Separa_Nome_Diretorio] (@strArquivo VARCHAR(1000), @str_DIR VARCHAR(500) OUT, @str_FILE VARCHAR(500) OUT)
AS
BEGIN
SET NOCOUNT ON
SELECT
@str_DIR = REVERSE(RIGHT(REVERSE(@strArquivo), (LEN(@strArquivo) - CHARINDEX('\', REVERSE(@strArquivo), 1)) + 1))
SELECT
@str_FILE = REVERSE(LEFT(REVERSE(@strArquivo), CHARINDEX('\', REVERSE(@strArquivo), 1) - 1))
END
Cómo utilizar:
DECLARE
@str_DIR VARCHAR(500),
@str_FILE VARCHAR(500)
EXEC CLR.dbo.stpArquivo_Separa_Nome_Diretorio
@strArquivo = '\\servidor\Pasta 1\Diretorio 2\Arquivos\Nome do Arquivo - 20140614.xlsx', -- varchar(1000)
@str_DIR = @str_DIR OUTPUT, -- varchar(500)
@str_FILE = @str_FILE OUTPUT -- varchar(500)
PRINT @str_DIR -- Vai imprimir na tela "\\servidor\Pasta 1\Diretorio 2\Arquivos\"
PRINT @str_FILE -- Vai imprimir na tela "Nome do Arquivo - 20140614.xlsx"
¡Eso es todo amigos!
Hasta el próximo post.
Dirceu Resende
Arquitecto de Bases de Datos y BI · Microsoft MVP · MCSE, MCSA, MCT, MTA, MCP.
Comentários (0)
Carregando comentários…