Alguém poderia me fornecer uma visão melhor sobre o recurso de modo de compatibilidade? Está se comportando diferente do que eu esperava.
Até onde eu entendo os modos de compatibilidade, trata-se da disponibilidade e suporte de certas estruturas de linguagem entre as várias versões do SQL Server.
Ele não afeta o funcionamento interno da versão do mecanismo de banco de dados. Ele tentaria impedir o uso de recursos e construções que ainda não estavam disponíveis em versões anteriores.
Acabei de criar um novo banco de dados com nível de compatibilidade 80 no SQL Server 2008 R2. Criou uma tabela com uma única coluna int e a preencheu com algumas linhas.
Em seguida, executou uma instrução select com uma row_number()
função.
Meu pensamento era que, como a função row_number foi introduzida apenas em 2005, isso geraria um erro no modo compat 80.
Mas para minha surpresa isso funcionou bem. Então, certamente, as regras de compatibilidade são avaliadas apenas quando você 'salva algo'. Então eu criei um proc armazenado para minha instrução row_number.
A criação do proc armazenado correu bem e posso executá-lo perfeitamente e obter resultados.
Alguém poderia me ajudar a entender melhor o funcionamento do modo de compatibilidade? Meu entendimento é obviamente falho.
Dos documentos :
Na minha interpretação, o modo de compatibilidade é sobre comportamento e análise de sintaxe, não para coisas como o analisador dizendo: "Ei, você não pode usar
ROW_NUMBER()
!" Às vezes, o nível de compatibilidade mais baixo permite que você continue fugindo com a sintaxe não mais suportada e, às vezes, impede que você use novas construções de sintaxe. A documentação lista vários exemplos explícitos, mas aqui estão algumas demonstrações:Passando funções internas como argumentos de função
Este código funciona no nível de compatibilidade 90+:
Mas em 80 rende:
O problema específico aqui é que em 80 você não tem permissão para passar uma função interna para uma função. Se você quiser permanecer no modo de compatibilidade 80, poderá contornar isso dizendo:
Passando um tipo de tabela para uma função com valor de tabela
Semelhante ao acima, você pode obter um erro de sintaxe ao usar um TVP e tentar passá-lo para uma função com valor de tabela. Isso funciona em níveis de compatibilidade modernos:
No entanto, altere o nível de compatibilidade para 80 e execute as três últimas linhas novamente; você recebe esta mensagem de erro:
Não é realmente nenhuma boa solução em cima da minha cabeça, além de atualizar o nível de compatibilidade ou obter os resultados de uma maneira diferente.
Usando nomes de coluna qualificados em APPLY
No modo de compatibilidade 90 ou superior, você pode fazer isso sem problemas:
No entanto, no modo de compatibilidade 80, a coluna qualificada entregue à função gera um erro de sintaxe genérico:
ORDER BY um alias que corresponde a um nome de coluna
Considere esta consulta:
No modo de compatibilidade 80, os resultados são os seguintes:
No modo de compatibilidade 90, os resultados são bem diferentes:
A razão? No modo de compatibilidade 80, o prefixo da tabela é totalmente ignorado, portanto, é ordenado pela expressão definida pelo alias na
SELECT
lista. Nos níveis de compatibilidade mais recentes, o prefixo da tabela é considerado, de modo que o SQL Server realmente usará essa coluna na tabela (se for encontrada). Se oORDER BY
alias não for encontrado na tabela, os níveis de compatibilidade mais recentes não perdoam a ambiguidade. Considere este exemplo:O resultado é ordenado pela
myname
expressão em 80, pois novamente o prefixo da tabela é ignorado, mas em 90 gera esta mensagem de erro:Tudo isso também é explicado na documentação :
ORDER BY algo que não está na lista SELECT
No modo de compatibilidade 90 você não pode fazer isso:
Resultado:
Em 80, porém, você ainda pode usar essa sintaxe.
Junções externas antigas e nojentas
O modo 80 também permite que você use a antiga e obsoleta sintaxe de junção externa (
*=/=*
):No SQL Server 2008 / 2008 R2, se você estiver em 90 ou superior, receberá esta mensagem detalhada:
No SQL Server 2012, isso não é mais uma sintaxe válida e produz o seguinte:
Claro que no SQL Server 2012 você não pode mais contornar esse problema usando o nível de compatibilidade, já que 80 não é mais suportado. Se você atualizar um banco de dados no modo de compatibilidade 80 (por atualização in-loco, desanexar/anexar, backup/restaurar, envio de log, espelhamento, etc.), ele será atualizado automaticamente para 90 para você.
Dicas de mesa sem COM
No modo de compatibilidade 80, você pode usar o seguinte e a dica da tabela será observada:
Em 90+, isso
NOLOCK
não é mais uma dica de tabela, é um alias. Caso contrário, isso funcionaria:Mas não:
Agora, para provar que o comportamento não é observado no primeiro exemplo no modo de compatibilidade 90, use o AdventureWorks (certificando-se de que está em um nível de compatibilidade mais alto) e execute o seguinte:
Este é particularmente problemático porque o comportamento muda sem uma mensagem de erro ou mesmo um erro. E também é algo que o consultor de atualização e outras ferramentas podem nem perceber, já que, pelo que sabe, é um alias de tabela.
Conversões envolvendo novos tipos de data/hora
Os novos tipos de data/hora introduzidos no SQL Server 2008 (por exemplo
date
, edatetime2
) suportam um intervalo muito maior do que o originaldatetime
esmalldatetime
). As conversões explícitas de valores fora do intervalo suportado falharão, independentemente do nível de compatibilidade, por exemplo:Rendimentos:
No entanto, as conversões implícitas funcionarão nos níveis de compatibilidade mais recentes. Por exemplo, isso funcionará em 100+:
Mas em 80 (e também em 90), gera um erro semelhante ao acima:
Cláusulas FOR redundantes em gatilhos
Este é um cenário obscuro que surgiu aqui . No modo de compatibilidade 80, isso será bem-sucedido:
Na compatibilidade 90 e superior, isso não é mais analisado e, em vez disso, você recebe a seguinte mensagem de erro:
PIVOT/UNPIVOT
Algumas formas de sintaxe não funcionarão abaixo de 80 (mas funcionam bem em 90+):
Isso rende:
Para algumas soluções alternativas, incluindo
CROSS APPLY
, consulte estas respostas .Novas funções integradas
Tente usar novas funções como
TRY_CONVERT()
em um banco de dados com nível de compatibilidade < 110. Elas simplesmente não são reconhecidas lá.Resultado:
Recomendação
Only use 80 compatibility mode if you actually need it. Since it will no longer be available in the next version after 2008 R2, the last thing you want to do is write code in this compat level, rely on the behaviors you see, and then have a whole bunch of breakage when you can no longer use that compat level. Be forward thinking and don't try to paint yourself into a corner by buying time to continue using old, deprecated syntax.
Compatibility Levels are only present to allow a controlled migration from an earlier version of SQL Server. Compat Level 90 does not preclude using new features, it simply means certain aspects of the database are retained in a way that is compatible with how SQL Server 2005 worked.
See http://msdn.microsoft.com/en-us/library/bb510680.aspx for more info.