Eu preciso dividir uma string delimitada por vírgulas, manipulá-la e concatená-la novamente em uma única string mantendo a ordem original dos dados (se possível).
Por exemplo, pegue uma lista de definição de coluna de uma CREATE TABLE
instrução (como uma string) como 'BrentOzarColumn INTEGER, PaulWhiteColumn DATETIME, ErikDarlingColumn VARCHAR(100)'
. Eu gostaria de dividir a lista delimitada por vírgulas em um conjunto de resultados, como usar a função interna do SQL Server STRING_SPLIT()
assim: SELECT TRIM([Value]) AS CoolDataPeople FROM STRING_SPLIT('BrentOzarColumn INTEGER, PaulWhiteColumn DATETIME, ErikDarlingColumn VARCHAR(100)', ',')
.
Sem especificar uma ORDER BY
cláusula, isso repetidamente produz (por coincidência?) os seguintes resultados que parecem ser ordenados pela mesma ordenação que estão na string:
Depois de ter o resultado definido acima, quero aplicar algumas manipulações de string adicionais a cada linha (como anexar algum texto constante) e, em seguida, concatenar cada linha de volta com uma função como STRING_AGG()
(adeus dias de STUFF ... FOR XML PATH
:) na mesma ordem que o corda original. Então, um exemplo do meu resultado final poderia ser 'BrentOzarColumn INTEGER SQLROX, PaulWhiteColumn DATETIME SQLROX, ErikDarlingColumn VARCHAR(100) SQLROX'
.
Em última análise, minha pergunta é: Os resultados da STRING_SPLIT()
função são retornados em uma ordem determinística? Eu sei que sem uma ORDER BY
cláusula, a ordenação não é garantida ao selecionar um conjunto de dados como a Table
ou View
, mas queria saber se há uma diferença com as funções?
Enquanto digito isso, tenho um palpite de que a resposta é não, a ordenação não é determinística, portanto, não tenho garantia da ordem dos resultados. Além disso, estou apostando que há um possível não determinismo adicional adicionado para cada função que executo em cima dos resultados, especialmente quando os combino novamente com STRING_AGG()
. (Independentemente da resposta, agradeço sua ajuda e todos vocês são pessoas legais com dados. ;)
Não, eles não são retornados em uma ordem determinística.
Embora seja improvável que você os veja retornados em uma ordem diferente, isso não torna o comportamento atual determinístico ou confiável. Truques como aplicar
ROW_NUMBER() OVER (ORDER BY (SELECT 1))
à saída em um local intermediário, como um CTE, também não são garantidos para funcionar.É um dos recursos notavelmente ausentes do
STRING_SPLIT()
, sobre o qual escrevi no blog:E Andy Mallon também:
Vote e comente aqui:
(Este item pede especificamente que uma coluna adicional seja retornada para indicar a posição dentro da string original, mas, devido a problemas de compatibilidade com versões anteriores, provavelmente precisaria ser entregue por meio de uma nova função, semelhante a como
CONCAT_WS
surgiu.)Como um aparte , a documentação originalmente dizia:
Isso foi deliberadamente alterado neste commit para remover qualquer noção de que a ordem de retorno é prometida. Agora a documentação diz:
Por que eles precisariam remover essa promessa?
Não estou familiarizado com a implementação interna, mas acredito que a versão original da documentação foi escrita por observadores, não pelos autores da função. Essa declaração provavelmente foi escrita dessa maneira porque foi o comportamento que eles observaram quando usaram a função. Muitos de nós fazemos a mesma coisa quando dizemos às pessoas que não precisamos
ORDER BY
ao selecionar linhas de uma tabela agrupada: "elas sempre sairão nesta ordem". Bastante confiável, até que o otimizador escolha um índice diferente.Meu palpite é que eles estão cobrindo suas bundas para comportamento futuro. Pense em todas as mudanças que eles fizeram no funcionamento das funções e também nas mudanças contínuas no otimizador.
Atualmente, com o caso simples:
Não há muita oportunidade ou razão para que isso não seja sequencial. Mas e quando você está
OUTER APPLY
em umanvarchar(max)
coluna entre duas enormes tabelas particionadas e os dados começam a ser processados em modo de lote e/ou em paralelo? Eles teriam que escrever lógica adicional no código para garantir que toda essa saída voltasse na ordem correta? Valeria a pena? Eles teriam que revisitá-lo para cada alteração futura de processamento/otimizador de função para manter essa promessa?Que mudanças eles estão fazendo?
A documentação foi atualizada recentemente para mostrar um novo argumento para a função,
enable_ordinal
, disponível no Banco de Dados SQL do Azure e em breve no SQL Server 2022 :Para ser claro, adicionar este argumento apenas adiciona uma
ordinal
coluna à saída indicando a sequência devalue
dentro da string original; ainda não garante que a saída será ordenada pelaordinal
coluna . Para isso, você ainda precisa adicionarORDER BY
à saída.