Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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ührlichere Erläuterung der Sortierungen selbst finden Sie unter Sortierungs- 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, trägt jedoch dazu bei, instanzunabhängig und einheitlich zu sein. Dies kann jedoch auch zu Verwirrung führen und Probleme für Sitzungen verursachen, die sowohl auf enthaltene als auch nicht enthaltene Datenbanken zugreifen.
Das Sortierungsverhalten der enthaltenen Datenbanken unterscheidet sich subtil vom Verhalten in nicht enthaltenen Datenbanken. Dieses Verhalten ist im Allgemeinen vorteilhaft und trägt zu Unabhängigkeit von Instanzen sowie Einfachheit bei. Einige Benutzer können Probleme haben, insbesondere wenn eine Sitzung auf enthaltene und nicht enthaltene Datenbanken zugreift.
In diesem Artikel wird der Inhalt der Änderung erläutert, und es werden Bereiche untersucht, in denen die Änderung Probleme verursachen kann.
Hinweis
Für Azure SQL-Datenbank unterscheiden sich Sortierungen für eigenständige Datenbanken. Die Datenbanksortierung und Katalogsortierung können beim Erstellen der Datenbank festgelegt werden und können 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 verfügen über eine Standardsortierung (die beim Erstellen oder Ändern einer Datenbank festgelegt werden kann). Diese Sortierung wird für alle Metadaten in der Datenbank verwendet und ist die Standardeinstellung für alle Zeichenfolgenspalten innerhalb der Datenbank. 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 wir nun eine Spalte erstellen, ist die standardsortierung diese chinesische Sortierung, aber wir können bei Bedarf eine andere auswählen:
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 spezifischen Datenbank abhängt, in der die Tabelle erstellt wird, treten Probleme mit der Verwendung temporärer Tabellen auf, die in tempdb
gespeichert werden. Die Sortierung der tempdb
entspricht in der Regel der Sortierung der Instanz, die nicht mit der Datenbanksortierung übereinstimmen muss.
Beispiel 2
Betrachten Sie beispielsweise die zuvor gezeigte (chinesische) Datenbank, wenn sie für eine Instanz mit einer Latin1_General
Sortierung verwendet wird:
CREATE TABLE T1 (T1_txt NVARCHAR (MAX));
GO
CREATE TABLE #T2 (T2_txt NVARCHAR (MAX));
GO
Auf den ersten Blick sehen diese beiden Tabellen wie dasselbe Schema aus, da sich die Sortierungen der Datenbanken jedoch unterscheiden, sind die Werte inkompatibel:
SELECT T1_txt, T2_txt
FROM T1
INNER JOIN #T2
ON T1.T1_txt = #T2.T2_txt;
Hier sehen Sie das Ergebnis.
Meldung 468, Ebene 16, Status 9, Zeile 2
Der Sortierungskonflikt zwischen "Latin1_General_100_CI_AS_KS_WS_SC" und "Chinese_Simplified_Pinyin_100_CI_AS" kann bei der Gleichheitsoperation nicht behoben werden.
Dies kann durch das explizite Sortieren der temporären Tabelle korrigiert werden. SQL Server erleichtert dies, 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
INNER JOIN #T2
ON T1.T1_txt = #T2.T2_txt;
Diese Abfrage wird jetzt ohne Fehler ausgeführt.
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 AS INT = 1;
DECLARE @İ AS INT = 2;
RETURN @x * @i;
END
Dies ist eine relativ spezielle Funktion. Bei einer groß- und kleinschreibungssensitiven Kollation kann die Rückgabeklausel @i
weder an @I
noch an @İ
gebunden 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.
Enthaltene 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. Details werden wie folgt angegeben.
In einer enthaltenen Datenbank ist die Katalog-Zeichensatz Latin1_General_100_CI_AS_WS_KS_SC
. Diese Sortierung ist für alle enthaltenen 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 CATALOG_DEFAULT
gibt die aktuelle Datenbanksortierung zurück, da Metadaten in der Datenbanksortierung sortiert werden. In einer enthaltenen Datenbank können diese beiden Werte unterschiedlich sein, da der Benutzer die Datenbanksortierung ändern kann, sodass sie nicht mit der Katalogsortierung übereinstimmt.
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 |
Temporäre Daten (Standard) |
tempdb Vergleichung |
DATABASE_DEFAULT |
Metadaten | DATABASE_DEFAULT / CATALOG_DEFAULT |
CATALOG_DEFAULT |
Temporäre Metadaten |
tempdb Vergleichung |
CATALOG_DEFAULT |
Variablen | Instanzsortierung | CATALOG_DEFAULT |
Goto-Labels | 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
INNER JOIN #T2
ON T1.T1_txt = #T2.T2_txt;
Diese Abfrage funktioniert, da sowohl T1_txt
als auch T2_txt
in der Datenbankkollation der enthaltenen Datenbank sortiert sind.
Überschneidung zwischen enthaltenen und nicht enthaltenen 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 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 geschehen, da ein Benutzer möglicherweise USE
zu einer anderen Datenbank wechseln 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.
Diese Entscheidung wird getroffen, bevor irgendein Befehl ausgegeben wird, einschließlich eines anfänglichen USE
. Das heißt, wenn ein Batch in einer enthaltenen Datenbank beginnt, aber der erste Befehl USE
an eine nicht-enthaltene Datenbank geht, wird das enthaltene Sortierungsverhalten weiterhin für den Batch verwendet. In diesem Szenario kann ein Verweis auf eine Variable beispielsweise mehrere mögliche Ergebnisse haben:
Der Verweis findet möglicherweise genau eine Übereinstimmung. In diesem Fall funktioniert der Verweis ohne Fehler.
Der Verweis findet möglicherweise keine Übereinstimmung in der aktuellen Sortierung, obwohl vorher eine vorhanden war. Dadurch wird ein Fehler ausgelöst, der angibt, dass die Variable nicht vorhanden ist, obwohl sie scheinbar erstellt wurde.
Der Verweis kann mehrere Übereinstimmungen finden, die ursprünglich unterschiedlich waren. Dies löst auch einen Fehler aus.
Wir veranschaulichen dies mit einigen Beispielen. Es wird angenommen, dass eine teilweise enthaltene Datenbank mit dem Namen MyCDB
standardmäßig auf die Datenbanksortierung Latin1_General_100_CI_AS_WS_KS_SC
festgelegt ist. Es wird davon ausgegangen, dass die Instanzsortierung lautet Latin1_General_100_CS_AS_WS_KS_SC
. 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 der Verweis keine Übereinstimmung in der aktuellen Sortierung findet, in der 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.
Msg 208, Level 16, State 0, Line 2
Invalid object name '#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 Abfrage ist erfolgreich, da sich die Tabellen in dieser Sortierung unterscheiden:
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.