Tag: MS SQL

  • UUID (GUID), facilitar o índice de SGBDs

    Os SGBDs, como MySQL, MSSQL, PostgreSQL, possuem em seus recursos criadores automáticos de identificação de registros. As mais comuns são o auto incremento e o uso de UUID ou GUID, tema desse artigo.

    O UUID é uma sigla que significa ou representa o universally unique identifier, ou identificador único universal. Também é aceita a sigla GUID, globally unique identifier ou identificador único global.

    O objetivo desse identificador é oferecer exclusividade de identificação, algo como em lugar nenhum no mundo haverá um identificador igual, mesmo sem estar ligado a qualquer rede de coordenação ou controle. Claro que literalmente isso é impossível, não há como garantir essa exclusividade, mas pelos cálculos de probabilidade, podemos considerar como um método seguro de identificação. Para definição exata desse identificador, podemos usar “identificador praticamente único”.

    Para este artigo, eu me concentro não na forma de criação desses identificadores pelos seus SGBDs, mas na forma como são ordenados. Ao passo que para todos os SGBDs a ordenação de registros baseados em identificadores de auto incremento seja lógica, padronizada, do menor ao maior ou vice-versa, a ordenação de registros baseados em UUID não tem um padrão. Cada gerenciador de banco de dados criou seu padrão de ordenação, que poderá ser em ordem alfabética, binária, numérica, por data, por bytes significativos, …. Cada SGBD usa seu próprio sistema de ordenação. Isso acaba sendo um ponto a ser levado em conta quando você trabalha com sistemas ou bibliotecas adaptáveis, ou que usam bancos diferentes na mesma aplicação.

    A seguir, eu proponho uma abordagem de criação de UUID de acordo com a ordenação dos SGBDs MySQL e MSSQL. Essa abordagem permite que a ordenação dos registros seja mais eficiente, independente de qual banco eu esteja acessando.

    using System;
    using System.Security.Cryptography;
    namespace Yordi.Ferramentas
    {
        public enum TipoGuid
        {
            /// 
            /// Ordem alfabética
            /// 
            MySQL,
            /// 
            /// Ordem binária
            /// 
            Oracle,
            /// 
            /// Ordem baseada nos últimos 6 bytes (12 posições)
            /// 
            MSSQL
        }
    
        public static class NewGuid
        {
            private static TipoGuid _seq = TipoGuid.MSSQL;
            private static readonly RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider();
    
            public static TipoGuid TipoGuid { set { _seq = value; } }
    
            public static Guid NewSequentialGuid()
            {
                byte[] randomBytes = new byte[10];
                _rng.GetBytes(randomBytes);
    
                long timestamp = DateTime.UtcNow.Ticks / 10000L;
                byte[] timestampBytes = BitConverter.GetBytes(timestamp);
    
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(timestampBytes);
                }
    
                byte[] guidBytes = new byte[16];
    
                switch (_seq)
                {
                    case TipoGuid.MySQL:
                    case TipoGuid.Oracle:
                        Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6);
                        Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10);
    
                        // Se o formato for string, reverter a ordem
                        // Se usa o sistema de extremidade...
                        if (_seq == TipoGuid.MySQL && BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(guidBytes, 0, 4);
                            Array.Reverse(guidBytes, 4, 2);
                        }
                        break;
    
                    case TipoGuid.MSSQL:
                        Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10);
                        Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6);
                        break;
                }
                return new Guid(guidBytes);
            }
        }
    }
    

    Segundo os documentos da Microsoft, “computadores diferentes usam diferentes convenções para ordenar os bytes dentro de valores inteiros multibyte.” Exemplo, alguns SGBDs ‘colocam o byte mais significativo primeiro (conhecido como ordem big-endian) e outros colocam o byte menos significativo primeiro (conhecido como ordem little endian)’.

    Para trabalhar com esses SGBDs (MySQL e MSSQL), que usam ordenação de bytes diferentes, acabei eu mesmo gerando o UUID, mas levando em conta a forma de ordenação.

    Eu uso essa abordagem numa classe base de inserção, onde não importa o SGBD que esteja sendo usado no momento. Veja esse código:

    private  int Insert(T obj) // onde T é uma classe
    {
        string sql = InsertWithParameters(obj); // Método com reflection para construir o INSERT em TSQL
        bool isAuto = false;
        Guid guid = Guid.Empty;
        int resultado = 0;
        List colunas = Campos(obj); // Método para 'converter' propriedades das classes em colunas de tabela
        //Conexão genérica, que se conecta tanto a MSSQL quanto a MySQL (também aceita outros)
        using (DbConnection conexaoSql = Conexao.ObterConexao())
        {
            DbCommand cmm = conexaoSql.CreateCommand();
            foreach (var c in colunas)
            {
                //Se não for autoincremento carrega o valor enviado pelo cliente
                if (!c.IsAutoIncrement)
                    cmm.Parameters.Add(CriaParameter(cmm, c)); // Resumo de CriaParameter: WithValue($"@{c.Nome}", c.Valor);
                //Se for autoincremento, mas do tipo GUID, carrega com valor próprio, 
                // de acordo com o banco usado. 
                else if (c.Tipo == Tipo.GUID)
                {
                    guid = NewGuid.NewSequentialGuid(); // <- Este é o foco desse artigo.
                    c.Valor = guid;
                    cmm.Parameters.Add(CriaParameter(cmm, c)); // WithValue($"@{c.Nome}", c.Valor);
                }
                //Se for auto incremento convencional (de números), usa o do banco
                else
                    isAuto = true;
            }
            try
            {
                if (isAuto)
                {
                    var undefined = cmm.ExecuteScalar();
                    int.TryParse(undefined.ToString(), out resultado);
                }
                else
                    resultado = cmm.ExecuteNonQuery();
    
                if (guid != Guid.Empty)
                    _msg = guid.ToString();
                else
                    _msg = $"Retorno: {resultado}";
            }
            catch (Exception e)
            {
                _msg = e.Message; // Cuidado com esse retorno!
            }
            return resultado;
        }
    }
    

  • Sebrae SP

    Segundo o próprio site, o Serviço Brasileiro de Apoio às Micro e Pequenas Empresas (Sebrae) é uma entidade privada que promove a competitividade e o desenvolvimento sustentável dos empreendimentos de micro e pequeno porte – aqueles com faturamento bruto anual de até R$ 3,6 milhões.

    O Sebrae é uma instituição privada a serviço do governo federal para auxiliar as micro, pequenas e médias empresas. Para receber os recursos do governo, há regras que precisam ser atendidas, dentre elas, quantidade de atendimentos e a qualidade deles.

    Para continuar com a sua excelência em serviços, foi criado um complexo sistema que possibilita medir com rapidez a Quantidade e a Qualidade dos seus serviços.

    Eu participei do desenvolvimento do sistema para medir a qualidade. Em resumo, trava-se de pesquisa por telefone a uma representativa amostra de todos os clientes (empreendedores, como gosta de chamar o Sebrae). Dependendo do setor de atuação destes empreendedores, havia perguntas específicas que serviam para classificar a qualidade do atendimento e descobrir as suas necessidades ou dificuldades.

    À medida que o sistema era construído e colocado em prática, percebeu-se o potencial de usá-lo como ‘fiscal’. Afinal, se a qualidade não estava boa ou o empreendedor nem foi atendido, era possível descobrir o porquê.

    No fim, o projeto que teve a minha participação por um ano, virou um gigantesco e complexo sistema de informações das mais variadas, com centenas de relatórios com milhares de páginas, com milhares de gravações de áudio, apresentados a cada mês, a cada trimestre, a cada semestre, e um relatório final, anual.

    Graças aos sistemas desenvolvidos, a empresa prestadora de serviços (Mark Sistemas e Peskize) manteve custos baixos, teve dinâmica e qualidade na apresentação de todos os materiais (relatórios, apresentações, gravações, estudos estatísticos), e visualização simples de cada etapa do processo.

    A seguir, descrevo, de forma resumida, que recursos foram usados. Percebam que foram recursos grátis ou de baixo custo ou ainda reutilização de recursos já disponíveis na empresa, como o pacote Office da Microsoft.

    1. VOiP em VBA.
    2. Gravação de áudio em VBA.
    3. Sorteio da Amostra (tinha regra pra caramba nesse sorteio) em VBA
    4. Sistema para CATI (vulgo ‘pesquisa por telefone’) em MS ACCESS (é o mais rápido para se construir um sistema de coleta).
    5. Banco em MS SQL 2012 Express. Para o tanto de registros que havia, o MS ACCESS não era capaz de lidar. Embora na documentação dele diga que ele lida com arquivos no tamanho máximo de 2GB, na prática, ele começa a travar com 1GB. Tínhamos a opção de trabalhar com o MySQL ou MS SQL Express. Devido à facilidade de comunicação entre produtos das Microsoft, optou-se pelo  MS SQL.
    6. Um sistema também em MS ACCESS para as conferências das entrevistas. Isso era necessário para garantir a qualidade da entrevista. Alguns auditavam os entrevistadores por ouvirem algumas gravações. O sistema selecionava pesquisas realizadas, apresentava as respostas marcadas pelo entrevistador, e apresentava todos os áudios relacionados à entrevista, para acompanhamento do auditor.
    7. Para os analistas e gerentes dos diversos setores do projeto, havia um sistema de controle de cotas, audições, checagens, verificações, codificação de respostas abertas.
    8. Para análise da informação, o sistema permitia exportar os resultados em diversos formatos (Excel, SPSS).
    9. Sistema de sintaxes em SPSS (Software de estatística IBM) para análises e cálculos, segundo metodologia proposta pelo cliente.
    10. Sistema para separação de áudios segundo as suas ocorrências, após finalização de conferência e validação.

    Enfim, foi um projeto exaustivo, mas ao mesmo tempo gratificante, pois trouxe um resultado bem satisfatório para o cliente final (Sebrae SP), meu cliente (a empresa Mark Sistemas), e a mim, por ter aprendido diversas coisas que não fazia ideia, como o SPSS (estatística e suas visões), VBA, áudio e VOiP.