Avant de faire quoi que ce soit, veuillez considérer les questions posées par @RDFozz dans un commentaire sur la question, à savoir:
Y a-t-il d' autres sources en plus de [Q].[G]
remplir ce tableau?
Si la réponse est autre que "Je suis sûr à 100% qu'il s'agit de la seule source de données pour cette table de destination", n'apportez aucune modification, que les données actuellement dans la table puissent ou non être converties sans perte de données.
Y a-t-il des plans / discussions concernant l'ajout de sources supplémentaires pour alimenter ces données dans un avenir proche?
Et je voudrais ajouter une question connexe: Y at - il eu des discussions autour de plusieurs langues dans le soutien de la table source de courant (ie [Q].[G]
) en convertissant ce à NVARCHAR
?
Vous devrez demander autour de vous pour avoir une idée de ces possibilités. Je suppose qu'on ne vous a actuellement rien dit qui pourrait aller dans cette direction, sinon vous ne poseriez pas cette question, mais si ces questions ont été supposées être "non", alors elles doivent être posées et un public suffisamment large pour obtenir la réponse la plus précise / complète.
Le problème principal ici n'est pas tant d'avoir des points de code Unicode qui ne peuvent pas convertir (jamais), mais plus encore d'avoir des points de code qui ne tiennent pas tous sur une seule page de code. C'est la bonne chose à propos d'Unicode: il peut contenir des caractères de TOUTES les pages de codes. Si vous effectuez une conversion de NVARCHAR
- où vous n'avez pas à vous soucier des pages de codes - vers VARCHAR
, vous devrez vous assurer que le classement de la colonne de destination utilise la même page de codes que la colonne source. Cela suppose d'avoir une ou plusieurs sources utilisant la même page de codes (pas nécessairement le même classement, cependant). Mais s'il existe plusieurs sources avec plusieurs pages de codes, vous pouvez potentiellement rencontrer le problème suivant:
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;
Renvoie (2e jeu de résultats):
ID SourceSlovak SourceHebrew Destination DestinationS DestinationH
1 Ţ ú NULL Ţ ú Ţ ú ? ?
2 NULL ט ת ? ? ט ת ט ת
Comme vous pouvez le voir, tous ces caractères peuvent être convertis en VARCHAR
, mais pas dans la même VARCHAR
colonne.
Utilisez la requête suivante pour déterminer la page de codes pour chaque colonne de votre table source:
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';
CELA ÉTANT DIT....
Vous avez mentionné être sur SQL Server 2008 R2, MAIS, vous n'avez pas dit quelle édition. SI vous êtes sur Enterprise Edition, alors oubliez tout ce truc de conversion (puisque vous le faites probablement juste pour économiser de l'espace), et activez la compression des données:
Implémentation de la compression Unicode
Si vous utilisez Standard Edition (et il semble maintenant que vous l'êtes), il existe une autre possibilité à très long terme: la mise à niveau vers SQL Server 2016 puisque SP1 inclut la possibilité pour toutes les éditions d'utiliser la compression de données (rappelez-vous, j'ai dit "à long terme" "😉).
Bien sûr, maintenant qu'il vient d'être clarifié qu'il n'y a qu'une seule source pour les données, alors vous n'avez rien à craindre car la source ne peut pas contenir de caractères Unicode uniquement, ou des caractères en dehors de son code spécifique page. Dans ce cas, la seule chose à laquelle vous devez faire attention est d'utiliser le même classement que la colonne source, ou au moins un qui utilise la même page de codes. Cela signifie que si la colonne source utilise SQL_Latin1_General_CP1_CI_AS
, vous pouvez utiliser Latin1_General_100_CI_AS
à la destination.
Une fois que vous savez quel classement utiliser, vous pouvez soit:
ALTER TABLE ... ALTER COLUMN ...
être VARCHAR
(assurez-vous de spécifier le paramètre NULL
/ actuel NOT NULL
), ce qui nécessite un peu de temps et beaucoup d'espace de journal des transactions pour 87 millions de lignes, OU
Créez de nouvelles colonnes "ColumnName_tmp" pour chacune et remplissez lentement via UPDATE
do TOP (1000) ... WHERE new_column IS NULL
. Une fois que toutes les lignes sont remplies (et validées qu'elles ont toutes été copiées correctement! Vous pourriez avoir besoin d'un déclencheur pour gérer les MISES À JOUR, s'il y en a), dans une transaction explicite, utilisez sp_rename
pour permuter les noms des colonnes des colonnes "actuelles" à " _Old "puis les nouvelles colonnes" _tmp "pour supprimer simplement" _tmp "des noms. Appelez ensuite sp_reconfigure
la table pour invalider tous les plans mis en cache référençant la table, et s'il existe des vues référençant la table, vous devrez appeler sp_refreshview
(ou quelque chose comme ça). Une fois que vous avez validé l'application et qu'ETL fonctionne correctement, vous pouvez supprimer les colonnes.
[G]
sont ETLed sur[P]
. Si[G]
c'est le casvarchar
, et que le processus ETL est le seul moyen par lequel les données entrent[P]
, alors à moins que le processus ajoute de vrais caractères Unicode, il ne devrait pas y en avoir. Si d'autres processus ajoutent ou modifient des données[P]
, vous devez être plus prudent - ce n'est pas parce que toutes les données actuelles peuvent l'êtrevarchar
que lesnvarchar
données ne pourront pas être ajoutées demain. De même, il est possible que tout ce qui consomme les données en ait[P]
besoinnvarchar
.