Unicode dans SQL Server : caractères, octets et pertes
Choisissez le stockage Unicode, comprenez les limites nvarchar et UTF-8 et testez le parcours complet entre application et base.
Passer une colonne en nvarchar ne répare pas un texte déjà remplacé par des points d'interrogation avant insertion. La correction Unicode concerne tout le trajet : décodage, application, paramètres du pilote, expressions SQL, stockage et export doivent préserver les mêmes caractères.
Distinguer caractères et stockage
Dans nvarchar(n), n désigne des paires d'octets UTF-16, pas nécessairement n caractères visibles. Un caractère supplémentaire peut nécessiter deux unités. Un caractère affiché peut aussi réunir plusieurs points de code, comme une lettre et un accent combinant. Les limites visuelles de l'application et celles du stockage peuvent donc diverger.
DECLARE @text nvarchar(20)=N'café ';
SELECT LEN(@text) AS LengthWithoutTrailingSpaces,
DATALENGTH(@text) AS StorageBytes;
DECLARE @emoji nvarchar(2)=N'😀';
SELECT LEN(@emoji COLLATE Latin1_General_100_CI_AS_SC) AS Characters,
DATALENGTH(@emoji) AS StorageBytes;
La première mesure montre que LEN ignore les espaces finaux, tandis que DATALENGTH mesure les octets stockés. LEN seul ne prouve pas la conservation exacte. La deuxième mesure utilise une collation adaptée aux caractères supplémentaires : l'emoji compte pour un caractère tout en occupant quatre octets en nvarchar.
Le préfixe N crée une constante Unicode. Sans lui, un passage par une page de codes non Unicode peut perdre des caractères avant l'affectation. Les paramètres applicatifs doivent eux aussi utiliser le type Unicode prévu. Testez de vrais textes non latins, pas seulement des noms ASCII.
Comparer les encodages avec les données réelles
SQL Server 2019 prend en charge UTF-8 pour varchar avec les collations correspondantes. Cela ne transforme pas automatiquement les anciennes colonnes varchar en Unicode. Collation et expressions intermédiaires comptent. Pour varchar(n), n limite les octets : des caractères multioctets réduisent le nombre de caractères stockables.
UTF-8 peut économiser de l'espace sur du texte majoritairement ASCII ; d'autres écritures demandent davantage d'octets par caractère. Comparez valeurs représentatives et tailles d'index, sans supposer une économie systématique de moitié. Version, limites des colonnes et compatibilité des clients font partie du choix.
Un changement de collation peut également modifier l'unicité. Une comparaison insensible à la casse ou aux accents peut considérer des entrées différentes égales. Des textes visuellement identiques peuvent inversement avoir des séquences de points de code distinctes. Définissez normalisation et identité explicitement.
Vérifier le parcours complet
Préparez accents latins, cyrillique, CJK, emoji, marques combinantes, guillemets et espaces finaux significatifs. Faites-les passer par la véritable API, l'insertion paramétrée, la lecture, la sérialisation et l'export. Comparez la séquence reçue à l'original, et les octets lorsque nécessaire. Une insertion réussie ne teste qu'une étape.
Avant migration, mesurez longueurs maximales en octets et valeurs proches des limites. Vérifiez index, contraintes, colonnes calculées et intégrations utilisant encore des paramètres varchar. Une copie de test avec comparaison aller-retour détecte des pertes invisibles dans un simple comptage de lignes.
Si les données anciennes contiennent déjà des caractères de remplacement, recherchez la source originale. Une conversion de type ne peut deviner le texte perdu. Récupérez-le depuis une source ou sauvegarde vérifiée et identifiez les lignes impossibles à restaurer fidèlement.
L'objectif est de rendre la même séquence que celle saisie, sauf normalisation explicitement convenue. Testez aussi le téléchargement puis la réimportation de fichiers. Les paramètres du pilote et les transformations comptent autant que le type de colonne.
Références techniques: Microsoft Learn: nvarchar · Microsoft Learn: Unicode and UTF-8 · Microsoft Learn: DATALENGTH.