2014-10-01 19 views
6

Alter fascicolazioneCambiare le regole di confronto di un database di SQL Server 2012

ho bisogno di cambiare le regole di confronto di una delle nostre banche dati su un particolare server da Latin1_General_CI_AS a SQL_Latin1_General_CP1_CI_AI in modo che corrisponda il resto delle nostre banche dati.

Alter Collation Dialog - SQL Server 2012 R2

Il problema

Tuttavia, quando tento di fare questo, ottengo il seguente errore:

ALTER DATABASE failed. The default collation of database 'XxxxxXxxxxx' cannot be set to SQL_Latin1_General_CP1_CI_AI. (Microsoft SQL Server, Error: 5075)

La mia ricerca

mio googling su l'argomento ha rivelato un numero di articoli wh ich indicare che ho bisogno di esportare tutti i dati, rilasciare il database, ricrearlo con le regole di confronto corrette, quindi reimportare i dati.

Ad esempio: Problem with database collation change (SQL Server 2008)

Ovviamente questo è un compito significativo, soprattutto perché le relazioni di chiave primaria-straniera devono essere conservati, e la nostra base di dati è abbastanza grande (oltre dieci milioni di righe di dati).

La mia domanda

C'è un modo per cambiare le regole di confronto di un database esistente di SQL Server 2012 che non richiede l'esportazione e re-importazione di tutti i dati?

In alternativa, c'è qualche strumento o script che può automatizzare questo processo in modo affidabile?

risposta

3

le seguenti opere per me su SQL Server 2012:

ALTER DATABASE CURRENT COLLATE SQL_Latin1_General_CP1_CI_AI; 

La risposta accettata nella questione collegata non è del tutto corretto, almeno non per SQL Server 2012. Si dice:

Ahh, this is one of the worst problems in SQL Server: you cannot change the collation once an object is created (this is true both for tables and databases...).

Ma sono stato in grado di modificare le regole di confronto predefinite e di avere tabelle popolate. La pagina di MSDN per ALTER DATABASE stati nella sezione "Osservazioni", sotto "Modifica le regole di confronto del database":

Before you apply a different collation to a database, make sure that the following conditions are in place:

  1. You are the only one currently using the database.

  2. No schema-bound object depends on the collation of the database.

    If the following objects, which depend on the database collation, exist in the database, the ALTER DATABASE database_name COLLATE statement will fail. SQL Server will return an error message for each object blocking the ALTER action:

    • User-defined functions and views created with SCHEMABINDING.

    • Computed columns.

    • CHECK constraints.

    • Table-valued functions that return tables with character columns with collations inherited from the default database collation.

Quindi, vorrei suggerire facendo in modo che il database è in modalità utente singolo, e che se si dispone di uno di questi quattro elementi, che si:

  • farli cadere
  • cambiamento delle regole di confronto
  • e poi ri-aggiungerli

MA, a questo punto tutto ciò che è stato modificato è il confronto predefinito del database. Le regole di confronto di qualsiasi colonna esistente nelle tabelle utente (ad esempio tabelle non di sistema) avranno ancora le regole di confronto originali.Se si desidera colonne di stringhe esistenti - CHAR, VARCHAR, NCHAR, NVARCHAR e il deprecato TEXT e NTEXT - per assumere le nuove regole di confronto, è necessario modificare ciascuna di tali colonne singolarmente. E, se ci sono degli indici definiti su quelle colonne, allora quegli indici dovranno prima essere eliminati (disabilitazione non è sufficiente) e creati nuovamente dopo lo ALTER COLUMN (altre dipendenze che impedirebbero che lo ALTER COLUMN sia già stato rilasciato per ottenere il ALTER DATABASE per funzionare). L'esempio che segue illustra questo comportamento:

Impostazione test

USE [tempdb]; 
SET NOCOUNT ON; 

CREATE TABLE dbo.ChangeCollationParent 
(
    [ChangeCollationParentID] INT NOT NULL IDENTITY(1, 1) 
        CONSTRAINT [PK_ChangeCollationParent] PRIMARY KEY, 
    ExtendedASCIIString VARCHAR(50) COLLATE Latin1_General_CI_AS NULL, 
    UnicodeString NVARCHAR(50) COLLATE Latin1_General_CI_AS NULL 
); 

CREATE TABLE dbo.ChangeCollationChild 
(
    [ChangeCollationChildID] INT NOT NULL IDENTITY(1, 1) 
        CONSTRAINT [PK_ChangeCollationChild] PRIMARY KEY, 
    [ChangeCollationParentID] INT NULL 
        CONSTRAINT [FK_ChangeCollationChild_ChangeCollationParent] FOREIGN KEY 
         REFERENCES dbo.ChangeCollationParent([ChangeCollationParentID]), 
    ExtendedASCIIString VARCHAR(50) COLLATE Latin1_General_CI_AS NULL, 
    UnicodeString NVARCHAR(50) COLLATE Latin1_General_CI_AS NULL 
); 

