Prima di fare qualsiasi cosa, si prega di considerare le domande poste da @RDFozz in un commento sulla domanda, vale a dire:
Ci sono tutte le altre fonti oltre [Q].[G]
che popolano questo tavolo?
Se la risposta è diversa da "Sono sicuro al 100% che questa è l' unica fonte di dati per questa tabella di destinazione", non apportare alcuna modifica, indipendentemente dal fatto che i dati attualmente nella tabella possano essere convertiti o meno senza perdita di dati.
Ci sono eventuali piani / discussioni relative all'aggiunta di ulteriori fonti per compilare questi dati in un prossimo futuro?
E vorrei aggiungere una questione connessa: v'è stata alcuna discussione intorno supporto di più lingue nella tabella di origine corrente (cioè [Q].[G]
) convertendo è di NVARCHAR
?
Dovrai chiedere in giro per avere un'idea di queste possibilità. Suppongo che al momento non ti sia stato detto nulla che indichi in questa direzione altrimenti non porteresti questa domanda, ma se queste domande sono state ritenute "no", allora devono essere poste e poste pubblico sufficientemente ampio per ottenere la risposta più accurata / completa.
Il problema principale qui non è tanto avere punti di codice Unicode che non possono essere convertiti (mai), ma piuttosto avere punti di codice che non rientrano tutti in una singola pagina di codice. Questa è la cosa bella di Unicode: può contenere caratteri di TUTTE le pagine di codice. Se esegui la conversione da NVARCHAR
- dove non devi preoccuparti delle pagine di codice - in VARCHAR
, dovrai assicurarti che le regole di confronto della colonna di destinazione utilizzino la stessa pagina di codice della colonna di origine. Ciò presuppone di avere una sola fonte o più fonti che utilizzano la stessa tabella codici (non necessariamente la stessa fascicolazione). Ma se ci sono più origini con più pagine di codice, è possibile che si verifichi il seguente problema:
DECLARE @Reporting TABLE
(
ID INT IDENTITY(1, 1) PRIMARY KEY,
SourceSlovak VARCHAR(50) COLLATE Slovak_CI_AS,
SourceHebrew VARCHAR(50) COLLATE Hebrew_CI_AS,
Destination NVARCHAR(50) COLLATE Latin1_General_CI_AS,
DestinationS VARCHAR(50) COLLATE Slovak_CI_AS,
DestinationH VARCHAR(50) COLLATE Hebrew_CI_AS
);
INSERT INTO @Reporting ([SourceSlovak]) VALUES (0xDE20FA);
INSERT INTO @Reporting ([SourceHebrew]) VALUES (0xE820FA);
UPDATE @Reporting
SET [Destination] = [SourceSlovak]
WHERE [SourceSlovak] IS NOT NULL;
UPDATE @Reporting
SET [Destination] = [SourceHebrew]
WHERE [SourceHebrew] IS NOT NULL;
SELECT * FROM @Reporting;
UPDATE @Reporting
SET [DestinationS] = [Destination],
[DestinationH] = [Destination]
SELECT * FROM @Reporting;
Resi (2 ° set di risultati):
ID SourceSlovak SourceHebrew Destination DestinationS DestinationH
1 Ţ ú NULL Ţ ú Ţ ú ? ?
2 NULL ט ת ? ? ט ת ט ת
Come puoi vedere, tutti quei personaggi possono essere convertiti VARCHAR
, ma non nella stessa VARCHAR
colonna.
Utilizzare la seguente query per determinare qual è la tabella codici per ogni colonna della tabella di origine:
SELECT OBJECT_NAME(sc.[object_id]) AS [TableName],
COLLATIONPROPERTY(sc.[collation_name], 'CodePage') AS [CodePage],
sc.*
FROM sys.columns sc
WHERE OBJECT_NAME(sc.[object_id]) = N'source_table_name';
DETTO CIÒ....
Hai detto di essere su SQL Server 2008 R2, MA, non hai detto quale edizione. SE ti trovi in Enterprise Edition, quindi dimentica tutte queste cose di conversione (poiché probabilmente lo stai facendo solo per risparmiare spazio) e abilita la compressione dei dati:
Implementazione della compressione Unicode
Se si utilizza Standard Edition (e ora sembra che tu sia 😞) allora c'è un'altra possibilità di tiro a segno: l'aggiornamento a SQL Server 2016 poiché SP1 include la possibilità per tutte le versioni di utilizzare la compressione dei dati (ricorda, ho detto "long-shot "😉).
Naturalmente, ora che è stato appena chiarito che esiste solo una fonte per i dati, allora non hai nulla di cui preoccuparti poiché la fonte non può contenere caratteri solo Unicode o caratteri al di fuori del suo codice specifico pagina. In tal caso, l'unica cosa di cui dovresti essere consapevole è usare la stessa Fascicolazione della colonna di origine, o almeno una che sta usando la stessa pagina di codice. Significato, se si utilizza la colonna di origine SQL_Latin1_General_CP1_CI_AS
, è possibile utilizzare Latin1_General_100_CI_AS
a destinazione.
Una volta che sai quale Collation usare, puoi:
ALTER TABLE ... ALTER COLUMN ...
essere VARCHAR
(assicurarsi di specificare la corrente NULL
/ NOT NULL
impostazione), che richiede un po 'di tempo e molto spazio nel registro delle transazioni per 87 milioni di righe, OPPURE
Crea nuove colonne "ColumnName_tmp" per ognuna e popolare lentamente UPDATE
facendo TOP (1000) ... WHERE new_column IS NULL
. Una volta popolate tutte le righe (e convalidate che siano state copiate tutte correttamente! Potrebbe essere necessario un trigger per gestire gli AGGIORNAMENTI, se presenti), in una transazione esplicita, utilizzare sp_rename
per scambiare i nomi delle colonne delle "attuali" colonne da " _Vecchio "e quindi le nuove colonne" _tmp "per rimuovere semplicemente" _tmp "dai nomi. Quindi chiama sp_reconfigure
la tabella per invalidare tutti i piani memorizzati nella cache che fanno riferimento alla tabella e se ci sono viste che fanno riferimento alla tabella, dovrai chiamare sp_refreshview
(o qualcosa del genere). Dopo aver convalidato l'app e ETL funziona correttamente con essa, è possibile eliminare le colonne.
[G]
sono ETLed a[P]
. Se lo[G]
èvarchar
, e il processo ETL è l'unico modo in cui entrano i dati[P]
, a meno che il processo non aggiunga caratteri Unicode veri, non dovrebbe essercene alcuno. Se altri processi aggiungono o modificano dati[P]
, devi stare più attento - solo perché tutti i dati attuali possono esserevarchar
non significa che invarchar
dati non possano essere aggiunti domani. Allo stesso modo, è possibile che qualunque cosa stia consumando i dati nei dati[P]
necessarinvarchar
.