Eu tenho uma coluna do SQL Server 2008 R2 contendo uma sequência que eu preciso dividir por vírgula. Eu já vi muitas respostas no StackOverflow, mas nenhuma delas funciona no R2. Verifiquei se tenho permissões de seleção em qualquer exemplo de função de divisão. Qualquer ajuda muito apreciada.
sql
sql-server
tsql
sql-server-2008
split
Lee Grindon
fonte
fonte
mdq.RegexSplit
função no complemento "Master Data Services", que pode ajudar. Certamente vale a pena investigar .Respostas:
Eu usei esse SQL antes, o que pode funcionar para você: -
e para usá-lo: -
fonte
Em vez de CTEs recursivas e enquanto loops, alguém considerou uma abordagem mais baseada em conjuntos? Observe que essa função foi escrita para a pergunta, baseada no SQL Server 2008 e vírgula como delimitador . No SQL Server 2016 e acima (e no nível de compatibilidade 130 e acima),
STRING_SPLIT()
é uma opção melhor .Se você quiser evitar que a limitação do comprimento da string seja <= o número de linhas
sys.all_columns
((9.980model
no SQL Server 2017; muito maior nos seus próprios bancos de dados de usuários)), você pode usar outras abordagens para derivar os números, como construindo sua própria tabela de números . Você também pode usar uma CTE recursiva nos casos em que não pode usar tabelas do sistema ou criar suas próprias:Mas você precisará anexar
OPTION (MAXRECURSION 0)
(ouMAXRECURSION <longest possible string length if < 32768>
) à consulta externa para evitar erros de recursão para cadeias> 100 caracteres. Se essa também não é uma boa alternativa, veja esta resposta conforme indicado nos comentários.(Além disso, o delimitador precisará ser
NCHAR(<=1228)
. Ainda pesquisando o porquê.)Mais sobre funções de divisão, por que (e prova disso) enquanto loops e CTEs recursivos não são dimensionados, e melhores alternativas, se as seqüências de caracteres provenientes da camada de aplicação são divididas:
fonte
sys.all_objects
for menor que o número de caracteres na string de entrada, ele truncará a string e os valores desaparecerão. Comosys.all_objects
está sendo usado apenas como um hack para gerar linhas, existem maneiras melhores de fazer isso, por exemplo, esta resposta .Finalmente, a espera terminou no SQL Server 2016 e eles introduziram a função String de divisão:
STRING_SPLIT
Todos os outros métodos para dividir seqüências de caracteres como XML, tabela Tally, loop while, etc., foram surpreendidos por essa
STRING_SPLIT
função.Aqui está um excelente artigo com comparação de desempenho: Surpresas e premissas de desempenho: STRING_SPLIT
fonte
A maneira mais fácil de fazer isso é usando o
XML
formato.1. Convertendo string em linhas sem tabela
INQUERIR
RESULTADO
2. Convertendo para linhas de uma tabela que possui um ID para cada linha CSV
TABELA DE FONTES
INQUERIR
RESULTADO
fonte
@String
contiver caracteres proibidos ... Acabei de postar uma resposta para superar esse problema.Eu precisava de uma maneira rápida de se livrar da
+4
a partir de um código postal .No proc ... no UDF ... apenas um pequeno comando embutido que faz o que deve. Não é chique, não é elegante.
Mude o delimitador conforme necessário, etc, e ele funcionará para qualquer coisa.
fonte
se você substituir
com
você pode eliminar a última inserção após o loop while!
fonte
+1
aSELECT @pos = LEN(@stringToSplit)
aparece para resolver esse problema. No entanto, o valorSELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
retornará, aInvalid length parameter passed to the LEFT or SUBSTRING function
menos que você adicione+1
ao terceiro parâmetro de SUBSTRING também. ou você pode substituir essa tarefa porSET @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, 4000) --MAX len of nvarchar is 4000
Todas as funções para divisão de string que usam algum tipo de loop (iterações) apresentam desempenho ruim. Eles devem ser substituídos por uma solução baseada em conjunto.
Este código executa excelente.
fonte
@List
contiver caracteres proibidos ... Acabei de postar uma resposta para superar esse problema.A abordagem frequentemente usada com elementos XML é interrompida no caso de caracteres proibidos. Essa é uma abordagem para usar esse método com qualquer tipo de caractere, mesmo com o ponto e vírgula como delimitador.
O truque é, primeiro usar
SELECT SomeString AS [*] FOR XML PATH('')
para obter todos os caracteres proibidos adequadamente escapados. Essa é a razão pela qual substituo o delimitador por um valor mágico para evitar problemas;
como delimitador.O resultado
fonte
Eu tive que escrever algo assim recentemente. Aqui está a solução que eu criei. É generalizado para qualquer string delimitadora e acho que teria um desempenho um pouco melhor:
fonte
Uma solução usando um CTE, se alguém precisar disso (além de mim, que obviamente fez, foi por isso que eu escrevi).
fonte
Isso é mais restrito. Quando faço isso, geralmente tenho uma lista delimitada por vírgula de IDs exclusivos (INT ou BIGINT), que quero converter como uma tabela para usar como uma junção interna a outra tabela que tenha uma chave primária de INT ou BIGINT. Desejo que uma função com valor de tabela in-line seja retornada para que eu tenha a junção mais eficiente possível.
O uso da amostra seria:
Eu roubei a ideia de http://sqlrecords.blogspot.com/2012/11/converting-delimited-list-to-table.html , alterando-a para ser valorizada em tabela e convertida como INT.
fonte
Há uma versão correta aqui, mas achei que seria bom adicionar um pouco de tolerância a falhas caso eles tenham uma vírgula à direita, além de torná-la para que você possa usá-la não como uma função, mas como parte de um código maior . Apenas no caso de você usá-lo apenas uma vez e não precisar de uma função. Isso também é para números inteiros (que é o que eu precisava) para que você possa ter que alterar seus tipos de dados.
fonte
SET @StringToSeperate = @StringToSeperate+','
imediatamente antes doWHILE
loop, acho que você poderá eliminar o bloco "adicionar último valor". Veja também meu sol'n no githubModifiquei um pouco a função de Andy Robinson. Agora você pode selecionar apenas a parte necessária da tabela de retorno:
SELECT Name FROM dbo.splitstring('ELIS.YD.CRP1.1.CBA.MDSP.T389.BT') WHERE numOrder=5
fonte
Se você precisar de uma solução ad-hoc rápida para casos comuns com código mínimo, essa linha recursiva CTE de duas linhas fará isso:
Use isso como uma declaração autônoma ou apenas adicione os CTEs acima a qualquer uma das suas consultas e poderá ingressar na tabela resultante
b
com outras pessoas para usar em outras expressões.editar (por Shnugo)
Se você adicionar um contador, receberá um índice de posição junto com a Lista:
O resultado:
fonte
Eu pego a rota xml envolvendo os valores em elementos (M, mas tudo funciona):
fonte
Aqui está uma versão que pode ser dividida em um padrão usando patindex, uma simples adaptação da postagem acima. Eu tive um caso em que precisava dividir uma string que continha vários caracteres separadores.
resultado se parece com isso
stringa stringb x y z
fonte
Pessoalmente, uso esta função:
fonte
Eu desenvolvi um divisor duplo (ocupa dois caracteres divididos) conforme solicitado aqui . Pode ser de algum valor nesse segmento, já que é o mais referenciado para consultas relacionadas à divisão de cadeias.
Uso:
Uso possível (obtenha o segundo valor de cada divisão):
fonte
Aqui está um exemplo que você pode usar como função ou também pode colocar a mesma lógica no procedimento. --SELECT * de [dbo] .fn_SplitString;
fonte
@vCSV
contiver caracteres proibidos ... Acabei de postar uma resposta para superar esse problema.Uma solução recursiva baseada em cte
fonte
Isso é baseado na resposta de Andy Robertson, eu precisava de um delimitador que não fosse vírgula.
E para usá-lo:
(Testado no SQL Server 2008 R2)
EDIT: código de teste correto
fonte
/ *
Casos de teste: veja o URL mencionado como "funcionalidade aprimorada" acima
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,b')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, ')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, c ')
* /
fonte
fonte
Você pode usar esta função:
fonte
Com todo o respeito ao @AviG, esta é a versão sem erros da função criada por ele para retornar todos os tokens na íntegra.
fonte
A maneira mais fácil:
Funciona mesmo em edição expressa :).
fonte