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
VARBINARY
co 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? 0x3000350033003000300030000820
NVARCHAR
dane 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 --08
i20
-- otrzymujemy "2008", czyli "spację interpunkcyjną" dodaną przezNCHAR(0x2008)
.Pamiętaj też, że
RTRIM
tu 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 doVARCHAR
aby 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 samoREPLACE
jak pokazano powyżej podczas wstawiania lub aktualizacji):ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
Pamiętaj, aby sprawdzić aktualny
NULL
/NOT NULL
ustawienie dla kolumny i zrób to samo w powyższej instrukcji ALTER, w przeciwnym razie może zostać zmienione, ponieważ wartość domyślna toNULL
jeś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