Olá pessoal,
Boa tarde!

Neste post, vou seguir a dica de um leitor e utilizar a excelente API gratuita do site Calendario.com.br para retornar a listagem de feriados nacionais, estaduais, municipais e facultativos do Brasil, permitindo filtrar por ano, estado e/ou cidade. Eu já havia comentado sobre este assunto no post Como criar uma tabela com os feriados (nacionais, estaduais e móveis) no SQL Server, mas acho que esse post vai trazer mais uma forma de se realizar essa tarefa.

Acredito que a solução deste post é mais completa que a do meu post anterior de feriados, por ter até os feriados municipais e facultativos. Entretanto, cada consulta gera uma requisição HTTP, o que aplicado para uma lista grande de cidades/anos, poderia demorar vários segundos, enquanto a solução do outro post já calcula e armazena todos os dados em uma tabela, o que não impede que isso seja feito também com a solução via API.

Para saber mais sobre o recurso OLE Automation, clique neste link.

Utilizando OLE Automation

A forma mais rápida de implementar isso, é utilizando o objeto MSXML2.ServerXMLHTTP do OLE Automation, que permite realizar requisições XML através do protocolo HTTP.

Como já havia comentado em outros posts, por motivos de segurança e estabilidade do ambiente, NÃO recomendo a ativação e utilização do recurso OLE Automation, mas quis demonstrar aqui uma solução de como utilizar esse poderoso, mas perigoso, recurso do banco de dados.

Visualizar código-fonte
CREATE PROCEDURE dbo.stpConsulta_Feriado (
    @Ds_Token VARCHAR(100),
    @Nr_Ano INT,
    @Ds_Cidade VARCHAR(50),
    @Sg_UF VARCHAR(2) = 'ES'
)
AS BEGIN


    DECLARE 
        @obj INT,
        @Url VARCHAR(8000),
        @xml XML,
        @resposta VARCHAR(MAX)
        
 
    IF (OBJECT_ID('tempdb..#xml') IS NOT NULL) DROP TABLE #xml
    CREATE TABLE #xml ( 
        Ds_Dados VARCHAR(MAX)
    )
    
 
    SET @Url = 'http://www.calendario.com.br/api/api_feriados.php?token=' + @Ds_Token + '&ano=' + CAST(@Nr_Ano AS VARCHAR(4))
 
    IF (NULLIF(LTRIM(RTRIM(@Sg_UF)), '') IS NOT NULL)
        SET @Url += '&estado=' + @Sg_UF


    IF (NULLIF(LTRIM(RTRIM(@Ds_Cidade)), '') IS NOT NULL)
        SET @Url += '&cidade=' + @Ds_Cidade

    
    EXEC sys.sp_OACreate @progid = 'MSXML2.ServerXMLHTTP', @objecttoken = @obj OUT, @context = 1
    EXEC sys.sp_OAMethod @obj, 'open', NULL, 'GET', @Url, false
    EXEC sys.sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
    EXEC sys.sp_OAMethod @obj, 'send'
 
 
    INSERT INTO #xml(Ds_Dados)
    EXEC sys.sp_OAGetProperty @obj, 'responseText' --, @resposta OUT
    
    
    EXEC sys.sp_OADestroy @obj
 
 
    SELECT TOP 1 @resposta = Ds_Dados FROM #xml
    SET @xml = @resposta COLLATE SQL_Latin1_General_CP1251_CS_AS

    SELECT
        eventos.linha.value('date[1]','varchar(100)') AS [Data],
        eventos.linha.value('name[1]','varchar(100)') AS Nome,
        eventos.linha.value('type[1]','varchar(30)') AS Tipo,
        eventos.linha.value('type_code[1]','int') AS Codigo_Tipo,
        eventos.linha.value('link[1]','varchar(100)') AS Link
    FROM   
        @xml.nodes('//events/event') eventos(linha)
    

END

Exemplo de uso:

sql-server-como-gerar-uma-tabela-de-feriados-nacionais-municipais-estaduais-com-api-ole-automation
sql-server-como-gerar-uma-tabela-de-feriados-nacionais-municipais-estaduais-com-api-ole-automation

