A consulta a seguir converte uma única string de CSV compactado que representa 13 mil linhas por 2 colunas. A coluna A é um bigint. A coluna B é um inteiro pequeno.
declare
@dataCsv nvarchar(max) = '29653,36,19603,36,19604,36,29654,36'; -- abbreviated, actually 13k rows
with Input as
(
select Value,
Row = row_number() over (order by (select null)) - 1
from string_split(@dataCsv, ',') o
)
--insert into PubCache.TableName
select 78064 as CacheId,
convert(bigint, i.Value) as ObjectId,
convert(smallint, i2.Value) as BrandId
from Input i
inner hash join Input i2 -- hash to encourage string_split() only once per column
on i2.Row = i.Row + 1
where i.Row % 2 = 0
order by i.Row
Plano de Execução: https://www.brentozar.com/pastetheplan/?id=By0hYPmd6
Conforme mostrado no plano, a avaliação de convert() está ocorrendo antes da junção, então às vezes (dependendo do comprimento da entrada), ela falha com
A conversão do valor nvarchar '37645' estourou uma coluna INT2. Use uma coluna inteira maior.
Alterar temporariamente a conversão de smallint para int permite que a consulta seja concluída e a inspeção da saída da coluna BrandId mostra que ela sempre contém apenas o valor '36' para este exemplo.
Existe uma maneira simples de atrasar o convert(smallint, i2.Value) até depois da junção, para que apenas as posições CSV esperadas sejam convertidas?
Sei que existem outras maneiras de compactar um fluxo de string (como usar múltiplas variáveis ou entrelaçar diferentes caracteres divididos, etc.), mas não estou interessado em resolver este exemplo dessa forma para fins desta questão. Obrigado!