Il y a quelques points à noter ici :
-
Si vous voulez voir exactement quel caractère s'y trouve, vous pouvez convertir la valeur en
VARBINARY
qui vous donnera la valeur hexadécimale / binaire de tous les caractères de la chaîne et il n'y a pas de concept de caractères "cachés" en hexadécimal :DECLARE @PostalCode NVARCHAR(20); SET @PostalCode = N'053000'+ NCHAR(0x2008); -- 0x2008 = "Punctuation Space" SELECT @PostalCode AS [NVarCharValue], CONVERT(VARCHAR(20), @PostalCode) AS [VarCharValue], CONVERT(VARCHAR(20), RTRIM(@PostalCode)) AS [RTrimmedVarCharValue], CONVERT(VARBINARY(20), @PostalCode) AS [VarBinaryValue];
Renvoie :
NVarCharValue VarCharValue RTrimmedVarCharValue VarBinaryValue 053000 053000? 053000? 0x3000350033003000300030000820
NVARCHAR
les données sont stockées au format UTF-16 qui fonctionne dans des ensembles de 2 octets. En regardant les 4 derniers chiffres hexadécimaux pour voir quel est l'ensemble caché de 2 octets, nous voyons "0820". Étant donné que Windows et SQL Server sont UTF-16 Little Endian (c'est-à-dire UTF-16LE), les octets sont dans l'ordre inverse. Inverser les 2 derniers octets --08
et20
-- nous obtenons "2008", qui est "l'espace de ponctuation" que nous avons ajouté viaNCHAR(0x2008)
.Veuillez également noter que
RTRIM
n'a pas aidé du tout ici. -
De manière simpliste, vous pouvez simplement remplacer les points d'interrogation par rien :
SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
-
Plus important encore, vous devez convertir le
[PostalCode]
champ àVARCHAR
afin qu'il ne stocke pas ces caractères. Aucun pays n'utilise des lettres qui ne sont pas représentées dans le jeu de caractères ASCII et qui ne sont pas valides pour le type de données VARCHAR, du moins pour autant que j'en ai jamais lu (voir la section inférieure pour les références). En fait, ce qui est autorisé est un sous-ensemble plutôt petit d'ASCII, ce qui signifie que vous pouvez facilement filtrer en entrant (ou simplement faire le mêmeREPLACE
comme indiqué ci-dessus lors de l'insertion ou de la mise à jour) :ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
Assurez-vous de vérifier le
NULL
actuel /NOT NULL
paramètre pour la colonne et rendez-le identique dans l'instruction ALTER ci-dessus, sinon il pourrait être modifié car la valeur par défaut estNULL
si non spécifié. -
Si vous ne pouvez pas modifier le schéma de la table et devez effectuer un "nettoyage" périodique des mauvaises données, vous pouvez exécuter ce qui suit :
;WITH cte AS ( SELECT * FROM TableName WHERE [PostalCode] <> CONVERT(NVARCHAR(50), CONVERT(VARCHAR(50), [PostalCode])) ) UPDATE cte SET cte.[PostalCode] = REPLACE(CONVERT(VARCHAR(50), [PostalCode]), '?', '');
Veuillez garder à l'esprit que la requête ci-dessus n'est pas censée fonctionner efficacement si la table contient des millions de lignes. À ce stade, il devrait être géré dans des ensembles plus petits via une boucle.
Pour référence, voici l'article wikipedia pour Code postal , qui indique actuellement que les seuls caractères jamais utilisés sont :
Et concernant la taille max du champ, voici la Wikipedia Liste des codes postaux