SQL Server: Criando e lendo arquivos XMLs – Parte 2

Boas galera!

Na primeira parte desse artigo vimos uma forma de criarmos um arquivo XML por meio de uma consulta no Banco. Agora vamos aprender como lemos esse arquivo que está no disco e transformarmos o XML em uma tabela física.

Abrindo o arquivo e transformando-o em tabela

Para carregar o arquivo que acabamos de criar vamos utilizar a cláusula OPENROWSET junto com a clausula BULK. Vejam o comando abaixo:

SELECT CONVERT(XML, BULKCOLUMN, 2)
     FROM OPENROWSET (BULK 'C:\TMP_LOGCLIENTE.XML' , SINGLE_BLOB) AS XMLDATA

Dessa maneira conseguimos pegar o conteúdo do arquivo e armazenarmos numa variável por exemplo. Porém, precisamos transformar esse XML em um estrutura de dados que podemos navegar (para quem lembra da faculdade, vamos transformá-la em uma árvore rsrs). Para isso utilizamos a sp_xml_preparedocument. Com o XML já navegável, podemos interpretá-lo e transformá-lo em uma tabela, utilizando a função OPENXML. Nosso script fica assim:

-- Variaveis
DECLARE @documento XML
DECLARE @handler INT

-- Lendo o arquivo
SET @documento = (SELECT CONVERT(XML, BULKCOLUMN, 2)
                    FROM OPENROWSET (BULK 'C:\TMP_LOGCLIENTE.XML' , SINGLE_BLOB) AS XMLDATA)

-- Transformando em uma estrutura de árvore
exec sp_xml_preparedocument @handler OUTPUT, @documento

-- Interpretando a estrutura e transformando-a em tabela
-- Armazenando o resultado em TMP_LOG_CLI
SELECT *
  INTO TMP_LOG_CLI
  FROM OPENXML (@handler, 'LOGCLI/LOGCLIENTES', 3)
  WITH (
          SEQUENCIALOG    NUMERIC(10) 'SEQUENCIALOG',
          CODIGOREGISTRO  NUMERIC(10) 'CODIGOREGISTRO',
          DESCRICAOERRO   VARCHAR(1000) 'DESCRICAOERRO'
        )

-- Removendo a estrutura
EXEC sp_xml_removedocument @handler

-- Consultando a tabela TMP_LOG_CLI
SELECT * FROM TMP_LOG_CLI

E pronto, temos os dados do arquivo em uma nova tabela.

Espero que tenham gostado e até a próxima!

Anúncios

SQL Server: Criando e lendo arquivos XMLs – Parte 1

Fala Pessoal!

Havia comentado aqui algumas maneiras de resolvermos a falta do suporte as Transações Autonomas do SQL Server nas versões 2008 e anteriores. Como primeira alternativa para esse problema, havia dito que podíamos criar um arquivo temporário e, depois de ter executado o Rollback, lermos ele e inserirmos os dados novamente da tabela de Log. O intuito desse post é mostrar como podemos fazer isso na prática.

Nesse exemplo nós utilizaremos arquivos XML para isso, porém nada impede de utilizarmos outros tipos (como txt ou csv). A vantagem de usarmos o XML é que a estrutura de sua linguagem acaba representando muito fielmente a tabela, e temos também algumas funcionalidades adicionais no SQL Server que podemos usar com esse tipo de dado.

Então resumindo, nesse de post vamos ver:

– Como extrair um XML a partir de uma consulta;
– Como criar arquivos utilizando esse XML extraído;
– Como ler o arquivo que acabamos de criar;
– Como transformar o XML do arquivo em tabela.

Para o exemplo, vou utilizar a mesma tabela de Log do artigo anterior. Segue o script de criação:

<br />
CREATE TABLE LOGCLIENTES<br />
(<br />
    SEQUENCIALOG    NUMERIC(10) NOT NULL PRIMARY KEY,<br />
    CODIGOREGISTRO NUMERIC(10) NOT NULL,<br />
    DESCRICAOERRO  VARCHAR(1000)<br />
)<br />
GO</p>
<p>INSERT INTO LOGCLIENTES VALUES (1, 1, 'DATA NASCIMENTO INVALIDA')<br />
INSERT INTO LOGCLIENTES VALUES (2, 2, 'EMAIL INVALIDO')<br />
INSERT INTO LOGCLIENTES  VALUES(3, 3, 'CPF INVALIDO')<br />
GO<br />

Habilitando a procedure xp_cmdshell