Utilizando o SQL CLR (C#)

Já velho conhecido aqui das postagens do blog, o CLR permite utilizar código C# ou VB.NET do .NET Framework dentro do banco de dados SQL Server, e assim, obter novos recursos e estender a capacidade do banco de dados.

Se você não conhece o CLR, ou não sabe como funciona e o que é, acesse este link.

Visualizar código-fonte
using System.Collections;
using System.Data.SqlTypes;
using System.IO;
using System.Net;
using System.Text;
using System.Xml;
using Bibliotecas.Model;
using System;

public partial class UserDefinedFunctions
{

    private class ConsultaFeriado
    {

        public SqlDateTime Date;
        public SqlString Name;
        public SqlString Type;
        public SqlInt32 Type_Code;
        public SqlString Link;

        public ConsultaFeriado(SqlDateTime date, SqlString name, SqlString type, SqlInt32 typeCode, SqlString link)
        {

            Date = date;
            Name = name;
            Type = type;
            Type_Code = typeCode;
            Link = link;

        }

    }
    
    [Microsoft.SqlServer.Server.SqlFunction(
        FillRowMethodName = "FillRow_ConsultaFeriado",
        TableDefinition = "Dt_Feriado DATETIME, Ds_Nome NVARCHAR(100), Ds_Tipo NVARCHAR(50), Nr_Tipo INT, Ds_Link NVARCHAR(500)"
    )]
    public static IEnumerable fncFeriados(int Ano, string Sg_UF, string Ds_Cidade)
    {

        var consultaFeriadoCollection = new ArrayList();

        if (Ano < 1900 || Ano > 2099)
            return consultaFeriadoCollection;


        // Gere o seu token no endereço: http://www.calendario.com.br/api_feriados_municipais_estaduais_nacionais.php
        var token = "";
        var parametros = "?token=" + token + "&ano=" + Ano;

        if (!string.IsNullOrEmpty(Sg_UF))
            parametros += "&estado=" + Sg_UF;

        if (!string.IsNullOrEmpty(Ds_Cidade))
            parametros += "&cidade=" + Ds_Cidade;


        var request = (HttpWebRequest)WebRequest.Create("http://www.calendario.com.br/api/api_feriados.php" + parametros);
        //request.Proxy = new WebProxy(Servidor.Ds_Proxy_Url, Servidor.Ds_Proxy_Porta) { Credentials = new NetworkCredential(Servidor.Ds_Proxy_Usuario, Servidor.Ds_Proxy_Senha, Servidor.Ds_Proxy_Dominio) };

        request.Method = "GET";
        request.UserAgent = "curl/7.45.0";
        request.ContentType = "application/x-www-form-urlencoded";


        using (var response = (HttpWebResponse)request.GetResponse())
        {
            using (var stream = response.GetResponseStream())
            {

                if (stream == null) return consultaFeriadoCollection;

                using (var streamReader = new StreamReader(stream, Encoding.GetEncoding("UTF-8")))
                {

                    var resposta = streamReader.ReadToEnd();

                    var xml = new XmlDocument();
                    xml.LoadXml(resposta);

                    var root = xml.DocumentElement;
                    var nodes = root?.SelectNodes("/events/event");

                    if (nodes == null) return consultaFeriadoCollection;

                    foreach (XmlNode node in nodes)
                    {

                        if (node != null)
                        {

                            consultaFeriadoCollection.Add(new ConsultaFeriado(
                                (string.IsNullOrEmpty(node["date"]?.InnerText)) ? SqlDateTime.Null : Convert.ToDateTime(node["date"].InnerText),
                                node["name"]?.InnerText,
                                node["type"]?.InnerText,
                                int.Parse(node["type_code"]?.InnerText),
                                node["link"]?.InnerText
                            ));

                        }
                        
                    }
                }
            }
        }


        return consultaFeriadoCollection;

    }

    protected static void FillRow_ConsultaFeriado(object objConsultaFeriado, out SqlDateTime date, out SqlString name, out SqlString type, out SqlInt32 typeCode, out SqlString link)
    {

        var consultaFeriado = (ConsultaFeriado)objConsultaFeriado;

        date = consultaFeriado.Date;
        name = consultaFeriado.Name;
        type = consultaFeriado.Type;
        typeCode = consultaFeriado.Type_Code;
        link = consultaFeriado.Link;

    }

}

sql-server-como-listar-os-feriados-nacionais-estaduais-e-municipais-no-clr
sql-server-como-listar-os-feriados-nacionais-estaduais-e-municipais-no-clr

É isso aí, pessoal!
Obrigado pela visita, espero que tenham gostado e até o próximo post.