Contained Database Collations
Gilt für: SQL Server Azure SQL Managed Instance
Auf die Sortierreihenfolge und die Gleichheitssemantik von Textdaten wirken sich verschiedene Eigenschaften aus, u. a. die Berücksichtigung der Groß- und Kleinschreibung, die Berücksichtigung von Akzenten sowie die verwendete Basissprache. Diese Eigenschaften werden für SQL Server durch die ausgewählte Sortierung der Daten ausgedrückt. Eine ausführliche Erläuterung zu Sortierungen finden Sie unter Sortierung und Unicode-Unterstützung.
Sortierungen gelten nicht nur für in Benutzertabellen gespeicherte Daten, sondern für jeden von SQL Server behandelten Text, einschließlich Metadaten, temporäre Objekte, Variablennamen usw. Deren Behandlung variiert in eigenständigen und abhängigen Datenbanken. Diese Änderung wirkt sich nicht auf viele Benutzer aus. Stattdessen trägt sie zu Unabhängigkeit von Instanzen und Einheitlichkeit bei. Dies verursacht jedoch möglicherweise auch etwas Verwirrung sowie Probleme bei Sitzungen, in denen sowohl auf enthaltene als auch auf nicht enthaltene Datenbanken zugegriffen wird.
Das Sortierungsverhalten enthaltener Datenbanken unterscheidet sich leicht von dem nicht enthaltener Datenbanken. Dieses Verhalten ist im Allgemeinen vorteilhaft und trägt zu Unabhängigkeit von Instanzen sowie Einfachheit bei. Für einige Benutzer können Probleme auftreten, insbesondere dann, wenn in einer Sitzung sowohl auf enthaltene als auch auf nicht enthaltene Datenbanken zugegriffen wird.
In diesem Artikel wird das Wesen der Änderung erläutert. Zudem werden einige Bereiche beschrieben, in denen sie möglicherweise Probleme verursacht.
Hinweis
Für Azure SQL-Datenbank unterscheiden sich Sortierungen für eigenständige Datenbanken. Die Datenbanksortierung und Katalogsortierung kann bei der Datenbankerstellung festgelegt und nicht aktualisiert werden. Geben Sie eine Sortierung für Daten (COLLATE
) und eine Katalogsortierung für Systemmetadaten und Objektbezeichner (CATALOG_COLLATION
) an. Weitere Informationen finden Sie unter CREATE DATABASE.
Abhängige Datenbanken
Alle Datenbanken weisen eine Standardsortierung auf, die beim Erstellen oder Ändern einer Datenbank festgelegt werden kann. Diese Sortierung wird für sämtliche Metadaten in der Datenbank sowie als Standard für alle Zeichenfolgenspalten in der Datenbank verwendet. Benutzer können mit der COLLATE
-Klausel für jede einzelne Spalte eine andere Sortierung auswählen.
Beispiel 1
Wenn Sie z. B. in Peking arbeiten, kann eine chinesische Sortierung verwendet werden:
ALTER DATABASE MyDB COLLATE Chinese_Simplified_Pinyin_100_CI_AS;
Wenn nun eine Spalte erstellt wird, ist deren Standardsortierung diese chinesische Sortierung. Gegebenenfalls kann jedoch eine andere Sortierung ausgewählt werden:
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
Hier sehen Sie das Ergebnis.
name collation_name
--------------- ----------------------------------
mycolumn1 Chinese_Simplified_Pinyin_100_CI_AS
mycolumn2 Frisian_100_CS_AS
Dies erscheint relativ einfach, es treten jedoch mehrere Probleme auf. Da die Sortierung für eine Spalte von der Datenbank abhängt, in der die Tabelle erstellt wurde, treten Probleme mit der Verwendung von temporären Tabellen auf, die in tempdb
gespeichert werden. Die Sortierung von tempdb
entspricht normalerweise der Sortierung für die Instanz. Diese muss nicht unbedingt der Datenbanksortierung entsprechen.
Beispiel 2
Betrachten Sie beispielsweise die obige (chinesische) Datenbank, wenn diese in einer Instanz mit der Sortierung Latin1_General verwendet wird:
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max)) ;
GO
Auf den ersten Blick weisen diese beiden Tabellen dasselbe Schema auf. Da sich aber die Sortierungen der Datenbanken unterscheiden, sind die Werte tatsächlich nicht kompatibel:
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt
Hier sehen Sie das Ergebnis.
Meldung 468, Ebene 16, Status 9, Zeile 2
Ein Sortierungskonflikt zwischen „Latin1_General_100_CI_AS_KS_WS_SC“ und „Chinese_Simplified_Pinyin_100_CI_AS“ im Equal To-Vorgang kann nicht aufgelöst werden.
Dies kann durch das explizite Sortieren der temporären Tabelle korrigiert werden. erleichtert diesen Vorgang etwas, indem das DATABASE_DEFAULT
-Schlüsselwort für die COLLATE
-Klausel bereitgestellt wird.
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 ;
Die Ausführung erfolgt nun ohne Fehler.
Das sortierungsabhängige Verhalten ist auch bei Variablen zu beobachten. Betrachten Sie die folgende Funktion:
CREATE FUNCTION f(@x INT) RETURNS INT
AS BEGIN
DECLARE @I INT = 1
DECLARE @İ INT = 2
RETURN @x * @i
END;
Dies ist eine relativ spezielle Funktion. In einer Sortierung mit Berücksichtigung der Groß-/Kleinschreibung kann für das @i
in der Rückgabeklausel keine Bindung an @I
oder @İ
hergestellt werden. Bei der Sortierung „Latin1_General“ ohne Berücksichtigung der Groß-/Kleinschreibung wird @i
an @I
gebunden, und die Funktion gibt 1
zurück. Bei der Sortierung „Turkish“ ohne Berücksichtigung der Groß-/Kleinschreibung wird jedoch @i
an @İ
gebunden, und die Funktion gibt 2 zurück. Dies kann erhebliche Beschädigungen in einer Datenbank verursachen, bei der zwischen Instanzen mit unterschiedlichen Sortierungen gewechselt wird.
Eigenständige Datenbanken
Da eines der Entwurfsziele bei eigenständigen Datenbanken darin besteht, diese in sich abgeschlossen einzurichten, muss die Abhängigkeit von Instanzen und tempdb
-Sortierungen abgetrennt werden. Hierzu wurde für eigenständige Datenbanken das Konzept der Katalogsortierung eingeführt. Die Katalogsortierung wird für Systemmetadaten und vorübergehende Objekte verwendet. Einzelheiten hierzu finden Sie weiter unten.
In einer eigenständigen Datenbank ist die Katalogsortierung Latin1_General_100_CI_AS_WS_KS_SC. Diese Sortierung ist für alle eigenständigen Datenbanken in allen Instanzen von SQL Server identisch und kann nicht geändert werden.
Die Datenbanksortierung wird beibehalten, sie wird jedoch nur für Benutzerdaten als Standardsortierung verwendet. Standardmäßig entspricht die Datenbanksortierung der model
-Datenbanksortierung, sie kann jedoch vom Benutzer wie bei abhängigen Datenbanken durch einen CREATE
- oder ALTER DATABASE
-Befehl geändert werden.
Das neue Schlüsselwort CATALOG_DEFAULT
ist in der COLLATE
-Klausel verfügbar. Diese wird als Verknüpfung zur aktuellen Sortierung der Metadaten in enthaltenen und nicht enthaltenen Datenbanken verwendet. Das heißt, in einer nicht enthaltenen Datenbank gibt CATALOG_DEFAULT
die aktuelle Datenbanksortierung zurück, da Metadaten in der Datenbanksortierung sortiert werden. In einer enthaltenen Datenbank können sich diese zwei Werte unterscheiden, da der Benutzer die Datenbanksortierung ändern kann, sodass sie von der Katalogsortierung abweicht.
Das Verhalten verschiedener Objekte in nicht enthaltenen und enthaltenen Datenbanken wird in dieser Tabelle zusammengefasst:
Artikel | Nicht enthaltene Datenbank | Enthaltene Datenbank |
---|---|---|
Benutzerdaten (Standard) | DATABASE_DEFAULT | DATABASE_DEFAULT |
Temp-Daten (Standard) | tempdb Sortierung |
DATABASE_DEFAULT |
Metadaten | DATABASE_DEFAULT/CATALOG_DEFAULT | CATALOG_DEFAULT |
Temporäre Metadaten | tempdb Sortierung |
CATALOG_DEFAULT |
Variablen | Instanzsortierung | CATALOG_DEFAULT |
Goto-Bezeichnungen | Instanzsortierung | CATALOG_DEFAULT |
Cursornamen | Instanzsortierung | CATALOG_DEFAULT |
Im zuvor beschriebenen Beispiel für eine temporäre Tabelle ist ersichtlich, dass dieses Sortierverhalten bei den meisten Verwendungen temporärer Tabellen eine explizite COLLATE
-Klausel überflüssig macht. In einer enthaltenen Datenbank wird dieser Code nun ohne Fehler ausgeführt, selbst wenn sich die Datenbanksortierung und die Instanzsortierung unterscheiden:
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 ;
Dies funktioniert, da sowohl T1_txt
als auch T2_txt
in der Datenbanksortierung der enthaltenen Datenbank sortiert werden.
Wechsel zwischen eingeschlossenen und nicht eingeschlossenen Kontexten
Solange sich eine Sitzung auf eine enthaltene Datenbank beschränkt, darf die Datenbank nicht verlassen werden, mit der eine Verbindung besteht. In diesem Fall ist das Verhalten sehr einfach. Wenn jedoch in einer Sitzung zwischen einem enthaltenen und einem nicht enthaltenen Kontext gewechselt wird, ist das Verhalten komplexer, da die beiden Regelsätze überbrückt werden müssen. Dies kann in einer teilweise enthaltenen Datenbank der Fall sein, da ein Benutzer mit USE
auf eine andere Datenbank zugreifen kann. In diesem Fall werden die Unterschiede zwischen den Sortierungsregeln gemäß dem folgenden Prinzip behandelt.
- Das Sortierungsverhalten für einen Batch wird von der Datenbank bestimmt, in der der Batch beginnt.
Beachten Sie, dass diese Entscheidung getroffen wird, bevor Befehle ausgegeben werden (auch der anfängliche USE
-Befehl). Das heißt, wenn ein Batch in einer eigenständigen Datenbank beginnt, der erste Befehl jedoch ein USE
-Befehl für eine abhängige Datenbank ist, wird dennoch das Sortierungsverhalten der eigenständigen Datenbank für den Batch verwendet. Angesichts dessen kann beispielsweise ein Verweis auf eine Variable mehrere mögliche Ergebnisse haben:
Durch den Verweis kann genau eine Übereinstimmung gefunden werden. In diesem Fall funktioniert der Verweis ohne Fehler.
Durch den Verweis wird möglicherweise keine Übereinstimmung in der aktuellen Sortierung gefunden, obwohl zuvor eine vorhanden war. Dadurch wird ein Fehler ausgelöst, der angibt, dass die Variable nicht vorhanden ist, auch wenn diese offensichtlich erstellt wurde.
Durch den Verweis können mehrere Übereinstimmungen gefunden werden, die sich ursprünglich voneinander unterschieden haben. Auch hierdurch wird ein Fehler ausgelöst.
Dies wird im Folgenden anhand einiger Beispiele veranschaulicht. Dabei wird angenommen, dass eine teilweise eigenständige Datenbank mit dem Namen MyCDB
vorhanden ist, deren Datenbanksortierung auf die Standardsortierung Latin1_General_100_CI_AS_WS_KS_SCfestgelegt ist. Wir nehmen an, dass die instanzsortierung Latin1_General_100_CS_AS_WS_KS_SCist. Die beiden Sortierungen unterscheiden sich nur hinsichtlich der Berücksichtigung der Groß- und Kleinschreibung.
Beispiel 1
Im folgenden Beispiel wird der Fall veranschaulicht, bei dem durch den Verweis genau eine Übereinstimmung gefunden wird.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #a VALUES(1);
GO
USE master;
GO
SELECT * FROM #a;
GO
Results:
Hier sehen Sie das Ergebnis.
x
-----------
1
In diesem Fall wird vom erkannten #a eine Bindung sowohl mit der Katalogsortierung ohne Berücksichtigung der Groß- und Kleinschreibung als auch mit der Instanzsortierung mit Berücksichtigung der Groß- und Kleinschreibung hergestellt, und der Code wird fehlerfrei ausgeführt.
Beispiel 2
Im folgenden Beispiel wird der Fall veranschaulicht, in dem durch den Verweis keine Übereinstimmung in der aktuellen Sortierung gefunden wird, wo zuvor eine Übereinstimmung vorhanden war.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #A VALUES(1);
GO
Hier wird eine Bindung von #A
an #a
in der Standardsortierung ohne Berücksichtigung der Groß- und Kleinschreibung hergestellt, und die Einfügung funktioniert.
Hier sehen Sie das Ergebnis.
(1 row(s) affected)
Wenn jedoch das Skript fortgesetzt wird...
USE master;
GO
SELECT * FROM #A;
GO
Beim Versuch, eine Bindung an #A
in der Instanzsortierung mit Berücksichtigung der Groß- und Kleinschreibung herzustellen, wird ein Fehler ausgegeben;
Hier sehen Sie das Ergebnis.
Meldung 208, Ebene 16, Status 0, Zeile 2
Ungültiger Objektname '#A'.
Beispiel 3
Im folgenden Beispiel wird der Fall veranschaulicht, wo durch den Verweis mehrere Übereinstimmungen gefunden werden, die sich ursprünglich voneinander unterschieden haben. Zunächst wird in tempdb
begonnen (die dieselbe Sortierung mit Berücksichtigung von Groß-/Kleinschreibung aufweist wie die gegebene Instanz), und folgende Anweisungen werden ausgeführt.
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
Diese Ausführung ist erfolgreich, da die Tabellen in dieser Sortierung eindeutig sind:
Hier sehen Sie das Ergebnis.
(1 row(s) affected)
(1 row(s) affected)
Beim Wechseln in die enthaltene Datenbank wird jedoch festgestellt, dass keine Bindungen an diese Tabellen hergestellt werden können.
USE MyCDB;
GO
SELECT * FROM #a;
GO
Hier sehen Sie das Ergebnis.
Msg 12800, Level 16, State 1, Line 2
The reference to temp table name #a is ambiguous and cannot be resolved. Possible candidates are #a and #A.