Nesse primeiro momento precisamos extrair os dados da tabela na forma de XML para que seja possível criarmos o arquivo. Para conseguirmos exportar os dados para um arquivo vamos utilizar a procedure xp_cmdshell, porém por padrão ela vem desabilitada. Para habilitá-la basta executar o script abaixo:

<br />
-- Permitir alterações nas opções avançadas<br />
EXEC sp_configure 'show advanced options', 1<br />
GO<br />
-- Atualizar as configurações<br />
RECONFIGURE WITH OVERRIDE<br />
GO<br />
-- Habilitar a procedure (que fica nas opções avançadas)<br />
EXEC sp_configure 'xp_cmdshell', 1<br />
GO<br />
-- Atualizar as configurações<br />
RECONFIGURE WITH OVERRIDE<br />
GO<br />

Extraindo um XML a partir de uma consulta

Feito isso, vamos extrair o XML da tabela. Para isso vamos utilizar a clausula FOR XML. Nosso Select fica dessa maneira:

<br />
SELECT * FROM [DB_LOG]..LOGCLIENTES AS LOGCLIENTES FOR XML AUTO, ELEMENTS, ROOT('LOGCLI')<br />

O comando FOR XML possui muitas variações, pois é possível formatarmos o XML conforme nossa necessidade. Nesse caso usamos o modo AUTO, que transforma as colunas retornadas no SELECT em atributos para a linha da tabela no XML (que no caso seria uma TAG <LOGCLIENTE> ). Já a cláusula ELEMENTS transforma esses atributos (no nosso caso as colunas da tabela) em SUBTAGS da TAG <LOGCLIENTE>. A cláusula ROOT serve para criar uma TAG “master” no XML, onde cada linha (TAG <LOGCLIENTE>) seria subTags dessa. Para entender melhor você pode executar o SQL um passo por vez (primeiro só com o AUTO e assim por diante) para ir comparando os resultados.

Criando o arquivo XML

Agora vamos criar um arquivo XML com esse script. Percebam que no script eu especifiquei a base de dados em que essa tabela se encontra ([DB_LOG]). É uma boa prática, já que o SQL Server pode se confundir caso haja uma tabela com mesmo nome em outros bancos. Para criar o arquivo vamos utilizar a procedure que acabamos de habilitar, a XP_CMDSHELL.

<br />
EXEC XP_CMDSHELL 'BCP &quot;SELECT * FROM [DB_LOG]..LOGCLIENTES AS LOGCLIENTES FOR XML AUTO, ELEMENTS, ROOT(''LOGCLI'')&quot; QUERYOUT C:\TMP_LOGCLIENTE.XML -S. -T -c'<br />

Nosso arquivo XML deve estar assim:

OBS: O XP_CMDSHELL serve para executar vários tipo de instruções. No nosso caso estamos utilizando o BCP (Bulk Copy Program) junto com a instrução QUERYOUT. Se eu quisesse gerar um arquivo CSV, por exemplo, poderia fazer dessa maneira:

<br />
EXEC XP_CMDSHELL 'BCP &quot;SELECT * FROM [DB_LOG]..LOGCLIENTES&quot; QUERYOUT C:\TMP_LOGCLIENTE.csv -c -t; -T -S'<br />

Na próxima parte desse artigo vamos ver como lemos o arquivo e transformamos o XML em uma estrutura de tabela (o processo inverso que fizemos aqui).

Abraços a todos.

Feliz 2011!

Bom pessoal,

Mais um ano chega ao seu final. Primeiramente gostaria de agradecer a todos que participaram do blog nesse ano, recebi muitas críticas e também muitos agradecimentos de pessoas que nunca pensei em conhecer, trocar idéias ou encontrarmos juntos as soluções de problemas. Muito obrigado a todos.

Esse ano foi muito corrido para mim, principalmente nesse segundo semestre. O trabalho, misturado com os deveres da faculdade, misturado também com outras coisas paralelas. Por vários momentos liguei o computador, comecei a escrever artigos mas nunca tive tempo de concluí-los, ou por causa de outros compromissos ou também pelo cansaço físico.

Estou caminhando para o ultimo ano da faculdade, e isso quer dizer que o ano que vem vai ser bem corrido também. Na medida do possível vou respondendo as dúvidas da galera (que na maioria das vezes é muito mais rápido do que escrever os artigos). Pretendo também escrever sobre a área que escolhi para o TCC, mas isso é assunto para depois.

Para concluir, gostaria de desejar a todos um Ano Novo repleto de saúde, paz e sucesso. Sei que é muito difícil ter tudo ao mesmo tempo, mas que consigamos compilar tudo junto, executar e ver no que dá kkk… Muitas novidades vão surgir e na medida do possível vamos nos atualizando.

