none
Separa valores de campo varchar RRS feed

  • Pergunta

  • Srs.,

    Tenho uma tabela onde tenho um campo DESCRICAO, do tipo varchar.

    Um registro deste campo, tem uma quantidade indefinida de Descrições, e estas são separadas por ";" - PONTO E VIRGULA

    Ex:

    ID       Descricao

    1         teste; teste1; teste2

    2         sql; sql1; sql2

    3         comp; comp1; comp2

    Eu preciso criar uma tabela associativa e buscar os dados nesta tabela anterior, ficando eles da seguinte forma:

    ID       Descricao

    1         teste

    1         teste1        

    1         teste2

    2         sql

    2         sql1

    2         sql2

    3        comp

    3        comp1

    3        comp2

    Enfim, preciso pegar cada valor (separados por ponto e virgula) do campo descrição e criar-lo como um novo resgistro nesta nova tabela.

    Preciso de ajuda

    Agradeço.

    segunda-feira, 19 de março de 2012 20:20

Respostas

  • Boa noite Rafael,

    Se você garantir que esses campos tem um padrão na separação por ponto e vírgula, você pode usar algo parecido com o exemplo abaixo.

    Eu tomei como premissa que sempre haverá um espaço após o ';' e que ele sempre será o último caractere do texto.
    Esse exemplo é pra você entender como pode fazer. Customize-o para atender às suas necessidades.

    CREATE TABLE #tmp
    (
    	Palavras VARCHAR(100)
    )
    DECLARE @TEXTO VARCHAR(200)
    SET @TEXTO = 'SQL; SQL1; SQL2; TESTE;'
    WHILE (LEN(@Texto) > 0)
    BEGIN
    	insert into #tmp
    	SELECT SUBSTRING(@TEXTO, 0, patindex('%;%', @texto))
    	set @TEXTO = SUBSTRING(@TEXTO, patindex('%;%', @texto) + 2, LEN(@TEXTO) )
    	PRINT @TExto 
    END
    SELECT * FROM #tmp

    []'s


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    • Marcado como Resposta Heloisa Pires segunda-feira, 26 de março de 2012 14:50
    segunda-feira, 19 de março de 2012 21:15
  • Boa Noite,

    Segue uma alternativa mais declarativa.

    declare @t table (ID INT, Descricao VARCHAR(50))
    insert into @t values (1,'teste; teste1; teste2')
    insert into @t values (2,'sql; sql1; sql2')
    insert into @t values (3,'comp; comp1; comp2')

    ;With Res (Id, DescXML) As
    (select ID, cast('<E><e>' + REPLACE(Descricao,'; ','</e><e>') + '</e></E>' as XML)
    from @t)

    SELECT ID, E.e.value('.','nvarchar(30)')
    FROM Res
    CROSS APPLY DescXml.nodes('/E/e') E(e)

    [ ]s,

    Gustavo Maia Aguiar
    Blog: http://gustavomaiaaguiar.wordpress.com
    Vídeos:http://www.youtube.com/user/gmasql


    Classifique as respostas. O seu feedback é imprescindível

    • Marcado como Resposta Heloisa Pires segunda-feira, 26 de março de 2012 14:51
    terça-feira, 20 de março de 2012 04:24
  • Rafael,

    Sempre que preciso disso uso a função que vou postar aqui. Ela recebe como parametro o texto que você quer pegar os valores, e o delimitador (o ";" está como padrão), e retorna uma variável do tipo tabela com os valores já separados.

    CREATE FUNCTION dbo.Split
      (
                              @Texto VARCHAR(MAX),
                              @Caractere VARCHAR(MAX) = ';'
      ) RETURNS @Saida TABLE (Array VARCHAR(8000)) 
    
    BEGIN
      
      DECLARE @Pt VARCHAR(8000)
      WHILE CHARINDEX(@Caractere, @Texto, 0) <> 0
        BEGIN
          SELECT @Pt    = RTRIM(LTRIM(SUBSTRING(@Texto, 1, CHARINDEX(@Caractere, @Texto, 0) -1))),
                 @Texto = RTRIM(LTRIM(SUBSTRING(@Texto, CHARINDEX(@Caractere, @Texto, 0)+ LEN(@Caractere), LEN(@Texto))))
          IF LEN(@Pt) > 0
            BEGIN
              INSERT INTO @Saida 
              SELECT @Pt
            END
        END 
    
      IF LEN(@Texto) > 0
        BEGIN
          INSERT INTO @Saida 
          SELECT @Texto
        END
        
      RETURN
      
    END
    
    GO


    • Editado Philipe Souza quarta-feira, 21 de março de 2012 03:38 Faltou complemento
    • Sugerido como Resposta Philipe Souza quarta-feira, 21 de março de 2012 03:38
    • Marcado como Resposta Heloisa Pires segunda-feira, 26 de março de 2012 14:51
    quarta-feira, 21 de março de 2012 03:37

