Estou coçando a cabeça sobre isso nos últimos dias - simplesmente não consigo ver por que um procedimento funciona em um ambiente, mas falha em outro devido a um erro de conversão (mesmos dados, mesmo código).
O plano para (uma versão fortemente reduzida) do servidor de trabalho está aqui: https://www.brentozar.com/pastetheplan/?id=B1jZWTfOf
(Isso não parece estar funcionando, então carreguei o XML do plano para pastebin aqui: https://pastebin.com/47Q6nniw )
Um pouco de plano de fundo para as colunas relevantes que estão causando o problema:
A tabela propertyInst contém uma coluna chamada ValueStr, que é um tipo de dados nvarchar. A tabela GeneralLedgerCode tem um id de coluna do tipo de dados int. Nossos desenvolvedores estão tentando unir as duas tabelas. A coluna ValueStr contém dados de texto, dados XML, dados int, dados decimais etc. Obviamente, decidimos adicionar uma função para garantir que apenas números inteiros sejam analisados (ISNUMERIC(ValueStr) = 1). O que não percebemos é que isso também tentaria converter quaisquer valores decimais - isso está causando um erro de conversão na produção da natureza:
A conversão falhou ao converter o valor nvarchar '0.1' para o tipo de dados int.
Minha pergunta aqui é, dado que o Table Scan da tabela propertyInst estará pegando todos os valores numéricos, incluindo decimais, por que a conversão implícita no operador escalar não falha com o mesmo erro de conversão? A saída da consulta ISNUMERIC retorna alguns desses decimais. Não consigo ver como o plano em anexo está funcionando.
Um operador de conversão implícito nunca falha completamente e o erro de conversão é proveniente do teste residual no operador de correspondência de hash? Então, novamente, como o valor poderia chegar ao operador quando falharia na conversão implícita?
Como uma pequena ajuda, a imagem do plano está aqui, com o Compute Scalar sobre o qual estou perguntando circulado.
Além disso, posso ver que não há linhas reais registradas no operador escalar - isso significa que o mecanismo decidiu não usar esse operador específico em tempo de execução devido ao erro de conversão?
Qualquer ajuda seria apreciada.
O cálculo do operador escalar de computação é adiado para quando ele é realmente usado (o resíduo de teste de ID do nó = 1) e as linhas que teriam falhado para você são filtradas pela correspondência de hash anterior (ID do nó = 3).
Dê uma olhada em Compute Scalars, Expressions and Execution Plan Performance de Paul White para obter mais informações.
Não há indicação nos planos de execução de que a avaliação de uma expressão seja adiada ou quando (em qual nó) ela foi realmente avaliada. Você normalmente pode codificar defensivamente em torno disso usando
CASE
(que vem com uma garantia de ordem de avaliação) e/ouTRY_CONVERT
.Feedback relacionado da Microsoft: O SQL Server não deve gerar erros ilógicos