Grande abraço a todos e até 2011!

Dica: Resolvendo o Autonomous Transaction no SQL Server

Um dos grandes desafios para os que utilizam o banco do SQL Server na versão 2008 (ou anteriores) é justamente a falta do suporte as transações autônomas. Elas servem para que os comandos sejam executados em uma transação distinta (autônoma rsrs) em relação a transação principal.

Ela é muito utilizada quando trabalhamos com Logs. Imagine que você tenha um arquivo de integração com 100.000 registros para realizar upload. Para cada linha que der erro na integração você precisa gravar um log contendo a causa do erro. Imagine também que você precise dar um rollback geral caso um único registro estiver inconsistente.  Vejam que temos uma questão fatal: Preciso dar rollback em tudo, mas se eu o fizer perderei os log dos registros (já que os Inserts estão na mesma transação). Como posso resolver esse problema? Preciso que a gravação do log esteja numa transação separada da principal.

No caso do Oracle utilizar as transações autonomas é muito simples. Basta utilizar a linha abaixo na seção DECLARE do seu SQL e pronto:

PRAGMA AUTONOMOUS_TRANSACTION;

Porém, como foi dito no começo desse post, nas versões que temos atualmente o SQL Server não possui essa funcionalidade. Mas precisamos resolver esse problema de alguma forma, afinal nossos clientes estão esperando kkkk.

Darei 3 soluções para esse problema, porém aconselho apenas a 3ª já que as outras dependem muito do tipo de aplicação que você está utilizando:

1ª – Criar um arquivo temporário com todos os registros de log das inconsistências. Após, dar o rollback nos dados e ler “novamente” o arquivo, re-inserindo os registros.

Veja: Criando e lendo arquivos XMLs – Parte1 e Criando e lendo arquivos XMLs – Parte2

Dificuldades: Mais lento, demora para se implementar, dependendo do local que se cria o arquivo pode dar erro com permissões no diretório.

2ª – Você cria a transação no próprio código C# (utilizando conn.BeginTransaction() mesmo). No fim da execução da procedure ela retorna um cursor (select) dos registros inseridos na tabela de log. Pegamos os registros usando o objeto DataTable ou qualquer outro que se possa trabalhar desconectado com o banco (o SQLDataReader não suporta por exemplo). Após fechar a conexão do DataTable com o banco, damos Rollback na transação e inserimos os dados do DataTable novamente na tabela de log.

Dificuldades: O maior problema da implementação dessa solução é a procedure retornar um log com muitos registros, pois a chance de subir uma OutOfMemoryException é muito grande. Um outro problema está na relação de tratar os commits e rollbacks fora do banco, já que em muitas situações necessitam que se tratem dentro dele.

3ª (a poderosa rsrs) – Utilizar uma variável TABLE para armazenar os dados. Essa é uma daquelas soluções “Por que eu não pensei nisso antes?”, mas o Rollback atinge somente aquilo que foi manipulado nas tabelas físicas do banco . Como é uma variável do tipo tabela e está na memória, o Rollback não a atinge.

Dificuldades: O único problema dessa solução é a modularização do código, já que o SQL Server não suporta passar uma variável Table por referencia para uma procedure por exemplo.

Vamos implementar a solução???

Darei apenas um exemplo ilustrativo, mas o importante é que você entenda a idéia e implemente no seu script, deixando seu chefe orgulhoso hehehe…

Estrutura da nossa tabela de log:

CREATE TABLE LOGCLIENTES
(
    SEQUENCIALOG    NUMERIC(10) NOT NULL PRIMARY KEY,
    CODIGOREGISTRO NUMERIC(10) NOT NULL,
    DESCRICAOERRO  VARCHAR(1000)
)
GO

Script:

-- Declaração da variável tipo tabela
DECLARE @TABCLI TABLE (
                          SEQUENCIALOG   NUMERIC(10),
                          CODIGOREGISTRO NUMERIC(10),
                          DESCRICAOERRO  VARCHAR(50)
                      )

-- Inicio da transação principal
BEGIN TRAN

    -- Inserindo os registros na tabela de log
    INSERT INTO LOGCLIENTES VALUES (1, 1, 'DATA NASCIMENTO INVALIDA')
    INSERT INTO LOGCLIENTES VALUES (2, 2, 'EMAIL INVALIDO')
    INSERT INTO LOGCLIENTES  VALUES(3, 3, 'CPF INVALIDO')

    -- Guardo os registros da tabela numa variável
    INSERT INTO @TABCLI
    SELECT SEQUENCIALOG,
           CODIGOREGISTRO,
           DESCRICAOERRO
      FROM LOGCLIENTES

    -- Dá rollback nos registros além de matar a transação
    ROLLBACK

    -- Re-inserindo todos os registros da variável novamente na tabela
    INSERT INTO LOGCLIENTES
    SELECT SEQUENCIALOG,
           CODIGOREGISTRO,
           DESCRICAOERRO
      FROM @TABCLI
