Das Ändern der Sortierung einer Datenbank wirkt sich nicht auf vorhandene Spalten aus. Dies betrifft neue Nicht-XML-Zeichenfolgenspalten, die keine COLLATE
Klausel (einschließlich Tabellenvariablen), Zeichenfolgenliterale und Variablenwerte angeben (keine Auflösung von Variablennamen, die durch die Sortierung auf Instanzebene bestimmt wird). Dies bedeutet, dass Folgendes betroffen ist:
IF (@Variable = 'string')
BEGIN
...
END;
Diese Änderung wirkt sich auch auf Metadaten auf Datenbankebene aus, z. B. Namen von Schemas, Objekten, Spalten, Indizes usw. Dies bedeutet, dass die folgenden zwei Szenarien betroffen sind:
SELECT ...
FROM sys.indexes si
WHERE si.[name] = N'somename'; -- real name = SomeName
und:
SELECT ...
FROM dbo.sometable st -- real name = SomeTable
In beiden Beispielen würden sie in einer Sortierung ohne Berücksichtigung der Groß- und Kleinschreibung arbeiten, in einer Sortierung ohne Berücksichtigung der Groß- und Kleinschreibung jedoch nichts oder Fehler zurückgeben.
Schließlich, wie @JonathanFite war so freundlich, mich daran zu erinnern, die Änderung der DB Sortierungs kann Abfragen auswirken temporäre Tabellen beteiligt sind . Die Standardkollatierung für Zeichenfolgenspalten in temporären Tabellen (keine Tabellenvariablen) ist die Standardkollatierung für [tempdb]
(die [model]
mit der Standardeinstellung der Instanz identisch sein sollte, es sei denn, jemand hat sie wiederhergestellt[model]
von einem Server mit einer anderen Standardkollatierung), nicht der Kollatierung der lokalen Datenbank. Das heißt, obwohl die temporären Tabellen jedes Mal erstellt werden und Sie daher erwarten können, dass sie sich mit der neuen Sortierung wie "neu erstellte Tabellen" verhalten, verhalten sie sich tatsächlich wie "vorhandene Tabellen" und verhalten sich weiterhin wie zuvor die Sortieränderung. Wenn Sie Zeichenfolgenspalten in temporären Tabellen benötigen, um die neue Kollatierung zu verwenden, müssen Sie deren Kollatierung COLLATE DATABASE_DEFAULT
in den CREATE TABLE
Anweisungen explizit festlegen .
Daher müssen Sie wirklich viele Tests durchführen!
Wenn Sie vorhandene Spalten ändern möchten, müssen Sie vorhandene Einschränkungen löschen, eine ausgeben ALTER TABLE ... ALTER COLUMN
und dann die Einschränkungen neu erstellen. Sie müssen auch Indizes neu erstellen, die eine Spalte verwenden, deren Sortierung geändert wurde, da die Sortierreihenfolge möglicherweise unterschiedlich ist.
Es ist auch am besten, keine Kollatierungen zu verwenden, die mit beginnen SQL_
. Verwenden Sie stattdessen Latin1_General_100_CS_AS
. Die Kollatierungen, die mit beginnen, SQL_
sind seit der Veröffentlichung von SQL Server 2000 veraltet (auch wenn sie nicht offiziell veraltet sind) . Ihr Umgang mit VARCHAR
/ 8-Bit-Daten ist veraltet und entspricht nicht dem neueren Verhalten. Aus Gründen der Abwärtskompatibilität war die Standardkollatierung für Installationen in US-Englisch leider die SQL_Latin1
Kollatierung, wie auf der Seite MSDN für SQL Server-Kollatierungen verwenden angegeben :
Aus Gründen der Abwärtskompatibilität lautet die Standardkollatierung in englischer Sprache (US) SQL_Latin1_General *.
Dies wird auch im Standardkollatierungsdiagramm auf der Seite Kollatierungseinstellungen im Setup- MSDN vermerkt ( drücken Sie Strg-F und fügen Sie es ein sql_latin
). Ich glaube, diese Standardeinstellung wurde ab SQL Server 2014 in eine Windows-Sortierung geändert, aber die Dokumentation verweist auch für das SQL Server 2016-Setup weiterhin auf die 2008 R2-Setup-Seite für Kollatierungen.
Unten finden Sie ein Skript, um einige der Verhaltensunterschiede beim Ändern der Sortierung einer Datenbank anzuzeigen:
USE [master];
GO
IF (DB_ID(N'ChangeDatabaseCollationTest') IS NULL)
BEGIN
CREATE DATABASE [ChangeDatabaseCollationTest] COLLATE Latin1_General_100_CI_AS;
END;
GO
USE [ChangeDatabaseCollationTest];
GO
-- Current DB Collation: Latin1_General_100_CI_AS
EXEC sp_help 'sys.objects';
-- Collation for [name] = Latin1_General_100_CI_AS
IF ('A' = 'a')
BEGIN
SELECT 'Case INsensitive comparison works.';
END;
ELSE
BEGIN
SELECT 'Case INsensitive comparison did NOT work.';
END;
-- Case INsensitive comparison works.
CREATE TABLE dbo.CaseTest_a (ID INT); -- success
SELECT * FROM dbo.CaseTest_A; -- success
CREATE TABLE dbo.CaseTest_A (ID INT); -- error:
-- Msg 2714, Level 16, State 6, Line 5
-- There is already an object named 'CaseTest_A' in the database.
ALTER DATABASE [ChangeCollationTest] COLLATE Latin1_General_100_CS_AS; -- success
IF ('A' = 'a')
BEGIN
SELECT 'Case INsensitive comparison works.';
END;
ELSE
BEGIN
SELECT 'Case INsensitive comparison did NOT work.';
END;
-- Case INsensitive comparison did NOT work.
SELECT * FROM dbo.CaseTest_A; -- error:
-- Msg 208, Level 16, State 1, Line 56
-- Invalid object name 'dbo.CaseTest_A'.
CREATE TABLE dbo.CaseTest_A (ID INT); -- success
EXEC sp_help 'sys.objects';
-- Collation for [name] = Latin1_General_100_CS_AS
ALTER DATABASE [ChangeCollationTest] COLLATE Latin1_General_100_CI_AS; -- error:
-- Msg 1505, Level 16, State 1, Line 23
-- The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for
-- the object name 'dbo.sysschobjs' and the index name 'nc1'. The duplicate key
-- value is (0, 1, CaseTest_A).
-- Msg 5072, Level 16, State 1, Line 23
-- ALTER DATABASE failed. The default collation of database 'ChangeCollationTest'
-- cannot be set to Latin1_General_100_CI_AS.