我在名为PostalCode的NVarchar字段中有一些unicode字符。当我将它们转换为Varchar时,结果中有?
。
我的代码是:
select PostalCode, cast((PostalCode) as varchar)) as val from table
结果是:
PostalCode | val
053000 | 053000?
我在这里得到一个'?'在结果中。有没有办法删除这些特殊字符?
答案 0 :(得分:4)
这里有几点需要注意:
如果你想确切地看到那个字符,你可以将值转换为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]), '?', '');
请注意,如果表包含数百万行,则上述查询无效。此时,需要通过循环在较小的集合中处理。
供参考,以下是Postal code的维基百科文章,该文章目前声明所使用的唯一字符是:
- 阿拉伯数字“0”至“9”
- ISO基本拉丁字母的字母
- 空格,连字符
关于字段的最大大小,这里是维基百科List of postal codes
答案 1 :(得分:0)
不,Unicode是Unicode。该标准允许ASCII之外的无数“特殊”字符。您可以做的最好的事情是在转换之前搜索所需的字符子集,并将它们转换为您喜欢的ASCII替身。
答案 2 :(得分:0)
只要“?”在实际的PostalCode值中不允许,您可以先进行强制转换,然后使用REPLACE
删除这些字符,将其替换为空字符串:
replace(cast((PostalCode) as varchar))), '?', '')
这些'?'
个字符表示原始nvarchar
值中未转换为等效ASCII varchar
字符的Unicode字符。这意味着此方法将以静默方式删除任何此类字符。你说你想删除这些字符,但你可能想重新考虑一下。
举个例子,如果邮政编码可以包含字母,并且有人不小心输入了带重音的字母:
1234-ABCD
最终结果将是:
1234-BCD
答案 3 :(得分:0)