none
Quebra de string em vários vetores RRS feed

  • Pergunta

  • Boa noite,

    Estou com um pequeno desafio a fazer, vou tentar explicar. Peguei um banco que há um coluna de uma tabela que foi criada para receber algumas informações dinâmicas. Quando faço um select deste campo o resultado é algo assim:

    [{"Name":"Telefone Fixo","Value":"34999999"},{"Name":"Celular","Value":"99999999"},{"Name":"Endereço","Value":"sucupiras"},{"Name":"Apto ","Value":null},{"Name":"Bairro","Value":"colina"},{"Name":"Condominio","Value":""},{"Name":"Ponto de Ref.","Value":"escola"},{"Name":"Obs:","Value":null}]

    Sendo que depois do "Name" vem o nome da informação dinâmica e depois do "Value" o valor desta informação. Sendo assim, preciso de algo para conseguir pegar parte desta string, porém não consegui usar o "Substring"pois não sei qual posição vai começar a informação. Suponhamos que eu deseje obter a informação do Endereço, a função que eu preciso me retornaria a palavra "sucupiras".

    Outra forma de conseguir resolver o meu problema seria uma função que quebrasse a string em vários registros, por exemblo:

    Name Value

    Telefone Fixo 34999999
    Celular 99999999
    Endereço sucupiras
    Apto NULL
    Bairro colina

    Será que existe algo pra me ajudar?

    Desde já agradeço.


    • Editado galves.rod sábado, 20 de dezembro de 2014 12:19 Alinhamento
    sexta-feira, 19 de dezembro de 2014 23:27

Respostas

  • "G", parece que está com algo semelhante ao modelo entidade-atributo-valor. No caso, cada campo está encapsulado entre {} e cada registro por [].

    Para essa coluna em específico, todas as linhas da tabela estão sempre com o mesmo número de atributos e na mesma sequência? Ou varia número de atributos ou ainda a sequência?

    A primeira impressão é que as informações podem ser recuperadas facilmente se transformar o conteúdo da coluna em formato XML (usando a função replace, por exemplo) e então usar as construções XML do SQL Server para obter o conteúdo da tabela no formato que necessita.


        José Diz     Belo Horizonte, MG - Brasil



    • Editado José Diz sábado, 20 de dezembro de 2014 09:59
    • Marcado como Resposta galves.rod sábado, 20 de dezembro de 2014 20:07
    sábado, 20 de dezembro de 2014 09:44
  • Gabriel, uma forma de obter os valores dos atributos é criar uma função que obtenha cada atributo, individualmente. Ou seja, para cada atributo deve-se criar uma função. Funciona, mas não é tão elegante e prática quanto XML.

    Por exemplo, para obter o número do telefone fixo, poderíamos ter

    -- código 1
    CREATE FUNCTION GetTelFixo (@pColuna varchar(500))
      returns varchar(30)
    as begin
    declare @Texto varchar(200), @PosI int, @PosF int;
    set @Texto= '{"Name":"Telefone Fixo","Value":'
    set @PosI= CharIndex(@Texto, @pColuna);
    IF @PosI > 0
      begin
      set @PosI+= Len(@Texto);
      set @PosF= CharIndex('}', @pColuna, @PosI);
      set @Texto= SubString(@pColuna, @PosI, (@PosF - @PosI));
      IF @Texto = 'null'
        set @Texto= NULL;
      end
    else
      set @Texto= NULL;  
    return @Texto;  
    end;
    go
     

    Como deve ter observado, o código 1 pode ser modificado para obter cada um dos atributos, criando então as funções GetTelCelular, GetEndereço etc etc.

    -- código 2
    SELECT coluna, 
           dbo.GetTelFixo (coluna) as [Telefone Fixo],
           dbo.GetTelCelular (coluna) as [Telefone Móvel],
           dbo.GetEndereço (coluna) as [Endereço],
           ...
      from tabela;



    Mas o código 1 também pode ser transformado em algo genérico. Por exemplo:

    -- código 3 v3
    CREATE FUNCTION GetValorAtributo (@pColuna varchar(500), @pAtributo varchar(100))
      returns varchar(200)
    as begin
    declare @Texto varchar(200), @PosI int, @PosF int;
    set @Texto= '{"Name":"' + @pAtributo + '","Value":';
    set @PosI= CharIndex(@Texto, @pColuna);
    IF @PosI > 0
      begin
      set @PosI+= Len(@Texto);
      set @PosF= CharIndex('}', @pColuna, @PosI);
      set @Texto= SubString(@pColuna, @PosI, (@PosF - @PosI));
      IF @Texto = 'null' or @Texto = '""'
        set @Texto= NULL;
      end
    else
      set @Texto= NULL;  
    return @Texto;  
    end;
    go

    e o mesmo seria utilizado desta forma:

    -- código 4 v2
    SELECT coluna, 
           dbo.GetValorAtributo (coluna, 'Telefone Fixo') as [Telefone Fixo],
           dbo.GetValorAtributo (coluna, 'Celular') as [Telefone Móvel],
           dbo.GetValorAtributo (coluna, 'Endereço') as [Endereço]
           ...
      from tabela;


        José Diz     Belo Horizonte, MG - Brasil


    • Marcado como Resposta galves.rod sábado, 20 de dezembro de 2014 20:06
    • Editado José Diz domingo, 21 de dezembro de 2014 10:17
    sábado, 20 de dezembro de 2014 12:50

