Det finns några saker att notera här:
-
Om du vill se exakt vilket tecken som finns där kan du konvertera värdet till
VARBINARY
som ger dig det hexadecimala/binära värdet för alla tecken i strängen och det finns inget koncept med "dolda" tecken i hex: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];
Returnerar:
NVarCharValue VarCharValue RTrimmedVarCharValue VarBinaryValue 053000 053000? 053000? 0x3000350033003000300030000820
NVARCHAR
data lagras som UTF-16 som fungerar i 2-byte set. När vi tittar på de sista 4 hexadecimala siffrorna för att se vad den dolda 2-byte uppsättningen är, ser vi "0820". Eftersom Windows och SQL Server är UTF-16 Little Endian (dvs UTF-16LE), är byten i omvänd ordning. Vänd de sista 2 byten --08
och20
-- vi får "2008", vilket är "Punctuation Space" som vi lade till viaNCHAR(0x2008)
.Observera också att
RTRIM
hjälpte inte alls här. -
Förenklat kan du bara ersätta frågetecknen med ingenting:
SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
-
Ännu viktigare är att du bör konvertera
[PostalCode]
tillVARCHAR
så att den inte lagrar dessa tecken. Inget land använder bokstäver som inte är representerade i ASCII-teckenuppsättningen och som inte är giltiga för VARCHAR-datatypen, åtminstone så långt jag någonsin har läst om (se det nedersta avsnittet för referenser). Det som är tillåtet är faktiskt en ganska liten delmängd av ASCII, vilket innebär att du enkelt kan filtrera på vägen in (eller bara göra sammaREPLACE
som visas ovan när du infogar eller uppdaterar):ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
Var noga med att kontrollera den aktuella
NULL
/NOT NULL
inställningen för kolumnen och gör den till samma i ALTER-satsen ovan, annars kan den ändras eftersom standardinställningen ärNULL
om inte specificerat. -
Om du inte kan ändra tabellens schema och behöver göra en periodisk "rensning" av dålig data, kan du köra följande:
;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]), '?', '');
Tänk på att frågan ovan inte är avsedd att fungera effektivt om tabellen har miljontals rader. Då skulle det behöva hanteras i mindre uppsättningar via en loop.
För referens, här är wikipedia-artikeln för Postnummer , som för närvarande anger att de enda tecken som någonsin använts är:
Och angående den maximala storleken på fältet, här är Wikipedias listan över postnummer