Why are you trying to convert Unicode? It's better to use Unicode throughout an application. Anyway ? means there are characters in the input string that can't be represented in the target codepage. Does your input contain invisible characters after the last number? I suspect LEN(PostalCode) will return 7 or higher.
– Panagiotis KanavosNov 21 '14 at 12:56

You can probably expect all postal codes to be expressible in [0-9][A-Z]. The one thing you might worry about is if the postal code can contain letters, and someone accidentally typed a letter with an accent. For example, if you process these by dropping non-ASCII characters, "1234-ÁBCD" would not indicate an error, and simply become "1234-BCD" instead of "1234-ABCD".
– Dan GetzNov 21 '14 at 14:19

4 Answers
4

If you want to see exactly which character is there, you can convert the value to VARBINARY which will give you the hex / binary value of all characters in the string and there is no concept of "hidden" characters in hex:

NVARCHAR data is stored as UTF-16 which works in 2-byte sets. Looking at the last 4 hex digits to see what the hidden 2-byte set is, we see "0820". Since Windows and SQL Server are UTF-16 Little Endian (i.e. UTF-16LE), the bytes are in reverse order. Flipping the final 2 bytes -- 08 and 20 -- we get "2008", which is the "Punctuation Space" that we added via NCHAR(0x2008).

Also, please note that RTRIM did not help at all here.

Simplistically, you can just replace the question marks with nothing:

SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');

More importantly, you should convert the [PostalCode] field to VARCHAR so that it doesn't store these characters. No country uses letters that are not represented in the ASCII character set and that are not valid for the VARCHAR datatype, at least as far as I have ever read about (see bottom section for references). In fact, what is allowed is a rather small subset of ASCII, which means you can easily filter on the way in (or just do the same REPLACE as shown above when inserting or updating):

This assumes that the OP has control over the DB schema.
– rory.apNov 21 '14 at 15:30

@roryap . Understood. However, it is just a recommendation. I did provide a way to accomplish the question, though I can make an update to account for having no control over the schema.
– Solomon RutzkyNov 21 '14 at 15:33

1

When you say "No country allows for Unicode characters in their postal codes", you are making a sweeping statement that isn't 100% accurate, since the Latin alphabet and Arabic digits are perfectly valid Unicode characters. You mean something more like "No country allows for Unicode characters outside the range U+0020 .. U+007E (equivalent to ASCII or the printing characters in the lower half of ISO 8859-1) in their postal codes". I'm not sure how to express that compactly; maybe "No country allows for Unicode characters that are not also ASCII printing characters in the postal codes".
– Jonathan LefflerNov 21 '14 at 16:23

@JonathanLeffler Thanks for commenting. That is why I copied the text of the Wikipedia article stating "ISO basic Latin alphabet". So maybe "no country uses letters that are not represented in the ASCII character set and that are not valid for the VARCHAR datatype"? Shouldn't need to mention printability as the only other characters are 0 - 9, space, and hyphen.
– Solomon RutzkyNov 21 '14 at 16:29

1

Yes, I know it's at the bottom, but maybe a '(see below)' or something similar. As it stands, your statement in item 2 is a contradiction; the postal code characters are Unicode characters; they are just particularly common/simple ones.
– Jonathan LefflerNov 21 '14 at 19:59

No, Unicode is Unicode. The standard allows for innumerable "special" characters beyond ASCII. The best you can do is search for your desired subset of characters before the conversion and convert them to your favorite ASCII stand-ins.

Except the original value doesn't appear to show anything that the conversion output doesn't include. It looks like the conversion is just adding a question mark (whatever that question mark might represent).
– a CVnNov 21 '14 at 12:52

The original value probably contains garbage non-visible characters after the last 0, otherwise it could be converted to any codepage. Numbers and the space character are available in all codepages
– Panagiotis KanavosNov 21 '14 at 12:54

1

@MichaelKjörling Maybe there's a unicode character in the table that wasn't carried over in the copy/paste to this post.
– rory.apNov 21 '14 at 12:57

@MichaelKjörling Unicode contain single characters like ... or , (yes, with the space). There are also at least 16 different spaces, joiners etc (U+2000 to U+200F)
– Panagiotis KanavosNov 21 '14 at 13:06

@roryap - there is a space after 0 in original unicode value.
– Rameshwar PawaleNov 21 '14 at 13:39

As long as "?" is not allowed in a real PostalCode value, you can cast first, and then remove these characters using REPLACE to replace them with the empty string:

replace(cast((PostalCode) as varchar))), '?', '')

Warning

These '?' characters represent Unicode characters in the original nvarchar value that were not converted to an equivalent ASCII varchar character. This means that this method will silently remove any such characters. You said you wanted to simply remove these characters, but you might want to rethink that.

To give an example, if the postal code can contain letters, and someone accidentally typed a letter with an accent:

What if it is multiple characters? And/or what if they are different Unicode characters?
– Solomon RutzkyNov 21 '14 at 17:13

Then my second method is not the right thing to do. (But it might still be worth trying RTRIM to see if it works.) This is an answer to one interpretation of the original question, "how do I get rid of only this particular character on the end".
– Dan GetzNov 21 '14 at 17:17