2009-12-10 4 views
31

Wir haben kürzlich unsere Datenbank von unserem SQL Server 2005-Server auf unseren SQL Server 2008-Server verschoben. Alles lief gut, aber jetzt stellen wir fest, dass wir Kollationskonflikte bekommen. Der alte Server hatte eine andere Sortierung als der neue Server.Aktualisierung Sortierung aller Felder in der Datenbank im laufenden Betrieb

Nun sind unsere Tabellen, die vor dem Verschieben erstellt wurden, eine Kollatierung, und die danach erstellten Tabellen sind eine weitere Kollatierung.

Gibt es eine Möglichkeit, die Tabellen/Spalten mit der alten Kollatierung auf die neue Kollatierung zu aktualisieren?

Ich verstehe, die Einstellung der Standard-Datenbank/Server-Sortierung ändert keine vorhandenen Tabellen (link). Ich möchte wirklich nicht die Datenbank neu erstellen, wenn ich nicht muss.

Jede Hilfe wirklich geschätzt.

UPDATE

Vielen Dank für Ihre Hilfe Jungs, bekam es schließlich arbeiten.

Für die Zukunft, hier ist meine letzte Skript:

SELECT 'ALTER TABLE [' + SYSOBJECTS.Name + '] ALTER COLUMN [' + SYSCOLUMNS.Name + '] ' + 
SYSTYPES.name + 
    CASE systypes.NAME 
    WHEN 'text' THEN ' ' 
    ELSE 
    '(' + RTRIM(CASE SYSCOLUMNS.length 
    WHEN -1 THEN 'MAX' 
    ELSE CONVERT(CHAR,SYSCOLUMNS.length) 
    END) + ') ' 
    END 

    + ' ' + ' COLLATE Latin1_General_CI_AS ' + CASE ISNULLABLE WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END 
    FROM SYSCOLUMNS , SYSOBJECTS , SYSTYPES 
    WHERE SYSCOLUMNS.ID = SYSOBJECTS.ID 
    AND SYSOBJECTS.TYPE = 'U' 
    AND SYSTYPES.Xtype = SYSCOLUMNS.xtype 
    AND SYSCOLUMNS.COLLATION IS NOT NULL 
    AND NOT (sysobjects.NAME LIKE 'sys%') 
    AND NOT (SYSTYPES.name LIKE 'sys%') 
    GO 

Hier ist die site, die das Skript enthalten ich es basiert auf. Ich musste zwicken, damit es richtig funktioniert.

+1

Russell, Sie sollten Ihre Lösung eine Antwort geben! –

+0

Danke Philipp, es steht sowieso oben auf der Frage, und OMG Ponies haben mir geholfen, dorthin zu kommen. :) – Russell

Antwort

6

Sie können die Sortierung aller neuen Objekte ändern, die in einer Benutzerdatenbank mithilfe der COLLATE-Klausel der ALTER DATABASE-Anweisung erstellt werden. Diese Anweisung ändert nicht die Sortierung der Spalten in beliebigen vorhandenen benutzerdefinierten Tabellen. Diese können mithilfe der COLLATE-Klausel ALTER TABLE geändert werden.

Referenz: Setting and Changing the Database Collation

Wenn es zu viele Spalten sind, können Sie eine Schleife durch sys.columns die ALTE TABLE-Anweisung anzuwenden.

+1

Ja, das ist nicht mein Problem, mein Problem ist mit bestehenden Spalten. – Russell

+0

Aus diesem Grund sagt die letzte Zeile, ALTER TABLE' zu verwenden. –

+0

Das ist keine Option, da es zu viele Felder dafür gibt. – Russell

2

Eine Option ist ein Programm wie Red Gate SQL Compare zu verwenden (ich bin mir sicher, dass es auch andere gibt). Damit können Sie Skriptdateien für Ihr Schema mit Kollationierung erstellen (stellen Sie sicher, dass dies in den Optionen aktiviert ist), dann suchen/ersetzen Sie die Dateien, aktualisieren Sie sie auf die neue Kollatierung und vergleichen Sie sie dann wieder mit Ihrer tatsächlichen Datenbank.

