Należy tutaj zwrócić uwagę na kilka rzeczy:
-
Jeśli chcesz zobaczyć dokładnie, który znak się tam znajduje, możesz przekonwertować wartość na
VARBINARYco da ci wartość szesnastkową / binarną wszystkich znaków w ciągu i nie ma pojęcia "ukrytych" znaków w szesnastkowym: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];Zwroty:
NVarCharValue VarCharValue RTrimmedVarCharValue VarBinaryValue 053000 053000? 053000? 0x3000350033003000300030000820NVARCHARdane są przechowywane jako UTF-16, który działa w zestawach 2-bajtowych. Patrząc na ostatnie 4 cyfry szesnastkowe, aby zobaczyć, jaki jest ukryty zestaw 2 bajtów, widzimy „0820”. Ponieważ Windows i SQL Server są UTF-16 Little Endian (tj. UTF-16LE), bajty są w odwrotnej kolejności. Odwracanie ostatnich 2 bajtów --08i20-- otrzymujemy "2008", czyli "spację interpunkcyjną" dodaną przezNCHAR(0x2008).Pamiętaj też, że
RTRIMtu w ogóle nie pomogło. -
Upraszczając, możesz po prostu zastąpić znaki zapytania niczym:
SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', ''); -
Co ważniejsze, powinieneś przekonwertować
[PostalCode]pole doVARCHARaby nie przechowywać tych znaków. Żaden kraj nie używa liter, które nie są reprezentowane w zestawie znaków ASCII i które nie są poprawne dla typu danych VARCHAR, przynajmniej o ile kiedykolwiek czytałem (patrz dolna sekcja dla odniesień). W rzeczywistości dozwolony jest raczej mały podzbiór ASCII, co oznacza, że możesz łatwo filtrować po drodze (lub po prostu zrobić to samoREPLACEjak pokazano powyżej podczas wstawiania lub aktualizacji):ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;Pamiętaj, aby sprawdzić aktualny
NULL/NOT NULLustawienie dla kolumny i zrób to samo w powyższej instrukcji ALTER, w przeciwnym razie może zostać zmienione, ponieważ wartość domyślna toNULLjeśli nie określono. -
Jeśli nie możesz zmienić schematu tabeli i musisz przeprowadzać okresowe „czyszczenie” złych danych, możesz uruchomić następujące polecenie:
;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]), '?', '');Należy pamiętać, że powyższe zapytanie nie działa wydajnie, jeśli tabela ma miliony wierszy. W tym momencie musiałaby być obsługiwana w mniejszych zestawach za pomocą pętli.
Dla porównania, oto artykuł w Wikipedii dotyczący Kod pocztowy , który obecnie stwierdza, że jedynymi używanymi znakami są:
A jeśli chodzi o maksymalny rozmiar pola, oto Wikipedia Lista kodów pocztowych