2013-08-08 21 views
32

Ho importato un database con alcuni dati da confrontare con un altro database.Modificare le regole di confronto di tutte le colonne di tutte le tabelle in SQL Server

Il database di destinazione ha fascicolazione Latin1_General_CI_AS e il database di origine ha SQL_Latin1_General_CP1_CI_AS.

Ho modificato le regole di confronto del database di origine in generale su Latin1_General_CI_AS utilizzando SQL Server Management Studio. Ma i tavoli e le colonne all'interno rimangono con le vecchie regole di confronto.

So che posso cambiare una colonna utilizzando:

ALTER TABLE [table] 
ALTER COLUMN [column] VARCHAR(100) COLLATE Latin1_General_CI_AS 

ma devo fare questo per tutte le tabelle e tutte le colonne all'interno.

Prima So iniziare a scrivere una stored procedure che legge tutti i tavoli e all'interno di tutti colonna di tipo varchar e li cambia in una tabella e la colonna del ciclo cursore ...

Qualcuno sa un modo più semplice o è la l'unico modo per farlo con uno script che attraversa tutte le tabelle in una procedura?

+4

possibile duplicato di [come modificare il fascicolato in tutte le colonne del database?] (Http://stackoverflow.com/questions/16730114/how-to-change-the-collate-to-all-the- colonne-del-database) –

+0

Grazie per il collegamento. Sembra che la risposta sia simile all'idea che ho avuto con la sceneggiatura che ho fatto. – YvesR

+0

http://www.codeproject.com/Articles/302405/The-Easy-way-of-changing-Collation-of-all-Database – NullUserException

risposta

38

Come non ho trovato un modo corretto ho scritto una sceneggiatura per farlo e lo sto condividendo qui per chi ne ha bisogno. Lo script esegue tutte le tabelle utente e raccoglie le colonne. Se il tipo di colonna è un qualsiasi tipo di carattere, tenta di convertirlo nelle regole di confronto specificate.

Le colonne devono essere indicizzate e senza vincoli perché funzioni.

Se qualcuno ha ancora una soluzione migliore per questo post, per favore!

DECLARE @collate nvarchar(100); 
DECLARE @table nvarchar(255); 
DECLARE @column_name nvarchar(255); 
DECLARE @column_id int; 
DECLARE @data_type nvarchar(255); 
DECLARE @max_length int; 
DECLARE @row_id int; 
DECLARE @sql nvarchar(max); 
DECLARE @sql_column nvarchar(max); 

SET @collate = 'Latin1_General_CI_AS'; 

DECLARE local_table_cursor CURSOR FOR 

SELECT [name] 
FROM sysobjects 
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1 

OPEN local_table_cursor 
FETCH NEXT FROM local_table_cursor 
INTO @table 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    DECLARE local_change_cursor CURSOR FOR 

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id 
     , c.name column_name 
     , t.Name data_type 
     , c.max_length 
     , c.column_id 
    FROM sys.columns c 
    JOIN sys.types t ON c.system_type_id = t.system_type_id 
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id 
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id 
    WHERE c.object_id = OBJECT_ID(@table) 
    ORDER BY c.column_id 

    OPEN local_change_cursor 
    FETCH NEXT FROM local_change_cursor 
    INTO @row_id, @column_name, @data_type, @max_length, @column_id 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 

     IF (@max_length = -1) OR (@max_length > 4000) SET @max_length = 4000; 

     IF (@data_type LIKE '%char%') 
     BEGIN TRY 
      SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN ' + @column_name + ' ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate 
      PRINT @sql 
      EXEC sp_executesql @sql 
     END TRY 
     BEGIN CATCH 
      PRINT 'ERROR: Some index or constraint rely on the column' + @column_name + '. No conversion possible.' 
      PRINT @sql 
     END CATCH 

     FETCH NEXT FROM local_change_cursor 
     INTO @row_id, @column_name, @data_type, @max_length, @column_id 

    END 

    CLOSE local_change_cursor 
    DEALLOCATE local_change_cursor 

    FETCH NEXT FROM local_table_cursor 
    INTO @table 

END 

CLOSE local_table_cursor 
DEALLOCATE local_table_cursor 

GO 
+0

Grazie, potrebbe aiutare –

+1

Se si utilizzano schemi, è necessario modificare il nome Select [nome ] da sysobjects a: SELECT sys.schemas.name + '.' + Sys.objects.name AS Nome DA sys.objects INNER JOIN sys.schemas SU sys.objects.schema_id = sys.schemas.schema_id WHERE type_desc = 'user_table' – Tod

15

lunghezza fissa problema nvarchar e ha aggiunto NULL/NOT NULL

DECLARE @collate nvarchar(100); 
DECLARE @table nvarchar(255); 
DECLARE @column_name nvarchar(255); 
DECLARE @column_id int; 
DECLARE @data_type nvarchar(255); 
DECLARE @max_length int; 
DECLARE @row_id int; 
DECLARE @sql nvarchar(max); 
DECLARE @sql_column nvarchar(max); 
DECLARE @is_Nullable bit; 
DECLARE @null nvarchar(25); 

SET @collate = 'Latin1_General_CI_AS'; 

DECLARE local_table_cursor CURSOR FOR 

SELECT [name] 
FROM sysobjects 
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1 

OPEN local_table_cursor 
FETCH NEXT FROM local_table_cursor 
INTO @table 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    DECLARE local_change_cursor CURSOR FOR 

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id 
     , c.name column_name 
     , t.Name data_type 
     , c.max_length 
     , c.column_id 
     , c.is_nullable 
    FROM sys.columns c 
    JOIN sys.types t ON c.system_type_id = t.system_type_id 
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id 
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id 
    WHERE c.object_id = OBJECT_ID(@table) 
    ORDER BY c.column_id 

    OPEN local_change_cursor 
    FETCH NEXT FROM local_change_cursor 
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 

     IF (@max_length = -1) SET @max_length = 4000; 
     set @null=' NOT NULL' 
     if (@is_nullable = 1) Set @null=' NULL' 
     if (@Data_type='nvarchar') set @max_length=cast(@max_length/2 as bigint) 
     IF (@data_type LIKE '%char%') 
     BEGIN TRY 
      SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + rtrim(@column_name) + '] ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate + @null 
      PRINT @sql 
      EXEC sp_executesql @sql 
     END TRY 
     BEGIN CATCH 
      PRINT 'ERROR: Some index or contraint rely on the column ' + @column_name + '. No conversion possible.' 
      PRINT @sql 
     END CATCH 

     FETCH NEXT FROM local_change_cursor 
     INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_Nullable 

    END 

    CLOSE local_change_cursor 
    DEALLOCATE local_change_cursor 

    FETCH NEXT FROM local_table_cursor 
    INTO @table 

END 

CLOSE local_table_cursor 
DEALLOCATE local_table_cursor 

GO 
+0

uniscono con index_columns e gli indici non vengono utilizzati e in realtà la causa duplicazione di colonne; si può anche usare un filtro per trovare solo le colonne necessarie per convertire (c.collation_name <> @collate) – Kodak

4

Per fare questo ho avuto una soluzione facile che funziona per me.

  1. Creare un nuovo database con le nuove regole di confronto.
  2. Esportare i dati del database originale in modalità script.
  3. Importare il contenuto nel nuovo database utilizzando lo script (rinominare la frase USE nel nuovo database).

Tuttavia, è necessario per ottenere cautela se si banca dati ha trigger, procedure o stoffe simili più di dati e tabelle.

27

Quindi eccomi, ancora una volta, non soddisfatto della risposta. Mi è stato chiesto di aggiornare JIRA 6.4.x a JIRA Software 7.x e sono andato a quel particolare problema con il database e le regole di confronto delle colonne.

In SQL Server, se non si rilasciano vincoli come chiave primaria o chiave esterna o addirittura indici, lo script fornito sopra come risposta non funziona affatto. Cambierà comunque quelli senza quelle proprietà. Questo è davvero problematico, perché non voglio abbandonare manualmente tutti i vincoli e crearli di nuovo. Tale operazione potrebbe probabilmente finire con errori. D'altro canto, la creazione di uno script che automatizza il cambiamento potrebbe richiedere anni.

Quindi ho trovato un modo per rendere la migrazione semplicemente utilizzando SQL Management Studio. Ecco la procedura:

  • Rinominare il database con qualcos'altro. Per esempio, il mio era "Jira", così l'ho ribattezzato "JiraTemp".
  • Creare un nuovo database denominato "Jira" e assicurarsi di impostare le giuste regole di confronto. Basta selezionare la pagina "Opzioni" e modificare le regole di confronto.
  • Una volta creato, tornare a "JiraTemp", fare clic con il pulsante destro del mouse, "Attività -> Genera script ...".
    • Selezionare "Script intero database e tutti gli oggetti del database".
    • Selezionare "Salva nuova finestra di query", quindi selezionare "Avanzate"
    • Modificare il valore di "Script per la versione Server" per il valore desiderato
    • Enable "Script oggetto le autorizzazioni a livello", "Script Owner" e "Script di indici full-text"
    • Lascia tutto il resto così com'è o personalizzalo se lo desideri.
  • Una volta generato, eliminare la sezione "CREATE DATABASE". Sostituisci "JiraTemp" di "Jira".
  • Eseguire lo script. L'intera struttura del database e le autorizzazioni del database sono ora replicate su "Jira".
  • Prima di copiare i dati, è necessario disabilitare tutti i vincoli. Esegui il seguente comando per farlo nel database "Jira": EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
  • Ora i dati devono essere trasferiti. Per fare ciò, fare semplicemente clic con il tasto destro su "JiraTemp", quindi selezionare "Attività -> Esporta dati ..."
    • Selezionare come origine dati e destinazione il provider OLE DB per SQL Server.
    • del database sorgente è "JiraTemp"
    • database di destinazione è "Jira"
    • Il nome del server è tecnicamente la stessa per origine e destinazione (a meno che non hai creato il database su un altro server).
    • Selezionare "Copia dati da una o più tabelle o viste"
    • Selezionare tutte le tabelle tranne le viste. Quindi, quando ancora evidenziato, fare clic su "Modifica mappature". Controllo "Enable identity insert"
    • Fare clic su OK, Avanti, quindi Fine
  • Il trasferimento dei dati può richiedere parecchio tempo. Una volta terminato, eseguire il seguente comando per riattivare tutti i vincoli: exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

Una volta completato, ho riavviato JIRA e il mio database di confronto era in ordine. Spero che aiuti molte persone!

+0

Seguita questa procedura alla lettera, ha ottenuto errori sul passo dei dati di copia: "La colonna XXXX non può essere elaborata perché più di un codice la pagina (X e Y) sono specificate per questo, fortunatamente era solo su un tavolo, quindi ho escluso quella tabella dal passaggio di copia e successivamente l'ho copiato manualmente, quindi non è una soluzione infallibile – pkExec

+0

Dato che non sono a conoscenza di alcun dettaglio riguardo a quale ambiente è stato fatto, né quale versione di SQL Server è stata utilizzata, non posso davvero dire qual è la causa esatta. Una ricerca rapida su Google sembra dire che è effettivamente correlata al trasferimento dei dati. Ecco cosa ho trovato per gli altri avendo il problema: http://dba.stackexchange.com/questions/22010/import-export-wizard-code-page-error o https://social.msdn.microsoft.com/Forums/sqlserver/en-US/ d2aa7365-3dfc-4eb4-8ec3-b2de3556e662/code-page? forum = sqlintegrationservices – DaveWut

+1

Specifico per quelli qui per gli aggiornamenti JIRA alla serie 7.x, ho scoperto che era più semplice eseguire un backup XML, rilasciare il database, ricreare con le regole di confronto corrette e quindi importare da XML. Vedere https://confluence.atlassian.com/adminjiraserver072/switching-databases-828787577.html – trebor

1

Problema di lunghezza fissa nvarchar (include max), testo incluso e aggiunto NULL/NOT NULL.

USE [put your database name here]; 

begin tran 

DECLARE @collate nvarchar(100); 
DECLARE @table nvarchar(255); 
DECLARE @column_name nvarchar(255); 
DECLARE @column_id int; 
DECLARE @data_type nvarchar(255); 
DECLARE @max_length int; 
DECLARE @max_length_str nvarchar(100); 
DECLARE @is_nullable bit; 
DECLARE @row_id int; 
DECLARE @sql nvarchar(max); 
DECLARE @sql_column nvarchar(max); 

SET @collate = 'Latin1_General_CI_AS'; 

DECLARE local_table_cursor CURSOR FOR 

SELECT [name] 
FROM sysobjects 
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1 
ORDER BY [name] 

OPEN local_table_cursor 
FETCH NEXT FROM local_table_cursor 
INTO @table 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    DECLARE local_change_cursor CURSOR FOR 

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id 
     , c.name column_name 
     , t.Name data_type 
     , col.CHARACTER_MAXIMUM_LENGTH 
     , c.column_id 
     , c.is_nullable 
    FROM sys.columns c 
    JOIN sys.types t ON c.system_type_id = t.system_type_id 
    JOIN INFORMATION_SCHEMA.COLUMNS col on col.COLUMN_NAME = c.name and c.object_id = OBJECT_ID(col.TABLE_NAME) 
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id 
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id 
    WHERE c.object_id = OBJECT_ID(@table) AND (t.Name LIKE '%char%' OR t.Name LIKE '%text%') 
    AND c.collation_name <> @collate 
    ORDER BY c.column_id 

    OPEN local_change_cursor 
    FETCH NEXT FROM local_change_cursor 
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 

     set @max_length_str = @max_length 
     IF (@max_length = -1) SET @max_length_str = 'max' 
     IF (@max_length > 4000) SET @max_length_str = '4000' 

     BEGIN TRY 
      SET @sql = 
      CASE 
       WHEN @data_type like '%text%' 
       THEN 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + @column_name + '] ' + @data_type + ' COLLATE ' + @collate + ' ' + CASE WHEN @is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END 
       ELSE 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + @column_name + '] ' + @data_type + '(' + @max_length_str + ') COLLATE ' + @collate + ' ' + CASE WHEN @is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END 
      END 
      --PRINT @sql 
      EXEC sp_executesql @sql 
     END TRY 
     BEGIN CATCH 
      PRINT 'ERROR (' + @table + '): Some index or constraint rely on the column ' + @column_name + '. No conversion possible.' 
      --PRINT @sql 
     END CATCH 

     FETCH NEXT FROM local_change_cursor 
     INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable 

    END 

    CLOSE local_change_cursor 
    DEALLOCATE local_change_cursor 

    FETCH NEXT FROM local_table_cursor 
    INTO @table 

END 

CLOSE local_table_cursor 
DEALLOCATE local_table_cursor 

commit tran 

GO 

Avviso: nel caso in cui hai solo bisogno di cambiare alcune specifiche condizioni di utilizzo di confronto come questo:

WHERE c.object_id = OBJECT_ID(@table) AND (t.Name LIKE '%char%' OR t.Name LIKE '%text%') 
    AND c.collation_name = 'collation to change' 

esempio NON il: AND c.collation_name <> @collate

Nel mio caso, ho avuto corretta raccolta/specificato di alcune colonne e non volevo cambiare loro.

Problemi correlati