Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Varias propiedades afectan a la semántica de ordenación e igualdad de los datos textuales, incluida la distinción entre mayúsculas y minúsculas, la distinción de énfasis y el idioma base que se usa. Estas cualidades se expresan en SQL Server mediante la elección de intercalación para los datos. Para obtener una explicación más detallada de las intercalaciones en sí mismas, consulte Compatibilidad con intercalación y Unicode.
Las intercalaciones se aplican no solo a los datos almacenados en tablas de usuario, sino a todo el texto manejado por SQL Server, incluidos metadatos, objetos temporales, nombres de variables, etc. El manejo de esto varía entre las bases de datos contenidas y no contenidas. Este cambio no afectará a muchos usuarios, pero ayuda a proporcionar independencia de instancias y uniformidad. Pero esto también puede provocar alguna confusión, así como problemas para las sesiones que acceden tanto a bases de datos contenidas como no contenidas.
En este tema se aclara el contenido del cambio y se examinan las áreas en las que el cambio puede causar problemas.
Bases de datos no encapsuladas
Todas las bases de datos tienen una intercalación predeterminada (que se puede establecer al crear o modificar una base de datos). Esta intercalación se utiliza para todos los metadatos de la base de datos, así como como predeterminado para todas las columnas de texto dentro de la base de datos. Los usuarios pueden elegir una intercalación diferente para cualquier columna determinada mediante la COLLATE
cláusula .
Ejemplo 1
Por ejemplo, si estuviéramos trabajando en Beijing, podríamos usar una ordenación china:
ALTER DATABASE MyDB COLLATE Chinese_Simplified_Pinyin_100_CI_AS;
Ahora, si creamos una columna, su intercalación predeterminada será esta intercalación china, pero podemos elegir otra si queremos:
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
El conjunto de resultados es el siguiente:
name collation_name
--------------- ----------------------------------
mycolumn1 Chinese_Simplified_Pinyin_100_CI_AS
mycolumn2 Frisian_100_CS_AS
Esto parece relativamente sencillo, pero surgen varios problemas. Dado que la intercalación de una columna depende de la base de datos en la que se crea la tabla, surgen problemas con el uso de tablas temporales que se almacenan en tempdb
. La intercalación de tempdb
generalmente coincide con la intercalación de la instancia, aunque no necesariamente con la de la base de datos.
Ejemplo 2
Por ejemplo, considere la base de datos (china) anterior cuando se utiliza en una instancia con una intercalación Latin1_General.
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max)) ;
GO
A primera vista, estas dos tablas tienen el mismo esquema, pero dado que las intercalaciones de las bases de datos difieren, los valores son realmente incompatibles:
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt
El conjunto de resultados es el siguiente:
Mensaje 468, nivel 16, estado 9, línea 2
No se puede resolver el conflicto de intercalación entre "Latin1_General_100_CI_AS_KS_WS_SC" y "Chinese_Simplified_Pinyin_100_CI_AS" en la operación igual a.
Podemos corregirlo ordenando explícitamente la tabla temporal. SQL Server facilita esto al proporcionar la DATABASE_DEFAULT
palabra clave para la 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 ;
Esto ahora se ejecuta sin error.
También podemos ver el comportamiento dependiente de la ordenación con variables. Tenga en cuenta la siguiente función:
CREATE FUNCTION f(@x INT) RETURNS INT
AS BEGIN
DECLARE @I INT = 1
DECLARE @?? INT = 2
RETURN @x * @i
END;
Esta es una función bastante peculiar. En una intercalación que distingue mayúsculas de minúsculas, la cláusula de devolución @i no se puede enlazar a @I ni a @??. En una intercalación de Latin1_General sin distinción entre mayúsculas y minúsculas, @i se vincula a @I y la función devuelve 1. Pero en una intercalación turca que no distingue mayúsculas de minúsculas, @i enlaza con @??, y la función devuelve 2. Esto puede causar daños en una base de datos que se mueve entre instancias con intercalaciones diferentes.
Bases de datos independientes
Dado que un objetivo de diseño de las bases de datos independientes es hacer que se autocontenan, se debe romper la dependencia de la instancia y tempdb
las intercalaciones. Para ello, las bases de datos contenidas presentan el concepto de intercalación del catálogo. La intercalación de catálogo se usa para los metadatos del sistema y los objetos transitorios. A continuación se proporcionan los detalles.
En una base de datos contenida, la intercalación del catálogo Latin1_General_100_CI_AS_WS_KS_SC. Esta configuración de intercalación es la misma para todas las bases de datos contenidas en todas las instancias de SQL Server y no se puede cambiar.
La clasificación de la base de datos se mantiene, pero solo se utiliza como clasificación predeterminada para los datos de los usuarios. De forma predeterminada, la intercalación de base de datos es igual a la intercalación de base de datos modelo, pero el usuario puede cambiarla a través de un CREATE
comando o ALTER DATABASE
como con bases de datos no independientes.
Hay disponible una palabra clave nueva, CATALOG_DEFAULT
, en la COLLATE
cláusula . Se usa como acceso rápido a la intercalación actual de metadatos en bases de datos contenidas y no contenidas. Es decir, en una base de datos no contenida, CATALOG_DEFAULT
devolverá la intercalación actual de la base de datos, ya que los metadatos se intercalan usando la intercalación de la base de datos. En una base de datos independiente, estos dos valores pueden ser diferentes, ya que el usuario puede cambiar la intercalación de la base de datos para que no coincida con la intercalación del catálogo.
El comportamiento de varios objetos en bases de datos no contenidos y contenidos se resume en esta tabla:
Elemento | Base de datos no contenida | Base de datos contenida |
Datos de usuario (valor predeterminado) | BASE_DE_DATOS_POR_DEFECTO | BASE_DE_DATOS_POR_DEFECTO |
Datos temporales (valor predeterminado) | Intercalación de TempDB | BASE_DE_DATOS_POR_DEFECTO |
Metadatos | BASE_DE_DATOS_DEFECTO/CATÁLOGO_DEFECTO | CATÁLOGO_POR_DEFECTO |
Metadatos temporales | Intercalación de tempdb | CATÁLOGO_PREDEFINIDO |
variables | Intercalación de instancia | CATALOG_DEFAULT |
Etiquetas goto | Intercalación de instancia | CATALOG_DEFAULT |
Nombres de cursor | Intercalación de instancias | CATÁLOGO_POR_DEFECTO |
Si describimos el ejemplo de tabla temporal anteriormente mencionado, podemos ver que este comportamiento de intercalación elimina la necesidad de una cláusula explícita COLLATE
en la mayoría de las tablas temporales. En una base de datos independiente, este código ahora se ejecuta sin errores, incluso si las intercalaciones de la base de datos y de la instancia difieren:
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 ;
Esto funciona porque tanto T1_txt
como T2_txt
se intercalan en la intercalación de base de datos de la base de datos contenida.
Cruce entre contextos confinados y no confinados
Siempre que una sesión de una base de datos independiente permanezca contenida, debe permanecer dentro de la base de datos a la que se ha conectado. En este caso, el comportamiento es muy sencillo. Pero si una sesión cruza entre contextos contenidos y no contenidos, el comportamiento se vuelve más complejo, ya que los dos conjuntos de reglas deben ser conectados. Esto puede ocurrir en una base de datos parcialmente contenida, ya que un usuario puede USE
a otra base de datos. En este caso, la diferencia en las reglas de ordenación se controla mediante el siguiente principio.
- El comportamiento de intercalación de un lote viene determinado por la base de datos en la que comienza el lote.
Tenga en cuenta que esta decisión se toma antes de que se emita cualquier comando, incluido un inicial USE
. Es decir, si un lote comienza en una base de datos contenida, pero el primer comando es para USE
una base de datos no contenida, el comportamiento de intercalación contenida se seguirá usando para el lote. Dado esto, una referencia a una variable, por ejemplo, puede tener varios resultados posibles:
La referencia puede encontrar exactamente una coincidencia. En este caso, la referencia funcionará sin error.
Es posible que la referencia no encuentre una coincidencia en la clasificación actual, donde había una antes. Esto generará un error que indica que la variable no existe, aunque aparentemente se creó.
La referencia puede encontrar varias coincidencias que en un principio eran distintas. Esto también generará un error.
Lo mostraremos con algunos ejemplos. Para estos, se supone que hay una base de datos parcialmente contenida denominada MyCDB
con su intercalación de base de datos configurada en la intercalación predeterminada, Latin1_General_100_CI_AS_WS_KS_SC. Se supone que la intercalación de instancia es Latin1_General_100_CS_AS_WS_KS_SC
. Las dos intercalaciones solo difieren en sensibilidad a mayúsculas.
Ejemplo 1
En el ejemplo siguiente se muestra el caso en el que la referencia encuentra exactamente una coincidencia.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #a VALUES(1);
GO
USE master;
GO
SELECT * FROM #a;
GO
Results:
El conjunto de resultados es el siguiente:
x
-----------
1
En este caso, el #a identificado enlaza tanto en la intercalación de catálogo sin distinción entre mayúsculas y minúsculas como en la intercalación de instancia que distingue mayúsculas de minúsculas y el código funciona.
Ejemplo 2
En el siguiente ejemplo se ilustra el caso en el que la referencia no encuentra una coincidencia en la ordenación actual, donde anteriormente había una.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #A VALUES(1);
GO
Aquí, el #A se enlaza a #a en un sistema de colación predeterminado sin distinguir entre mayúsculas y minúsculas, y la inserción funciona.
El conjunto de resultados es el siguiente:
(1 row(s) affected)
Pero si seguimos el script...
USE master;
GO
SELECT * FROM #A;
GO
Se produce un error al intentar enlazar a #A en la intercalación de instancia que distingue mayúsculas de minúsculas;
El conjunto de resultados es el siguiente:
Mensaje 208, nivel 16, estado 0, línea 2
Nombre de objeto "#A" no válido.
Ejemplo 3
En el ejemplo siguiente se muestra el caso en el que la referencia encuentra varias coincidencias que originalmente eran distintas. En primer lugar, empezamos en tempdb
(que tiene la misma intercalación con distinción entre mayúsculas y minúsculas que nuestra instancia) y ejecutamos las siguientes instrucciones.
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
Esto se realiza correctamente, ya que las tablas son distintas en esta intercalación:
El conjunto de resultados es el siguiente:
(1 row(s) affected)
(1 row(s) affected)
Sin embargo, si pasamos a nuestra base de datos independiente, encontramos que ya no podemos enlazar a estas tablas.
USE MyCDB;
GO
SELECT * FROM #a;
GO
El conjunto de resultados es el siguiente:
Mensaje 12800, nivel 16, estado 1, línea 2
La referencia al nombre de tabla temporal "#a" es ambigua y no se puede resolver. Los posibles candidatos son "#a" y "#A".
Conclusión
El comportamiento de intercalación de las bases de datos contenidas difiere del de las bases de datos no contenidas. Este comportamiento suele ser beneficioso, lo que proporciona independencia de instancia y simplicidad. Algunos usuarios pueden tener problemas, especialmente cuando una sesión accede a bases de datos contenidas y no contenidas.