Тук трябва да отбележите няколко неща:
-
Ако искате да видите точно кой знак има, можете да конвертирате стойността в
VARBINARY
което ще ви даде шестнадесетичната / двоичната стойност на всички знаци в низа и няма концепция за "скрити" знаци в шестнадесетичен: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];
Връща:
NVarCharValue VarCharValue RTrimmedVarCharValue VarBinaryValue 053000 053000? 053000? 0x3000350033003000300030000820
NVARCHAR
данните се съхраняват като UTF-16, който работи в 2-байтови набори. Разглеждайки последните 4 шестнадесетични цифри, за да видим какъв е скрития 2-байтов набор, виждаме "0820". Тъй като Windows и SQL Server са UTF-16 Little Endian (т.е. UTF-16LE), байтовете са в обратен ред. Обръщане на последните 2 байта --08
и20
-- получаваме "2008", което е "Интервалът за препинателни знаци", който добавихме чрезNCHAR(0x2008)
.Също така имайте предвид, че
RTRIM
тук изобщо не помогна. -
Опростено, можете просто да замените въпросителните знаци с нищо:
SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
-
По-важното е, че трябва да конвертирате
[PostalCode]
поле къмVARCHAR
така че да не съхранява тези знаци. Нито една страна не използва букви, които не са представени в набора от символи ASCII и които не са валидни за типа данни VARCHAR, поне доколкото съм чел (вижте долния раздел за справки). Всъщност това, което е позволено, е доста малко подмножество от ASCII, което означава, че можете лесно да филтрирате по пътя (или просто да направите същотоREPLACE
както е показано по-горе при вмъкване или актуализиране):ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
Не забравяйте да проверите текущия
NULL
/NOT NULL
настройка за колоната и я направете същата в оператора ALTER по-горе, в противен случай тя може да бъде променена, тъй като по подразбиране еNULL
ако не е посочено. -
Ако не можете да промените схемата на таблицата и трябва да правите периодично "почистване" на лошите данни, можете да изпълните следното:
;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]), '?', '');
Моля, имайте предвид, че горната заявка не е предназначена да работи ефективно, ако таблицата има милиони редове. В този момент ще трябва да се обработва в по-малки комплекти чрез цикъл.
За справка, ето статията в wikipedia за Пощенски код , който в момента гласи, че единствените използвани някога знаци са:
А относно максималния размер на полето, ето Списък с пощенски кодове в Уикипедия