Todas as Respostas

  • "G", parece que está com algo semelhante ao modelo entidade-atributo-valor. No caso, cada campo está encapsulado entre {} e cada registro por [].

    Para essa coluna em específico, todas as linhas da tabela estão sempre com o mesmo número de atributos e na mesma sequência? Ou varia número de atributos ou ainda a sequência?

    A primeira impressão é que as informações podem ser recuperadas facilmente se transformar o conteúdo da coluna em formato XML (usando a função replace, por exemplo) e então usar as construções XML do SQL Server para obter o conteúdo da tabela no formato que necessita.


        José Diz     Belo Horizonte, MG - Brasil



    • Editado José Diz sábado, 20 de dezembro de 2014 09:59
    • Marcado como Resposta galves.rod sábado, 20 de dezembro de 2014 20:07
    sábado, 20 de dezembro de 2014 09:44
  • Bom dia,

    Obrigado por responder. Não conhecia esse modelo, mas já vou dar uma olhada no link que você me passou.

    A minha primeira impressão em usar o REPLACE foi que seria trabalhoso e muito complicado de quaisquer posterior manutenção no código. Já havia até começado a fazer alguns testes mas achei melhor vir ao fórum e estudar alguma possível melhor opção.

    Segue dois registro trazidos do banco de dados, no exemplo é possível ver que não há uma posição certa dos campos o que dificulta o uso do REPLACE, e não há também um carácter que possibilite usar o CHARINDEX, em combinação com o replace.

    [{"Name":"Telefone Fixo","Value":"34999999"},{"Name":"Celular","Value":"99999999"},{"Name":"Endereço","Value":"sucupiras"},{"Name":"Apto ","Value":null},{"Name":"Bairro","Value":"colina"},{"Name":"Condominio","Value":""},{"Name":"Ponto de Ref.","Value":"escola"},{"Name":"Obs:","Value":null}]

    [{"Name":"Telefone Fixo","Value":"38201119"},{"Name":"Celular","Value":null},{"Name":"Endereço","Value":"Rua das sucupiras,144"},{"Name":"Apto ","Value":null},{"Name":"Bairro","Value":"Colina"},{"Name":"Condominio","Value":null},{"Name":"Ponto de Ref.","Value":"Escola Padre Almir"},{"Name":"Obs:","Value":""},{"Name":"CPF","Value":"08614396600"}]

    Atenciosamente,

    Gabriel Alves.

    sábado, 20 de dezembro de 2014 10:40
  • Gabriel, uma forma de obter os valores dos atributos é criar uma função que obtenha cada atributo, individualmente. Ou seja, para cada atributo deve-se criar uma função. Funciona, mas não é tão elegante e prática quanto XML.

    Por exemplo, para obter o número do telefone fixo, poderíamos ter

    -- código 1
    CREATE FUNCTION GetTelFixo (@pColuna varchar(500))
      returns varchar(30)
    as begin
    declare @Texto varchar(200), @PosI int, @PosF int;
    set @Texto= '{"Name":"Telefone Fixo","Value":'
    set @PosI= CharIndex(@Texto, @pColuna);
    IF @PosI > 0
      begin
      set @PosI+= Len(@Texto);
      set @PosF= CharIndex('}', @pColuna, @PosI);
      set @Texto= SubString(@pColuna, @PosI, (@PosF - @PosI));
      IF @Texto = 'null'
        set @Texto= NULL;
      end
    else
      set @Texto= NULL;  
    return @Texto;  
    end;
    go
     

    Como deve ter observado, o código 1 pode ser modificado para obter cada um dos atributos, criando então as funções GetTelCelular, GetEndereço etc etc.

    -- código 2
    SELECT coluna, 
           dbo.GetTelFixo (coluna) as [Telefone Fixo],
           dbo.GetTelCelular (coluna) as [Telefone Móvel],
           dbo.GetEndereço (coluna) as [Endereço],
           ...
      from tabela;



    Mas o código 1 também pode ser transformado em algo genérico. Por exemplo:

    -- código 3 v3
    CREATE FUNCTION GetValorAtributo (@pColuna varchar(500), @pAtributo varchar(100))
      returns varchar(200)
    as begin
    declare @Texto varchar(200), @PosI int, @PosF int;
    set @Texto= '{"Name":"' + @pAtributo + '","Value":';
    set @PosI= CharIndex(@Texto, @pColuna);
    IF @PosI > 0
      begin
      set @PosI+= Len(@Texto);
      set @PosF= CharIndex('}', @pColuna, @PosI);
      set @Texto= SubString(@pColuna, @PosI, (@PosF - @PosI));
      IF @Texto = 'null' or @Texto = '""'
        set @Texto= NULL;
      end
    else
      set @Texto= NULL;  
    return @Texto;  
    end;
    go

    e o mesmo seria utilizado desta forma:

    -- código 4 v2
    SELECT coluna, 
           dbo.GetValorAtributo (coluna, 'Telefone Fixo') as [Telefone Fixo],
           dbo.GetValorAtributo (coluna, 'Celular') as [Telefone Móvel],
           dbo.GetValorAtributo (coluna, 'Endereço') as [Endereço]
           ...
      from tabela;


        José Diz     Belo Horizonte, MG - Brasil


    • Marcado como Resposta galves.rod sábado, 20 de dezembro de 2014 20:06
    • Editado José Diz domingo, 21 de dezembro de 2014 10:17
    sábado, 20 de dezembro de 2014 12:50
  • Boa tarde,

    A solução funcionou perfeitamente. Muito Obrigado.

    sábado, 20 de dezembro de 2014 20:06
  • Ok, Gabriel.

    Fique atento a ajustar o tamanho dos parâmetros e variáveis internas da função GetValorAtributo. No código 3 ajuste os tamanhos do parâmetro @pColuna, do retorno e da variável interna @Texto.

    Por exemplo, se o campo "Obs:" for o de maior comprimento e aceitar até 300 caracteres, e o tamanho da coluna que contém os valores esteja declarada na tabela do banco de dados como tamanho de até 800 caracteres, sugiro

    CREATE FUNCTION GetValorAtributo (@pColuna varchar(800), @pAtributo varchar(100))
      returns varchar(302)
    as begin
    declare @Texto varchar(302), @PosI int, @PosF int;


        José Diz     Belo Horizonte, MG - Brasil


    • Editado José Diz domingo, 21 de dezembro de 2014 15:27
    domingo, 21 de dezembro de 2014 10:14
  • A sim, verdade. Obrigado mais uma vez.
    • Editado galves.rod quinta-feira, 30 de julho de 2015 15:10 Correção Ortografica
    domingo, 21 de dezembro de 2014 12:13