Todas as Respostas

  • Boa noite Rafael,

    Se você garantir que esses campos tem um padrão na separação por ponto e vírgula, você pode usar algo parecido com o exemplo abaixo.

    Eu tomei como premissa que sempre haverá um espaço após o ';' e que ele sempre será o último caractere do texto.
    Esse exemplo é pra você entender como pode fazer. Customize-o para atender às suas necessidades.

    CREATE TABLE #tmp
    (
    	Palavras VARCHAR(100)
    )
    DECLARE @TEXTO VARCHAR(200)
    SET @TEXTO = 'SQL; SQL1; SQL2; TESTE;'
    WHILE (LEN(@Texto) > 0)
    BEGIN
    	insert into #tmp
    	SELECT SUBSTRING(@TEXTO, 0, patindex('%;%', @texto))
    	set @TEXTO = SUBSTRING(@TEXTO, patindex('%;%', @texto) + 2, LEN(@TEXTO) )
    	PRINT @TExto 
    END
    SELECT * FROM #tmp

    []'s


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    • Marcado como Resposta Heloisa Pires segunda-feira, 26 de março de 2012 14:50
    segunda-feira, 19 de março de 2012 21:15
  • Boa Noite,

    Segue uma alternativa mais declarativa.

    declare @t table (ID INT, Descricao VARCHAR(50))
    insert into @t values (1,'teste; teste1; teste2')
    insert into @t values (2,'sql; sql1; sql2')
    insert into @t values (3,'comp; comp1; comp2')

    ;With Res (Id, DescXML) As
    (select ID, cast('<E><e>' + REPLACE(Descricao,'; ','</e><e>') + '</e></E>' as XML)
    from @t)

    SELECT ID, E.e.value('.','nvarchar(30)')
    FROM Res
    CROSS APPLY DescXml.nodes('/E/e') E(e)

    [ ]s,

    Gustavo Maia Aguiar
    Blog: http://gustavomaiaaguiar.wordpress.com
    Vídeos:http://www.youtube.com/user/gmasql


    Classifique as respostas. O seu feedback é imprescindível

    • Marcado como Resposta Heloisa Pires segunda-feira, 26 de março de 2012 14:51
    terça-feira, 20 de março de 2012 04:24
  • Rafael,

    Sempre que preciso disso uso a função que vou postar aqui. Ela recebe como parametro o texto que você quer pegar os valores, e o delimitador (o ";" está como padrão), e retorna uma variável do tipo tabela com os valores já separados.

    CREATE FUNCTION dbo.Split
      (
                              @Texto VARCHAR(MAX),
                              @Caractere VARCHAR(MAX) = ';'
      ) RETURNS @Saida TABLE (Array VARCHAR(8000)) 
    
    BEGIN
      
      DECLARE @Pt VARCHAR(8000)
      WHILE CHARINDEX(@Caractere, @Texto, 0) <> 0
        BEGIN
          SELECT @Pt    = RTRIM(LTRIM(SUBSTRING(@Texto, 1, CHARINDEX(@Caractere, @Texto, 0) -1))),
                 @Texto = RTRIM(LTRIM(SUBSTRING(@Texto, CHARINDEX(@Caractere, @Texto, 0)+ LEN(@Caractere), LEN(@Texto))))
          IF LEN(@Pt) > 0
            BEGIN
              INSERT INTO @Saida 
              SELECT @Pt
            END
        END 
    
      IF LEN(@Texto) > 0
        BEGIN
          INSERT INTO @Saida 
          SELECT @Texto
        END
        
      RETURN
      
    END
    
    GO


    • Editado Philipe Souza quarta-feira, 21 de março de 2012 03:38 Faltou complemento
    • Sugerido como Resposta Philipe Souza quarta-feira, 21 de março de 2012 03:38
    • Marcado como Resposta Heloisa Pires segunda-feira, 26 de março de 2012 14:51
    quarta-feira, 21 de março de 2012 03:37
  • Bom Dia,

    Algumas considerações sobre o uso de funções:

    Funções Escalares – Resusabilidade, Formatação, Preguiça vs Desempenho
    http://gustavomaiaaguiar.wordpress.com/2011/05/29/funes-escalares-resusabilidade-formatao-preguia-vs-desempenho/

    [ ]s,

    Gustavo Maia Aguiar
    Blog: http://gustavomaiaaguiar.wordpress.com
    Vídeos:http://www.youtube.com/user/gmasql


    Classifique as respostas. O seu feedback é imprescindível

    quarta-feira, 21 de março de 2012 12:57