Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Várias propriedades afetam a ordem de classificação e a semântica de igualdade dos dados textuais, incluindo a sensibilidade a maiúsculas e minúsculas, a sensibilidade a acentos e a linguagem base que está sendo utilizada. Essas qualidades são expressas no SQL Server por meio da escolha de ordenação para os dados. Para obter uma discussão mais detalhada sobre ordenações em si, consulte Ordenação e Suporte Unicode.
As ordenações se aplicam não apenas aos dados armazenados em tabelas de usuário, mas a todos os textos manipulados pelo SQL Server, incluindo metadados, objetos temporários, nomes de variáveis etc. O tratamento deles difere em bancos de dados independentes e não contidos. Essa alteração não afetará muitos usuários, mas ajudará a fornecer independência e uniformidade da instância. Mas isso também pode causar alguma confusão, bem como problemas para sessões que acessam bancos de dados independentes e não contidos.
Este tópico esclarece o conteúdo da alteração e examina áreas em que a alteração pode causar problemas.
Bancos de dados não contidos
Todos os bancos de dados têm uma ordenação padrão (que pode ser definida ao criar ou alterar um banco de dados. Essa ordenação é usada para todos os metadados no banco de dados, bem como o padrão para todas as colunas de cadeia de caracteres dentro do banco de dados. Os usuários podem escolher uma ordenação diferente para qualquer coluna específica usando a COLLATE cláusula.
Exemplo 1
Por exemplo, se estivéssemos trabalhando em Pequim, poderíamos usar uma ordenação chinesa:
ALTER DATABASE MyDB COLLATE Chinese_Simplified_Pinyin_100_CI_AS;
Agora, se criarmos uma coluna, sua ordenação padrão será essa ordenação chinesa, mas podemos escolher outra se quisermos:
CREATE TABLE MyTable
(mycolumn1 nvarchar,
mycolumn2 nvarchar COLLATE Frisian_100_CS_AS);
GO
SELECT name, collation_name
FROM sys.columns
WHERE name LIKE 'mycolumn%' ;
GO
Aqui está o conjunto de resultados.
name collation_name
--------------- ----------------------------------
mycolumn1 Chinese_Simplified_Pinyin_100_CI_AS
mycolumn2 Frisian_100_CS_AS
Isso parece relativamente simples, mas surgem vários problemas. Como a ordenação de uma coluna depende do banco de dados no qual a tabela é criada, surgem problemas com o uso de tabelas temporárias armazenadas em tempdb. A ordenação de tempdb geralmente corresponde à ordenação da instância e não precisa corresponder à ordenação do banco de dados.
Exemplo 2
Por exemplo, considere o banco de dados (chinês) acima quando usado em uma instância com uma ordenação Latin1_General :
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max)) ;
GO
À primeira vista, essas duas tabelas parecem ter o mesmo esquema, mas como as ordenações dos bancos de dados diferem, os valores são realmente incompatíveis:
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt
Aqui está o conjunto de resultados.
Msg 468, Nível 16, Estado 9, Linha 2
Não é possível resolver o conflito de ordenação entre "Latin1_General_100_CI_AS_KS_WS_SC" e "Chinese_Simplified_Pinyin_100_CI_AS" na operação de igualdade.
Podemos corrigir isso ordenando explicitamente a tabela temporária. O SQL Server facilita um pouco o fornecimento da DATABASE_DEFAULT palavra-chave para a COLLATE cláusula.
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max) COLLATE DATABASE_DEFAULT);
GO
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt ;
Isso agora é executado sem erros.
Também podemos ver o comportamento dependente de classificação com variáveis. Considere a seguinte função:
CREATE FUNCTION f(@x INT) RETURNS INT
AS BEGIN
DECLARE @I INT = 1
DECLARE @?? INT = 2
RETURN @x * @i
END;
Essa é uma função bastante peculiar. Em uma ordenação que diferencia maiúsculas de minúsculas, a cláusula de retorno @i não pode ser associada a um @I ou @??. Em uma ordenação Latin1_General que não diferencia maiúsculas de minúsculas, @i associa-se a @I, e a função retorna 1. Mas, em uma ordenação turca que não diferencia maiúsculas de minúsculas, @i associa-se a @??, e a função retorna 2. Isso pode causar estragos em um banco de dados que se move entre instâncias com ordenações diferentes.
Bancos de dados independentes
Como um objetivo de design de bancos de dados autossuficientes é torná-los autocontidos, a dependência das instâncias e das ordenações de tempdb deve ser eliminada. Para fazer isso, os bancos de dados contidos introduzem o conceito da ordenação de catálogo. A ordenação de catálogo é usada para metadados do sistema e objetos transitórios. Os detalhes são fornecidos abaixo.
Em um banco de dados independente, a ordenação do catálogo Latin1_General_100_CI_AS_WS_KS_SC. Essa ordenação é a mesma para todos os bancos de dados contidos em todas as instâncias do SQL Server e não pode ser alterada.
A ordenação do banco de dados é mantida, mas é usada apenas como a ordenação padrão para dados do usuário. Por padrão, a ordenação de banco de dados é igual à ordenação de banco de dados modelo, mas pode ser alterada pelo usuário por meio de um CREATE comando ou ALTER DATABASE como com bancos de dados não contidos.
Uma nova palavra-chave, CATALOG_DEFAULT, está disponível na cláusula COLLATE. Isso é usado como um atalho para a ordenação atual de metadados em bancos de dados contidos e não contidos. Ou seja, em um banco de dados não contido, CATALOG_DEFAULT retornará a ordenação de banco de dados atual, uma vez que os metadados são agrupados na ordenação do banco de dados. Em um banco de dados independente, esses dois valores podem ser diferentes, pois o usuário pode alterar a ordenação do banco de dados para que ele não corresponda à ordenação do catálogo.
O comportamento de vários objetos em bancos de dados não contidos e independentes é resumido nesta tabela:
| Item | Banco de dados não contido | Banco de dados contido |
| Dados do usuário (padrão) | DATABASE_DEFAULT | DATABASE_DEFAULT |
| Dados temporários (padrão) | Ordenação de TempDB | Banco de dados padrão |
| Metadados | CONFIGURAÇÃO_PADRÃO_DO_BANCO_DE_DADOS/CONFIGURAÇÃO_PADRÃO_DO_CATÁLOGO | CATALOG_DEFAULT |
| Metadados temporários | Ordenação do banco de dados tempdb | CATÁLOGO_PADRÃO |
| Variáveis | Ordenação e comparação de instância | CATALOGO_PADRAO |
| Rótulos "goto" | Classificação de instância | CATÁLOGO_PADRÃO |
| Nomes de cursor | Ordenação de instância | CATÁLOGO_PADRÃO |
Se o exemplo de tabela temporária for descrito anteriormente, poderemos ver que esse comportamento de ordenação elimina a necessidade de uma cláusula explícita COLLATE na maioria das utilizações da tabela temporária. Em um banco de dados independente, esse código agora é executado sem erros, mesmo que as ordenações de banco de dados e instância diferem:
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max));
GO
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt ;
Isso funciona porque ambos, T1_txt e T2_txt, são agrupados de acordo com a ordenação da colação do banco de dados contido.
Cruzando entre contextos contidos e não contidos
Enquanto uma sessão em um banco de dados independente permanecer contida, ela deverá permanecer no banco de dados ao qual se conectou. Nesse caso, o comportamento é muito simples. No entanto, se uma sessão cruza entre contextos contidos e não contidos, o comportamento se torna mais complexo, pois os dois conjuntos de regras devem ser reconciliados. Isso pode acontecer em um banco de dados parcialmente contido, já que um usuário pode USE acessar outro banco de dados. Nesse caso, a diferença nas regras de ordenação é tratada pelo princípio a seguir.
- O comportamento de ordenação de um lote é determinado pelo banco de dados no qual o lote começa.
Observe que essa decisão é tomada antes que todos os comandos sejam emitidos, incluindo um inicial USE. Ou seja, se um lote começar em um banco de dados independente, mas o primeiro comando for um USE para um banco de dados não contido, o comportamento de ordenação independente ainda será usado para o lote. Considerando isso, uma referência a uma variável, por exemplo, pode ter vários resultados possíveis:
A referência pode encontrar exatamente uma coincidência. Nesse caso, a referência funcionará sem erros.
A referência pode não encontrar uma correspondência na ordenação atual em que havia uma antes. Isso gerará um erro indicando que a variável não existe, mesmo que tenha sido aparentemente criada.
A referência pode achar várias correspondências que eram originalmente distintas. Isso também gerará um erro.
Ilustraremos isso com alguns exemplos. Para eles, presumimos que haja um banco de dados parcialmente contido nomeado MyCDB com sua ordenação de banco de dados definida como a ordenação padrão, Latin1_General_100_CI_AS_WS_KS_SC. Presumimos que a ordenação da instância seja Latin1_General_100_CS_AS_WS_KS_SC. As duas ordenações diferem apenas em sensibilidade a maiúsculas e minúsculas.
Exemplo 1
O exemplo a seguir ilustra o caso em que a referência encontra exatamente uma correspondência.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #a VALUES(1);
GO
USE master;
GO
SELECT * FROM #a;
GO
Results:
Aqui está o conjunto de resultados.
x
-----------
1
Nesse caso, o #a identificado se associa tanto ao ordenamento do catálogo que não diferencia maiúsculas de minúsculas quanto ao ordenamento da instância que diferencia maiúsculas de minúsculas, e o código funciona.
Exemplo 2
O exemplo a seguir ilustra o caso em que a referência não encontra uma correspondência na classificação atual, onde havia uma anteriormente.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #A VALUES(1);
GO
Aqui, o #A se associa a #a na ordenação padrão que não diferencia maiúsculas de minúsculas e a inserção funciona,
Aqui está o conjunto de resultados.
(1 row(s) affected)
Mas se continuarmos o script...
USE master;
GO
SELECT * FROM #A;
GO
Obtemos um erro ao tentar associar a #A na ordenação da instância que diferencia maiúsculas de minúsculas;
Aqui está o conjunto de resultados.
Msg 208, Nível 16, Estado 0, Linha 2
Nome de objeto inválido '#A'.
Exemplo 3
O exemplo a seguir ilustra o caso em que a referência encontra várias correspondências que eram originalmente distintas. Primeiro, começamos em tempdb (que tem a mesma ordenação que diferencia maiúsculas de minúsculas que nossa instância) e executamos as instruções a seguir.
USE tempdb;
GO
CREATE TABLE #a(x int);
GO
CREATE TABLE #A(x int);
GO
INSERT INTO #a VALUES(1);
GO
INSERT INTO #A VALUES(2);
GO
Isso é bem-sucedido, uma vez que as tabelas são distintas nesta ordenação:
Aqui está o conjunto de resultados.
(1 row(s) affected)
(1 row(s) affected)
No entanto, se passarmos para nosso banco de dados independente, descobriremos que não podemos mais nos associar a essas tabelas.
USE MyCDB;
GO
SELECT * FROM #a;
GO
Aqui está o conjunto de resultados.
Msg 12800, Nível 16, Estado 1, Linha 2
A referência ao nome da tabela temporária '#a' é ambígua e não pode ser resolvida. Os possíveis candidatos são "#a" e "#A".
Conclusão
O comportamento de ordenação de bancos de dados independentes difere sutilmente daquele em bancos de dados não contidos. Esse comportamento geralmente é benéfico, proporcionando independência das instâncias e simplicidade. Alguns usuários podem ter problemas, especialmente quando uma sessão acessa bancos de dados independentes e não contidos.