GO

-- Faz uma consulta para verificar se todos os registros foram salvos
SELECT *
  FROM LOGCLIENTES

Gostaria de agradecer ao meu amigo Rogério Gigliotti por ter participado dessa solução.

Abraço a todos.

Artigo: Geração Y (Olhar digital)

Gostaria de deixar aqui um ótimo artigo do Olhar Digital sobre a Geração Y. Leiam que vocês não vão se arrepender.

Artigo: Há um Mark Zuckerberg na sua empresa? Saiba como identificá-lo

Quer que um Y seja produtivo? Ele será, se o gerente aprender a negociar o resultado esperado.


Nenhum fenômeno de bilheteria lançado em 2010 conseguiu surpreender tanto quanto “A rede Social”. Ancorado na popularidade do Facebook, o filme oferece como maior atrativo contar a história de Mark Zuckerberg – o mais jovem bilionário no ranking da revista Forbes.

Aos 20 e poucos anos, Zuckerberg apresenta, no limite – como mostrado no filme –, as virtudes e os vícios dos jovens inteligentes, impetuosos e ambiciosos da “era digital”.

Uma particularidade dos cerca de 73 milhões de pessoas entre 20 e 30 e poucos anos denominada de Geração Y? Não! A história é pródiga em exemplos de jovens extraordinários e que mudaram o mundo. Talvez o fato novo seja que jovens como o criador da mais popular rede de relacionamento estejam revolucionando o mundo dos negócios. Aliás, estão criando o mundo dos novos negócios e novos mercados.

Um fenômeno da Era Digital? Em grande parte sim. A Era Digital, com suas possibilidades quase ilimitadas, acende a fogueira da curiosidade (e das vaidades, claro) e da tentação de testar limites, algo inerente aos jovens. Uma conseqüência é o pânico dos nascidos na transição analógico-digital (Geração X) e os nascidos na era analógica (Baby Bommers) em gerenciar o que é ingerenciável (como pais ou como gerentes): paixões! E um mundo de possibilidades nunca antes imaginadas.

Uma característica dessa realidade, ao mesmo tempo instigante e deletéria, é a velocidade, a urgência e ansiedade gerada pela sensação de obsolescência. A inovação de ontem será ultrapassada amanhã. A abundância, e não a escassez de recursos, informações e de possibilidades se torna um problema. E gera culpa, nunca mitigada, numa geração quase sem culpa. Não mais a dicotomia: capitalismo ou socialismo? Só a urgência: ser feliz aqui e agora! (sem as questões filosóficas que “ser feliz” pode suscitar).

Quem, além da geração Y, está mais adaptado a um mundo em que a única certeza é a mudança contínua e vertiginosa?

Quem, senão um Y, exposto a dispositivos digitais desde a infância, pode lidar, com invejável desenvoltura, com as novas tecnologias, incluindo a grande capacidade de navegar e explorar a Internet de forma intuitiva?

O que resta ao menos adaptados, os X, os baby bommers e aos que vieram antes, senão criar as condições para que os da Geração Y façam o que sabem fazer melhor?

Vivendo nas redes sociais, os Y estão mais propensos em confiar naquilo que se espalha no marketing viral do boca a boca do que na publicidade tradicional, e por isso se adaptam facilmente a rotinas de trabalho mais colaborativos e desenvolvidos em equipe. Sim, neles, cooperação e individualismo coexistem. Deles, não espere reuniões monótonas, impositivas e prepare-se para uma apaixonada defesa de pontos de vista e um desconcertante pragmatismo.

Porque tudo lhes parece fácil e simples, e porque estão conectados com muitas pessoas e muitas informações simultaneamente, podem perder o foco e, não obstante a criatividade, podem não transformar as ideias em inovações ou produtos e serviços úteis.

E é aí que pessoas de gerações anteriores podem ser eficazes: como mentores ou coaches dos Y. Mas esqueça os estilos gerenciais que fizeram as gigantes empresas da era industrial o que foram décadas atrás. A autoridade que aceitam é aquela advinda da competência técnica e da reputação de quem pretende comandá-los. E sabem distinguir autoridade de autoritarismo – que rejeitam. Para eles, ordem e progresso não andam juntos. Progresso, sim; ordem, nem tanto.

