it-swarm.com.de

SQL Server: Ist das Ändern der Sortierung in vorhandenen Datenbanken sicher?

Ich bin neu in SQL Server und war mir der Möglichkeit nicht bewusst, dass bei T-SQL die Groß- und Kleinschreibung nicht berücksichtigt wird.

Ich habe Entitäten normalisiert, indem ich Tabellen und Einschränkungen aufgeteilt habe. Ich habe Angst, dass, wenn ich die Sortierung jetzt ändere, einige dieser Einschränkungen ungültig sein können, wenn beispielsweise ein Fremdschlüsselwert ohne Berücksichtigung der Groß- und Kleinschreibung auf einen PK-Wert mit einer anderen Groß- und Kleinschreibung verweist.

Wenn ich diese Abfrage in der Datenbank ausführen würde (getestet in einer Basisdatenbank):

ALTER DATABASE <db_name>
COLLATE SQL_Latin1_General_Cp1_CS_AS ;
GO

Was würde passieren, wenn einige Einschränkungen verletzt würden?

Gibt es einen anderen Grund, warum ich vorsichtig sein sollte, eine datenbankweite Änderung vorzunehmen, z. B. die Sortierung zu ändern?

7
Zach Smith

Das Ändern der Sortierung einer Datenbank wirkt sich nicht auf vorhandene Spalten aus. Dies betrifft neue Nicht-XML-Zeichenfolgenspalten, die nicht die Klausel COLLATE (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, da @JonathanFite so freundlich war, mich daran zu erinnern, hat das Ändern der DB-Sortierung may Auswirkungen auf Abfragen mit temporären Tabellen. Die Standardkollatierung für Zeichenfolgenspalten in temporären Tabellen (keine Tabellenvariablen) ist die Standardkollatierung für [tempdb] (Die mit [model] Entspricht, die die Standardinstanz sein sollte, sofern nicht jemand wiederhergestellt hat [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 explizit mit COLLATE DATABASE_DEFAULT In den Anweisungen CREATE TABLE 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, einen ALTER TABLE ... ALTER COLUMN Ausgeben 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 SQL_ Beginnen. Verwenden Sie stattdessen Latin1_General_100_CS_AS. Die Kollatierungen, die mit SQL_ Beginnen, sind seit der Veröffentlichung von SQL Server 2000 veraltet (auch wenn sie nicht offiziell veraltet sind). Ihre Behandlung von VARCHAR/8-Bit-Daten ist veraltet und entspricht nicht dem neueren Verhalten. Aus Gründen der Abwärtskompatibilität war die Standardkollatierung für US-Englisch-Installationen leider die SQL_Latin1 - Kollatierung, wie auf der Seite Verwenden von SQL Server-Kollatierungen MSDN angegeben:

Aus Gründen der Abwärtskompatibilität lautet die Standardkollatierung in englischer Sprache (US) SQL_Latin1_General *.

Dies wird auch im Standard-Sortierdiagramm auf der Seite Sortiereinstellungen im Setup MSDN vermerkt (drücken Sie Strg-F und fügen Sie sql_latin Ein). 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.
6
Solomon Rutzky

Zunächst wird nichts passieren. Die Sortierung der Datenbank ist nur eine Standardeinstellung, die beim Erstellen in neue Spalten kopiert wird. Einmal erstellt, behalten sie diese Sortierung bei. Siehe sys.columns.collation_name .

Wenn Sie die Datenbankkollatierung ändern und dann neue Spalten erstellen, haben diese Spalten die neue Kollatierung. Dies kann eine Kollatierung sein, die mit den bereits vorhandenen Spalten kompatibel ist.

Wenn Sie eine Sortierung mit Groß- und Kleinschreibung für die Datenbank übernehmen, wird bei SQL zwischen Groß- und Kleinschreibung unterschieden. Objektnamen müssen genau mit den deklarierten Zeichenfolgen übereinstimmen. Dies kann die Anwendung beschädigen.

Ich habe diesen Prozess vor vielen Jahren durchlaufen. Ich scheine mich zu erinnern, dass ich jede Zeichenspalte in der Datenbank explizit auf die neue Sortierung ändern und dann die Daten für die Kollatierungsänderung aktualisieren musste (Aktualisierungstabelle set charcol1 = charcol1, charcol2 = charcol2 ...; Nicht-Zeichenfolge) Spalten wurden nicht benötigt). Dies war vor vielen Versionen, so dass die Dinge jetzt einfacher sein können. Würde ich es je nach Größe und Komplexität erneut tun, wäre ich versucht, alle Objekte zu skripten, die Datei zu bearbeiten, um Kollatierungen zu entfernen, dann eine neue Datenbank von Grund auf neu zu erstellen und die Daten und Berechtigungen usw. zu übertragen.

Viel Glück.

2
Michael Green