Ci sono alcune cose da notare qui:
-
Se vuoi vedere esattamente quale carattere è presente, puoi convertire il valore in
VARBINARY
che ti darà il valore esadecimale/binario di tutti i caratteri nella stringa e non esiste il concetto di caratteri "nascosti" in esadecimale: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];
Resi:
NVarCharValue VarCharValue RTrimmedVarCharValue VarBinaryValue 053000 053000? 053000? 0x3000350033003000300030000820
NVARCHAR
i dati vengono archiviati come UTF-16 che funziona in set da 2 byte. Osservando le ultime 4 cifre esadecimali per vedere qual è il set di 2 byte nascosto, vediamo "0820". Poiché Windows e SQL Server sono UTF-16 Little Endian (ovvero UTF-16LE), i byte sono in ordine inverso. Capovolgere gli ultimi 2 byte --08
e20
-- otteniamo "2008", che è lo "spazio di punteggiatura" che abbiamo aggiunto tramiteNCHAR(0x2008)
.Inoltre, tieni presente che
RTRIM
non ha aiutato affatto qui. -
Semplificando, puoi semplicemente sostituire i punti interrogativi con niente:
SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
-
Ancora più importante, dovresti convertire il
[PostalCode]
campo aVARCHAR
in modo che non memorizzi questi caratteri. Nessun paese utilizza lettere che non sono rappresentate nel set di caratteri ASCII e che non sono valide per il tipo di dati VARCHAR, almeno per quanto ho letto (vedere la sezione in basso per i riferimenti). In effetti, ciò che è consentito è un sottoinsieme piuttosto piccolo di ASCII, il che significa che puoi facilmente filtrare durante il percorso (o semplicemente fare lo stessoREPLACE
come mostrato sopra durante l'inserimento o l'aggiornamento):ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
Assicurati di controllare l'attuale
NULL
/NOT NULL
impostazione per la colonna e rendila uguale nell'istruzione ALTER sopra, altrimenti potrebbe essere modificata poiché l'impostazione predefinita èNULL
se non specificato. -
Se non puoi modificare lo schema della tabella e devi eseguire una "pulizia" periodica dei dati non validi, puoi eseguire quanto segue:
;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]), '?', '');
Tieni presente che la query precedente non è pensata per funzionare in modo efficiente se la tabella ha milioni di righe. A quel punto dovrebbe essere gestito in set più piccoli tramite un ciclo.
Per riferimento, ecco l'articolo di Wikipedia per Codice postale , che attualmente afferma che gli unici caratteri mai utilizzati sono:
E per quanto riguarda la dimensione massima del campo, ecco l'Elenco dei codici postali di Wikipedia