Eu tenho as seguintes variáveis e instrução CASE:
DECLARE @DATE_VALUE VARCHAR(20) = '4/29/2021'
DECLARE @CONVERT_CODE VARCHAR(1) = 'I'
SELECT CASE @CONVERT_CODE WHEN 'I' THEN DATEDIFF(day, '04/21/2021', @DATE_VALUE)
END AS ConvertedValue
Não há nada de especial nisso. Ele retorna 8 (int) como eu esperava.
No entanto, assim que adiciono à minha instrução CASE uma condicional que retorna um tipo de dados datetime, não recebo mais 8 (int), apesar de continuar usando "I" como o valor @CONVERT_CODE.
DECLARE @DATE_VALUE VARCHAR(20) = '4/29/2021'
DECLARE @CONVERT_CODE VARCHAR(1) = 'I'
SELECT CASE @CONVERT_CODE WHEN 'I' THEN DATEDIFF(day, '04/21/2021', @DATE_VALUE)
WHEN 'D' THEN GETDATE()
END AS ConvertedValue
Em vez disso, recebo o valor de data e hora de "1900-01-09 00:00:00.000"
Eu acho que "D" não deve ser avaliado porque, no SQL Server, uma vez que uma condição é avaliada como verdadeira ("I" neste caso), ela deve sair da instrução CASE - então não tenho certeza por que o tipo de dados "D" está afetando o tipo de dados de retorno geral. Além disso, não importa se eu inverter a ordem das condições e ainda usar "I":
DECLARE @DATE_VALUE VARCHAR(20) = '4/29/2021'
DECLARE @CONVERT_CODE VARCHAR(1) = 'I'
SELECT CASE @CONVERT_CODE WHEN 'D' THEN GETDATE()
WHEN 'I' THEN DATEDIFF(day, '04/21/2021', @DATE_VALUE)
END AS ConvertedValue
Estou esquecendo de algo?
A coluna definida por sua
CASE
expressão tem um tipo de dados, como todas as colunas.O SQL Server determina o tipo resultante da maneira usual, fazendo uso da precedência de tipo de dados . O tipo
datetime
tem uma precedência maior queinteger
.Você pode estar esperando que a
CASE
expressão retorne tipos diferentes em caminhos diferentes, mas isso não é possível (sql_variant
à parte)."1900-01-09 00:00:00.000" é a data número 8. O problema que você está enfrentando depende do fato de que o caso retornará apenas um tipo de dados. Ele avaliará cada expressão de caso, escolhendo um tipo de dados e convertendo implicitamente todos os resultados para esse tipo de dados.
No seu caso, um caso retorna int (datediff) e outro datetime, então o sql decidiu usar datetime e depois converteu 8 para datetime, que é o que você encontrou.
Essa decisão de tipo de dados é avaliada antes de aplicar a instrução case a cada linha selecionada.
Eu acho que "D" não deve ser avaliado porque, no SQL Server, uma vez que uma condição é avaliada como verdadeira ("I" neste caso), ela deve sair da instrução CASE
Muitos deveriam - tente dar uma olhada em Dirty Secrets of the CASE Expression de Aaron Bertrand.