;WITH
cte_Date ( DateCode_FK ) AS (
SELECT DATEADD( DAY,
1 - ROW_NUMBER() OVER (
ORDER BY so1.object_id ),
GETDATE() )
FROM sys.objects so1
CROSS APPLY sys.objects so2 )
SELECT TOP 10 d.DateCode_FK
FROM cte_Date d
ORDER BY d.DateCode_FK DESC;
Nada muito interessante, mas estou recebendo uma mensagem de erro se eu executá-la com a ORDER BY
cláusula:
Msg 517, Nível 16, Estado 1, Linha 4
Adicionar um valor a uma coluna 'datetime' causou um estouro.
No entanto, sem a ORDER BY
cláusula, funciona muito bem. Além disso, se eu executar a consulta em outros catálogos contidos na mesma instância no mesmo servidor, a consulta funcionará bem com ou sem a ORDER BY
cláusula.
Examinei as opções de configuração e os níveis de compatibilidade entre o catálogo afetado e um catálogo no qual a consulta é executada conforme o esperado, mas não encontrei nada que pudesse justificar a diferença. Alguém mais se deparou com um problema semelhante? Posso contornar isso por enquanto, mas, idealmente, preciso ser capaz de corrigir o problema, seja ele qual for.
Dica potencial - se você tiver um número relativamente grande de objetos em um catálogo (> 5000), você poderá reproduzir o erro... Isso está ocorrendo no meu maior catálogo e parece que se eu incluir um TOP em o CTE, o problema ORDER BY desaparece.
O SQL Server não garante o tempo ou o número de avaliações para expressões escalares. Isso significa que uma consulta que pode lançar um erro dependendo da ordem das operações em um plano de execução pode (ou não) fazê-lo em tempo de execução.
O script usa
CROSS APPLY
whereCROSS JOIN
provavelmente pretendido, mas o ponto é que o número potencial de linhas sobre o qualROW_NUMBER
é calculado depende do tamanho dosys.objects
produto cruzado.Para um banco de dados com objetos suficientes, um estouro para o
DATEADD
resultado é um risco esperado. Por exemplo, isso pode ser reproduzido usando o banco de dados de exemplo AdventureWorks , que possui 637 entradas em formatosys.objects
. O tamanho do produto vetorial é 637 * 637 = 405.769; o seguinte lança um erro de estouro:Pode-se argumentar que não há necessidade de materializar o resultado de uma expressão para linhas que não são retornadas (e, portanto, não geram um erro), mas não é assim que as coisas funcionam hoje.
Considerar:
ROW_NUMBER
dará o menor valor paraDateCode_FK
naDATEADD(DAY, 1 - ROW_NUMBER()...
expressãoORDER BY
éDateCode_FK DESC
Se o otimizador contivesse lógica para raciocinar que números de linha mais baixos levam a valores mais
DateCode_FK
altos, uma classificação explícita não seria necessária. Apenas dez linhas precisariam fluir pelo plano de execução. Os dez números de linha mais baixos são garantidos para produzir os dezDateCode_FK
valores mais altos.Independentemente disso, mesmo quando um Sort está presente, o argumento é que o SQL Server não deve gerar um erro porque nenhuma das dez linhas realmente retornadas está associada a um erro de estouro. Como eu disse acima, "não é assim que as coisas funcionam hoje" .
Uma formulação alternativa que evita o erro (embora ainda não seja garantido - veja minha observação de abertura), torna a numeração de linhas determinística e usa
CROSS JOIN
:Cole o Plano
Ressaca de feriado, eu acho.
O
ORDER BY
na parte externa da consulta às vezes força a construção da lista completa para ordená-la corretamente. Com mais de 5 mil linhas retornadas desys.objects
, oDATETIME
tipo de dados transborda ao tentar criar datas com mais de 25 milhões de dias.