Quer que um Y seja produtivo? Ele será, se o gerente aprender a negociar o resultado esperado. A Geração Y gosta de “trocar”: trocar ideias, trocar coisas, trocar resultados e comprometimento por um trabalho com significado, desafio, aprendizagem, liderança inspiradora, ambiente de trabalho agradável e divertido.

A Geração Y gosta de lugares e pessoas divertidas. Aliás, está ensinando às gerações precedentes que o trabalho pode e deve ser divertido. Expressões como IFT (índice de felicidade no trabalho) e FIB (felicidade interna bruta) fazem parte do léxico corporativo.

Mas é esse o habitat de um Mark Zuckerberg? Pode haver um Zuckerberg  na sua empresa?

É quase certo que não. Se há outros – e deve haver – ele provavelmente deve estar criando mais uma nova empresa por aí. Está criando um novo mercado (e você ainda vai comprar dele algo que ainda nem sabe que precisa). Ele talvez até já tenha passado por sua empresa e você não reparou. Talvez seja aquele jovem cheio de ideias que ninguém levava muito sério e para quem os gerentes não tinham tempo nem paciência. Ou aquele empregado-problema, rebelde, irritante, insubordinado, que não cumpria horário, estourava prazos, orçamentos, e só fazia perguntas quando você queria respostas.

E quase certo que você quisesse reter um Mark Zuckerberg se ele tivesse as virtudes do gênio que ele é, mas não vícios do homem açoitado por paixões e interesses nem tão virtuosos assim (pelo que se depreende do filme). Mas aí ele não seria a personalidade do ano. Seria?

Na dúvida, melhor dialogar com os Y que habitam sua empresa. Quer saber o que pensam? Pergunte a eles o que querem, pensam e sentem. Exatamente como faz com os seus clientes especiais.

Quem sabe você não descobre em um Y de seu time de talentos com potencial de um Mark Zuckerberg?

*Luiz Alberto Ferla é CEO da Talk Interactive, empresa especializada em estratégias de serviços digitais. É engenheiro e administrador pós-graduado em planejamento estratégico.

Fonte: Olhar Digital

Evento: SECOMPP – 2010

Pessoal, meu amigo Luiz Felipe que estuda na Unesp de Presidente Prudente pediu para que ajudasse a divulgar a 8ª edição do evento Semana da Computação em Presidente Prudente, que ocorrem nos dias 20 a 24 de Setembro.

Segue algumas informações:

A SECOMPP é um evento que está se tornando tradição em Presidente Prudente e região! Desde 2002 as atividades ocorridas durante a SECOMPP abordam novas tecnologias e conceitos da Ciência da Computação trazendo para a comunidade um pouco de conhecimento técnico de um profissional da informática.

Conforme pode ser observado, há um conjunto significativo de diferentes atividades (06 Palestras, 18 Minicursos e 01 Mesa Redonda). Vale informar que alguns dos minicursos possuem número limitado de vagas, logo, fica a sugestão para que façam suas inscrições, o quanto antes.

Gostaria de realçar ainda, a importância da participação dos alunos do Curso de Ciência da Computação no evento, que é pensado no sentido de complementar a formação acadêmica de todos e possibilitar que haja uma interação com ex-alunos da FCT/UNESP-PP (atuando no mercado de trabalho), alunos e professores de outras instituições, além de profissionais experientes ligados a empresas regionais, nacionais e internacionais. Enfim, a troca de experiências e de vivências profissionais é uma das tônicas do evento.

Um grupo de alunos extremamente dedicado, tem trabalhado há mais de um mês no sentido de viabilizar e operacionalizar o evento. As inscrições podem ser feitas a partir do link: http://www4.fct.unesp.br/semanas/secompp/inscricao/inscricoes.php.

Clique aqui para acessar o site do evento.

Obrigado a todos.

Oracle: Substituindo Cursores pelo comando FOR IN

Uma alternativa para a substituição do uso de cursores no oracle é o comando FOR IN.

Sua sintaxe não é complexa, veja o exemplo abaixo:

FOR cProdutos IN (SELECT CD_PRODUTO
                    FROM PRODUTO
                  WHERE CD_FORNECEDOR = vFornecedor)
LOOP
      vResult := vResult || '$' || cProdutos. CD_PRODUTO;
END LOOP;

Há ainda a opção de percorrer inversamente a query (de trás para frente) utilizando o comando REVERSE:

FOR cFunc IN REVERSE (SELECT CODIGOFUNCIONARIO,
                             NOMEFUNCIONARIO,
                     SALARIO
             FROM FUNCIONARIO
                   WHERE CODIGOCLASSE = 1)
LOOP
     -- Instruções
END LOOP;