Hey guys!
In this post I would like to share some solutions on how to compress and decompress files and directories using SQL Server. This is especially useful for creating ETL routines where you need to use these resources using T-SQL scripts or even to compress backup files generated in the Express version (which does not support compressed backups).
If you are interested in file processing by SQL Server, see some more posts on this subject:
– SQL Server – File operations using xp_cmdshell (How to list, read, write, copy, delete and move files)
– How to compress directories into ZIP files using 7zip and CMD
– SQL Server – How to export database data to text file (CLR, OLE, BCP)
– SQL Server – How to import text files into the database (OLE Automation, CLR, BCP, BULK INSERT, OPENROWSET)
– SQL Server – How to list, read, write, copy, delete and move files with the CLR (C#)
– File operations using OLE Automation in SQL Server
– SQL Server – How to export and import files with tabular data (Ex: CSV) using the CLR (C#)
– Importing CSV files into SQL Server database
– SQL Server – How to integrate with FTP and list, upload and download files using the CLR (C#)
As in some alternatives I will use 7-zip, you can further customize the examples mentioned here by consulting the official binary documentation, very complete and exemplified.
Alternative #1: Using 7-zip and xp_cmdshell
View contentTo activate xp_cmdshell, simply run the command below:
sp_configure 'advanced options', 1
RECONFIGURE
GO
sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO
Prerequisite: 7-zip
To be able to use this feature, you will need to download the 7-zip binaries in this link. You will need to download the “7-Zip Extra” version: standalone console version, 7z DLL, Plugin for Far Manager”, which comes in .7z format.
If you do not want to install 7-zip in your environment to be able to open this file, I will make the files related to the standalone console version (version 18.05) below:
x64 version (recommended) | x86 version
After downloading the files, unzip them to a directory of your choice. For the examples in this article, I chose the “C:\Binn\” directory.
How to compress files and directories
To compress files and directories using 7-zip and xp_cmdshell, you can use the Stored Procedure below, which will make it easier to use on a daily basis.
USE [dirceuresende]
GO
CREATE PROCEDURE dbo.stpCompacta_Arquivo (
@caminho VARCHAR(500),
@filtro VARCHAR(500),
@arquivoCompactado VARCHAR(500),
@nivelCompactacao INT = 5,
@recursivo BIT = 0,
@senha VARCHAR(100) = NULL
)
AS
BEGIN
DECLARE @caminhoBinario VARCHAR(255) = 'C:\Binn\7za.exe'
DECLARE @argumentos VARCHAR(MAX) = 'a -tzip -mx' + CAST(@nivelCompactacao AS VARCHAR(2)) + ' "' + @arquivoCompactado + '"' + (CASE WHEN @recursivo = 1 THEN ' -r' ELSE '' END) + (CASE WHEN NULLIF(LTRIM(RTRIM(@senha)), '') IS NOT NULL THEN ' -p' + @senha ELSE '' END) + ' "' + @caminho + '\' + @filtro + '" -mmt';
DECLARE @Comando VARCHAR(8000) = 'call "' + @caminhoBinario + '" ' + @argumentos
-- PRINT @Comando
EXEC xp_cmdshell @Comando
END
Usage example
In this example, I will demonstrate how to compress all files and subdirectories in the “C:\Temporary\” directory, and saving them in the “C:\Test\Arquivo.zip” file, with a medium compression level (5):
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario\', -- varchar(500)
@filtro = '*', -- varchar(500)
@arquivoCompactado = 'C:\Teste\Arquivo.zip', -- varchar(500)
@nivelCompactacao = 5, -- int
@recursivo = 1 -- bit
Other examples:
-- Modo básico
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario', -- varchar(500)
@filtro = '*.txt', -- varchar(500)
@arquivoCompactado = 'C:\Teste\Arquivo.zip' -- varchar(500)
-- Compactando todos os arquivos que comecem com Teste%
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario', -- varchar(500)
@filtro = 'Teste*', -- varchar(500)
@arquivoCompactado = 'C:\Teste\Arquivo.zip' -- varchar(500)
-- Compactando o arquivo "Teste.txt"
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario', -- varchar(500)
@filtro = 'Teste.txt', -- varchar(500)
@arquivoCompactado = 'C:\Teste\Arquivo.zip' -- varchar(500)
/*
Compacta todos os arquivos com extensão .txt no diretório "C:\Temporario" (apenas na raiz, sem sub-diretórios),
usando compactação máxima (9) e protegendo o arquivo com a senha "dirceu"
*/
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario', -- varchar(500)
@filtro = '*.txt', -- varchar(500)
@arquivoCompactado = 'C:\Teste\Arquivo.zip', -- varchar(500)
@nivelCompactacao = 9, -- int
@recursivo = 0, -- bit
@senha = 'dirceu' -- varchar(100)
How to unzip files and directories
Using the Stored Procedure below, we can easily unzip files (with and without password) into some directory as per our need. It is worth mentioning that, if the destination directory does not exist, it will be created.
USE [dirceuresende]
GO
CREATE PROCEDURE dbo.stpDescompacta_Arquivo (
@arquivoCompactado VARCHAR(500),
@pastaDestino VARCHAR(500),
@filtro VARCHAR(500) = NULL,
@senha VARCHAR(100) = NULL
)
AS
BEGIN
DECLARE @caminhoBinario VARCHAR(255) = 'C:\Binn\7za.exe'
DECLARE @argumentos VARCHAR(MAX) = 'x "' + @arquivoCompactado + '" -aoa -o"' + @pastaDestino + '" ' + ISNULL(@filtro, '') + '' + (CASE WHEN NULLIF(LTRIM(RTRIM(@senha)), '') IS NOT NULL THEN ' -p' + @senha ELSE '' END) + ' -r -mmt';
DECLARE @Comando VARCHAR(8000) = 'call "' + @caminhoBinario + '" ' + @argumentos
PRINT @Comando
EXEC xp_cmdshell @Comando
END
Usage examples:
-- Exemplo básico
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = 'C:\Teste\Arquivo.zip', -- varchar(500)
@pastaDestino = 'C:\Teste 2\'
-- Descompactando arquivos com senha
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = 'C:\Teste\Arquivo.zip', -- varchar(500)
@pastaDestino = 'C:\Teste 2\', -- varchar(100)
@senha = 'dirceu' -- varchar(100)
-- Descompactando apenas arquivos com extensão .txt
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = 'C:\Teste\Arquivo.zip', -- varchar(500)
@pastaDestino = 'C:\Teste 2\', -- varchar(100)
@filtro = '*.txt' -- varchar(100)
-- Descompactando apenas o arquivo "Teste.txt"
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = 'C:\Teste\Arquivo.zip', -- varchar(500)
@pastaDestino = 'C:\Teste 2\', -- varchar(100)
@filtro = 'Teste.txt' -- varchar(100)
Alternative #2: Using 7-zip and SQLCLR (C#)
View contentIf you don't know or don't know what SQLCLR is, find out more by accessing the post Introduction to SQL CLR (Common Language Runtime) in SQL Server.
Prerequisite: 7-zip
To be able to use this feature, you will need to download the 7-zip binaries in this link. You will need to download the “7-Zip Extra” version: standalone console version, 7z DLL, Plugin for Far Manager”, which comes in .7z format.
If you do not want to install 7-zip in your environment to be able to open this file, I will make the files related to the standalone console version (version 18.05) below:
x64 version (recommended) | x86 version
After downloading the files, unzip them to a directory of your choice. For the examples in this article, I chose the “C:\Binn\” directory.
Solution source code
Below, I will provide the source code of the compression solution using 7-zip and SQLCLR.
Retorno.cs Class (Display alert and error messages)
using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
namespace Bibliotecas.Model
{
public static class Retorno
{
public static void Erro(string erro)
{
Mensagem(erro);
throw new ApplicationException(erro);
}
public static void Mensagem(string mensagem)
{
using (var conexao = new SqlConnection("context connection=true"))
{
conexao.Open();
using (var comando = new SqlCommand("IF ( (512 & @@OPTIONS) = 512 ) select 1 else select 0", conexao))
{
if ((int)comando.ExecuteScalar() != 0) return;
}
var retorno = SqlContext.Pipe;
retorno?.Send(mensagem.Length > 4000 ? mensagem.Substring(0, 4000) : mensagem);
}
}
public static void RetornaReader(SqlDataReader dataReader)
{
var retorno = SqlContext.Pipe;
retorno?.Send(dataReader);
}
}
public class Ret : Exception
{
public Ret(string str) : base(str)
{
}
}
}
stpCompacta_File.cs
using System;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using System.Diagnostics;
using Bibliotecas.Model;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpCompacta_Arquivo(SqlString caminho, SqlString filtro, SqlString arquivoCompactado, SqlInt32 nivelCompactacao, SqlString senha)
{
string[] arquivos;
#region tratamento de entradas
if (nivelCompactacao.Value < 0 || nivelCompactacao.Value > 9)
{
Retorno.Erro("Parametro inválido na variavel nivelCompactacao, use de 0 a 9 para compactar, sendo 9 o nivel mais alto (5 recomendado).");
return;
}
try
{
if (!Directory.Exists(caminho.Value))
{
Retorno.Erro($"O caminho especificado '{arquivoCompactado}' não existe ou está inacessivel.");
return;
}
}
catch
{
Retorno.Erro($"Erro ao converter caminho especificado ('{arquivoCompactado}').");
return;
}
try
{
arquivos = Directory.GetFiles(caminho.Value, filtro.Value);
}
catch
{
Retorno.Erro($"Erro ao listar arquivos no caminho especificado ({arquivoCompactado}).");
return;
}
var objetoArquivoCompactado = new FileInfo(arquivoCompactado.Value);
var diretorioArquivoCompactado = objetoArquivoCompactado.Directory?.ToString();
if (diretorioArquivoCompactado == null || !Directory.Exists(diretorioArquivoCompactado))
{
Retorno.Erro($"O caminho do arquivo compactado especificado ({diretorioArquivoCompactado}) não existe ou inacessível.");
return;
}
if (objetoArquivoCompactado.Extension.Trim() != "")
{
try
{
objetoArquivoCompactado.Delete();
}
catch
{
Retorno.Erro($"o arquivo compactado especificado ({arquivoCompactado.Value}) está sendo usado.");
return;
}
}
else
{
Retorno.Erro($"O arquivo compactado especificado não possui uma extensão válida ({objetoArquivoCompactado.Extension.Trim()}).");
return;
}
#endregion
try
{
var argumentos = $@" a -tzip -mx{nivelCompactacao.Value} ""{arquivoCompactado.Value}""" + (!senha.IsNull && !string.IsNullOrEmpty(senha.Value) ? $" -p{senha.Value} " : " ") + $@"""{caminho.Value}\{filtro.Value}"" -mmt";
using (var scriptProc = new Process { StartInfo = { FileName = @"C:\Binn\7za.exe", UseShellExecute = false, Arguments = argumentos, RedirectStandardOutput = true, RedirectStandardError = true, StandardOutputEncoding = Encoding.GetEncoding(850), StandardErrorEncoding = Encoding.GetEncoding(850), CreateNoWindow = true } })
{
scriptProc.Start();
var output = scriptProc.StandardOutput.ReadToEnd();
var erro = scriptProc.StandardError.ReadToEnd();
if (output.Length > 0)
{
//Retorno.Mensagem(output);
}
if (erro.Length > 0)
{
Retorno.Erro(erro);
}
}
var quantidadeArquivos = arquivos.Length;
Retorno.Mensagem("Total de: (" + quantidadeArquivos + ") arquivos foram compactados em: " + arquivoCompactado.Value);
}
catch (Exception e)
{
Retorno.Erro("Erro : " + e.Message);
}
}
};
Alternative #3: Using SharpZipLib and SQLCLR (C#)
View contentIf you don't know or don't know what SQLCLR is, find out more by accessing the post Introduction to SQL CLR (Common Language Runtime) in SQL Server.
As the SharpZipLib library is quite large, it ends up being unfeasible to make all the source code available here in the post, as well as the T-SQL version. For this reason, I will provide links to download the source code files.
The complete Visual Studio solution, where you can edit the code freely, is available available at this link.
In this link here I am making the T-SQL source code available, to allow the creation of objects without having to install or open Visual Studio.
To better understand the @filtro parameter of this solution, since it is different from the previous alternatives (which use 7-zip), I recommend reading the official library documentation.
How to compress files and directories
-- Exemplo básico
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario\',
@filtro = '*',
@arquivoCompactado = 'C:\Teste\Arquivo.zip',
@nivelCompactacao = 5,
@senha = ''
-- Compactando arquivos com extensão .txt e utilizando compactação máxima (9)
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario\',
@filtro = '*',
@arquivoCompactado = 'C:\Teste\Arquivo.zip',
@nivelCompactacao = 9,
@senha = ''
-- Compactando arquivos e protegendo-os com senha
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario\',
@filtro = '*',
@arquivoCompactado = 'C:\Teste\Arquivo.zip',
@nivelCompactacao = 5,
@senha = 'dirceu'
-- Compactando apenas o arquivo "Teste 1.txt"
EXEC dbo.stpCompacta_Arquivo
@caminho = 'C:\Temporario\',
@filtro = 'Teste 1.txt',
@arquivoCompactado = 'C:\Teste\Arquivo.zip',
@nivelCompactacao = 5,
@senha = ''
How to unzip files and directories
-- Exemplo básico
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = N'C:\Teste\Arquivo.zip', -- nvarchar(max)
@pastaDestino = N'C:\Teste\', -- nvarchar(max)
@filtro = N'', -- nvarchar(max)
@senha = N'' -- nvarchar(max)
-- Descompactando arquivos com senha
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = N'C:\Teste\Arquivo.zip', -- nvarchar(max)
@pastaDestino = N'C:\Teste\', -- nvarchar(max)
@filtro = N'', -- nvarchar(max)
@senha = N'dirceu' -- nvarchar(max)
-- Descompactando apenas arquivos com extensão .txt
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = N'C:\Teste\Arquivo.zip', -- nvarchar(max)
@pastaDestino = N'C:\Teste\', -- nvarchar(max)
@filtro = N'.txt', -- nvarchar(max)
@senha = N'' -- nvarchar(max)
-- Descompactando arquivos que começam com "Teste%"
EXEC dbo.stpDescompacta_Arquivo
@arquivoCompactado = N'C:\Teste\Arquivo.zip', -- nvarchar(max)
@pastaDestino = N'C:\Teste\', -- nvarchar(max)
@filtro = N'Teste*', -- nvarchar(max)
@senha = N'' -- nvarchar(max)
That's it, folks!
I hope you liked this post, hugs and see you next time!
Dirceu Resende
Database & BI Architect · Microsoft MVP · MCSE, MCSA, MCT, MTA, MCP.


Comentários (0)
Carregando comentários…