An dieser Stelle kann SQL Compare diese Änderungen übernehmen (oder die Änderungen in einer Skriptdatei speichern, wenn Sie dies bevorzugen), und Ihre vorhandenen Spalten sind alle behoben.

Theoretisch könnten Sie dies alles noch während der Testphase tun, obwohl ich vorschlagen würde, dass es ein gutes Werkzeug ist, um es zu behalten, da es viele SQL-Aufgaben einfacher macht!

+0

Redgate Compare ist auch ein großartiges Werkzeug. : D – Russell

10

Nur falls jemand bei dieser Suche wird mithilfe von SQL Server 2008, musste ich ein paar Änderungen vornehmen:

SELECT 'ALTER TABLE [' + sys.objects.name + '] ALTER COLUMN [' 
+ sys.columns.name + '] ' + sys.types.name + 
    CASE sys.types.name 
    WHEN 'text' THEN ' ' 
    ELSE 
    '(' + RTRIM(CASE sys.columns.max_length 
    WHEN -1 THEN 'MAX' 
    ELSE CONVERT(CHAR,sys.columns.max_length) 
    END) + ') ' 
    END 

    + ' ' + ' COLLATE Latin1_General_BIN ' + CASE sys.columns.is_nullable WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END 
    FROM sys.columns , sys.objects , sys.types 
    WHERE sys.columns.object_id = sys.objects.object_id 
    AND sys.objects.TYPE = 'U' 
    AND sys.types.system_type_id = sys.columns.system_type_id 
    AND sys.columns.collation_name IS NOT NULL 
    AND NOT (sys.objects.NAME LIKE 'sys%') 
    AND NOT (sys.types.name LIKE 'sys%') 
+0

Danke für den Tipp. Was wurde geändert? Ich habe das obige Skript auf SQL Server 2008 verwendet.: D – Russell

+1

Dies verwendet sys.columns anstatt SYSCOLUMNS – edosoft

+0

dann wie würden Sie dies durchlaufen und die Anweisungen ausführen? – Chagbert

4

Wie wäre:

DECLARE @collation NVARCHAR(64) 
SET @collation = 'Latin1_General_CI_AS' 

SELECT 
    'ALTER TABLE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] ' 
    + 'ALTER COLUMN [' + COLUMN_NAME + '] ' 
    + DATA_TYPE + '(' + CASE CHARACTER_MAXIMUM_LENGTH 
     WHEN -1 THEN 'MAX' 
     ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) END + ') ' 
    + 'COLLATE ' + @collation + ' ' 
    + CASE WHEN IS_NULLABLE = 'NO' THEN 'NOT NULL' ELSE 'NULL' END 
FROM INFORMATION_SCHEMA.columns 
WHERE COLLATION_NAME IS NOT NULL 
AND COLLATION_NAME <> @collation 
+1

'UND TABLE_NAME IN (SELECT TABLE_NAME aus information_schema.tables WHERE table_type = 'BASE TABLE')' – danihp

3

um dieses Problem zu beheben, müssen Sie viel mehr Feuerkraft bietet dieses Skript dann.Ich habe das Skript ausprobiert und stieß auf Probleme mit abhängigen Objekten, die nicht aktualisiert werden konnten: Indizes, Schlüssel und Prozeduren. Die endgültige Lösung dauerte nur 5 Minuten mit dieser Code-Projekt-App. Die App heißt es für SQL Server 2000 ist, aber ich habe es erfolgreich mit 2008.

http://www.codeproject.com/Articles/12753/SQL-Server-2000-Collation-Changer

ich nicht genug betonen kann. Sichern Sie Ihre Datenbank. Ich musste mein Backup dreimal benutzen, um diese Aufgabe zu erledigen.

-3

Der Code kann NText-, NChar- und NVarchar-Doppelbytes nicht berücksichtigen. Wenn Sie NText haben, wird es fehlschlagen, wenn Ntext (16) die Größe auf NText nicht festlegen kann.

Für NChar und NVarChar es verdoppelt sich die Länge, weil sie Größe aufzuteilen nicht durch 2.

Another Quirky kleine Detail, das ist für Nvarchar zumindest, -1 ist nicht MAX, aber 0 ist.