INSERT INTO dbo.ChangeCollationParent ([ExtendedASCIIString], [UnicodeString]) 
VALUES ('test1' + CHAR(200), N'test1' + NCHAR(200)); 
INSERT INTO dbo.ChangeCollationParent ([ExtendedASCIIString], [UnicodeString]) 
VALUES ('test2' + CHAR(170), N'test2' + NCHAR(170)); 


INSERT INTO dbo.ChangeCollationChild 
     ([ChangeCollationParentID], [ExtendedASCIIString], [UnicodeString]) 
VALUES (1, 'testA ' + CHAR(200), N'testA ' + NCHAR(200)); 
INSERT INTO dbo.ChangeCollationChild 
     ([ChangeCollationParentID], [ExtendedASCIIString], [UnicodeString]) 
VALUES (1, 'testB ' + CHAR(170), N'testB ' + NCHAR(170)); 

SELECT * FROM dbo.ChangeCollationParent; 
SELECT * FROM dbo.ChangeCollationChild; 

Test 1: Cambiare colonna di fascicolazione senza dipendenze

ALTER TABLE dbo.ChangeCollationParent 
    ALTER COLUMN [ExtendedASCIIString] VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL; 
ALTER TABLE dbo.ChangeCollationParent 
    ALTER COLUMN [UnicodeString] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL; 

ALTER TABLE dbo.ChangeCollationChild 
    ALTER COLUMN [ExtendedASCIIString] VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL; 
ALTER TABLE dbo.ChangeCollationChild 
    ALTER COLUMN [UnicodeString] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL; 

SELECT * FROM dbo.ChangeCollationParent; 
SELECT * FROM dbo.ChangeCollationChild; 

I ALTER COLUMN dichiarazioni di cui sopra completano con successo.

Test 2: Cambiare colonna di fascicolazione con dipendenze

-- First, create an index: 
CREATE NONCLUSTERED INDEX [IX_ChangeCollationParent_ExtendedASCIIString] 
    ON dbo.ChangeCollationParent ([ExtendedASCIIString] ASC); 

-- Next, change the Collation back to the original setting: 
ALTER TABLE dbo.ChangeCollationParent 
    ALTER COLUMN [ExtendedASCIIString] VARCHAR(50) COLLATE Latin1_General_CI_AS NULL; 

Questa volta, la dichiarazione ALTER COLUMN ricevuto il seguente errore:

Msg 5074, Level 16, State 1, Line 60
The index 'IX_ChangeCollationParent_ExtendedASCIIString' is dependent on column 'ExtendedASCIIString'.
Msg 4922, Level 16, State 9, Line 60
ALTER TABLE ALTER COLUMN ExtendedASCIIString failed because one or more objects access this column.

INOLTRE, si prega di essere consapevole del fatto che le regole di confronto alcune colonne di stringhe nelle viste del catalogo di sistema con ambito database (ad esempio sys.objects, sys.columns, sys.indexes, ecc.) Cambierà nella nuova fascicolazione. Se il tuo codice ha JOINs a una qualsiasi di queste colonne di stringhe (ad esempio name), potresti iniziare a ricevere errori di disaccoppiamento di Collation finché non modifichi le regole di confronto sulle colonne di join nelle tabelle utente.

+0

Grazie mille per la risposta ricercata srutzky. Farò un tentativo. –

+0

Questo metodo non funziona se nel database si utilizza una delle colonne in questione. Ad esempio, se si dispone di un SP con qualcosa come "WHERE x = y" e xey sono varchars, non è possibile modificare le regole di confronto a causa del problema (2). Quindi, fondamentalmente, funziona per database a cui in realtà non interessa e non riesce per niente al mondo reale. –

+0

@MauryMarkowitz riguardo "_se tu hai un SP che ha qualcosa del tipo" WHERE x = y "e xey sono varchars, non puoi cambiare le regole di confronto a causa del problema (2) _": hai provato questo e hai scoperto che lo ha fatto non funziona, o stai andando in base a ciò che dice la documentazione che ho citato? Perché l'ho provato e funziona davvero. Stai leggendo erroneamente il punto 2. Non ha nulla a che fare con i proc memorizzati e le colonne (N) VARCHAR hanno una Collation definita. Si tratta di stringhe letterali, parametri e alcune colonne nelle tabelle del catalogo di sistema che sono interessate dal momento che sono controllate dalle regole di confronto predefinite di db. –

Problemi correlati