Dies ist ein sehr, sehr hässliche Hack auf dem Code, nur um die Probleme zu veranschaulichen:

ALTER TABLE [BlanketBruger] ALTER COLUMN [BrugerNavn] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BlanketBruger] ALTER COLUMN [BrugerFuldNavn] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [blanketgruppe] ALTER COLUMN [GruppeNavn] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [blanketSerie] ALTER COLUMN [SerieTitel] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [blanketSerie] ALTER COLUMN [SerieAlias] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [FormUse] ALTER COLUMN [HostName] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [value1] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [value2] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [ip] varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [username] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [gruppenavn] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [scriptname] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [querystring] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [useragent] nvarchar(400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [sessionid] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [htmlcontent] nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [value1] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [value2] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [ip] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [querystring] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [useragent] nvarchar(400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [sessionid] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [log4net] ALTER COLUMN [Thread] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Level] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Logger] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Message] text COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Exception] varchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [log4net] ALTER COLUMN [Server] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Server] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Thread] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Level] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Message] varchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileContentIdentifier] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileContent] ntext COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileName] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
+0

der tatsächliche Abfragecode wäre hilfreicher als Beispielausgabe; wir können nicht sagen, dass irgendeine dieser nvarchar Spalten doppelte Größe hat. –

0

Okay, ich den Code von edosoft neu geschrieben haben und es in einer Schleife setzen die tatsächlichen T-SQL-Anweisungen ausführen .

-- **************** BEGIN INPUT ********************** 
USE [YourDBName] 

DECLARE @collation NVARCHAR(128) 
-- enter you collation name below 
SET @collation = N'Latin1_General_CI_AS' 
-- **************** END INPUT ************************ 

-- **************** BEGIN LOGIC ********************** 
DECLARE @sqlCode VARCHAR(2048) 

DECLARE myCursor CURSOR LOCAL FOR 
    SELECT 'ALTER TABLE [' + sys.objects.name + '] 
     ALTER COLUMN ['+ sys.columns.name + '] ' + sys.types.name + 
     CASE sys.types.name 
      WHEN 'text' THEN ' ' 
      WHEN 'ntext' THEN ' ' 
      ELSE '(' + RTRIM(
       CASE 
        WHEN sys.columns.max_length = -1 THEN 'MAX' 
        WHEN sys.columns.max_length > 4000 THEN 'MAX' 
        ELSE CONVERT(CHAR,sys.columns.max_length) 
       END) + ')' 
     END 
     + ' COLLATE ' + @collation + CASE sys.columns.is_nullable WHEN 0 THEN ' NOT NULL' ELSE ' NULL' END 
     FROM sys.columns , sys.objects , sys.types 
     WHERE sys.columns.object_id = sys.objects.object_id 
      AND sys.objects.TYPE = 'U' 
      AND sys.types.system_type_id = sys.columns.system_type_id 
      AND sys.columns.collation_name IS NOT NULL 
      AND sys.columns.collation_name <> @collation 
      AND NOT (sys.objects.NAME LIKE 'sys%') 
      AND NOT (sys.types.name LIKE 'sys%') 

OPEN myCursor 
FETCH NEXT FROM myCursor INTO @sqlCode 

WHILE @@FETCH_STATUS = 0 BEGIN 
    PRINT 'Executing: ' + @sqlCode 
    BEGIN TRY 
     EXEC(@sqlCode); 
     PRINT 'Done!' + CHAR(10) 
    END TRY 
    BEGIN CATCH 
     PRINT 'Error: ' + ERROR_MESSAGE() + CHAR(10) 
    END CATCH 
    FETCH NEXT FROM myCursor INTO @sqlCode 
END 

PRINT 'Finished!' 
-- **************** END LOGIC ********************** 

Wenn Sie die Fehler etwas ähnliches zu bekommen „Kann nicht eine Reihe von Größe 8075, die von 8060 größer als die zulässigen maximalen Zeilengröße ist schaffen“. Erstellen Sie die Tabelle neu, für die Sie den Fehler erhalten, und führen Sie das obige Skript erneut aus.

ALTER TABLE [dbo].[YourTableName] REBUILD 
Verwandte Themen