2017-10-17 68 views
1

有一个奇怪的空白字符,我似乎无法摆脱那偶尔会出现在我的数据从Excel导入时。显然,它会作为空白字符出现,但SQL Server将其视为问号(ASCII 63)。如何在SQL Server中删除奇怪的Excel字符?

declare @temp nvarchar(255); set @temp = '[email protected]?am.com' 
select @temp 

回报:

[email protected]?am.com 

我怎样才能摆脱空白的没有摆脱真正的问号?如果我查看每个“?”的ASCII码当我获得63个角色时,其中只有一个角色是真正的问题标记。

+0

如果您执行Ltrim(@temp)会怎么样? – Harry

+2

注意:如果出于某种原因想要保持字符串不变,您应该设置@temp = N'mystring'(显式声明该字符串是unicode,即使您的变量是NVARCHAR,也应该这样做')而不是你目前正在做的事情。 – ZLK

+0

看起来像一个字符集不匹配。 – Namphibian

回答

2

查看this answer有类似问题的人。对不起,如果这是一个长长的啰嗦:

SQL Server似乎通过映射不可代表的字符(没有合适的替代字符)到问号来将Unicode变为ASCII。要复制它,请尝试打开Character Map Windows程序(应该安装在大多数机器上),选择Arial作为字体并找到U + 034f“组合Grapheme连接器”。选择这个角色,复制到剪贴板,然后粘贴下面的单引号之间:

declare @t nvarchar(10) 
set @t = '͏' 
select rtrim(ltrim(@t)) -- we can try and trim it, but by this stage it's already a '?' 

你会得到一个问号了,因为它不知道如何当它施放它代表了这个非ASCII字符到varchar。为了强制它接受它为双字节字符(nvarchar),您需要改为使用N'',如前所述。上述引号前添加N问号消失(但原来不可见字符在输出保存 - 和ltrim,并如下面所示rtrim将无法​​将其删除):

declare @t nvarchar(10), 
     @s varchar(10) -- note: single-byte string 
set @t = rtrim(ltrim(N'͏')) -- trimming doesn't work here either 
set @s = @t 
select @s -- still outputs a question mark 

进口数据绝对可以做到这个,我以前见过,像上面显示的那些人物特别难以诊断,因为你看不到他们!您需要创建某种清理流程来删除这些不打印邮件(以及其他任何垃圾邮件),并确保您在任何地方都使用nvarchar,否则最终会出现此问题。更糟的是,那些虚幻的问号将成为真正的问号,你将无法与合法问号区分开来。

要查看字符代码你处理,你可以投为varbinary如下:

declare @t nvarchar(10) 
set @t = N'͏test?' 
select cast(@t as varbinary) -- returns 0x4F0374006500730074003F00 

-- Returns: 
-- 0x4F03 7400 6500 7300 7400 3F00 
-- badchar t e s t ? 

我们摆脱它:

declare @t nvarchar(10) 
set @t = N'͏test?' 
select cast(@t as varbinary) -- bad char 
set @t = replace(@t COLLATE Latin1_General_100_BIN2, nchar(0x034f), N''); 
select cast(@t as varbinary) -- gone! 

注意,我不得不调换字节顺序从0x4f030x034f(同样的原因“t”在输出中出现为0x7400,而不是0x0074)。有关我们使用二进制排序规则的一些说明,请参阅this answer

这是一种混乱,因为你不知道什么是肮脏的人物,他们可能是成千上万的可能性之一。一种选择是使用like甚至unicode()function迭代字符串,并放弃不在可接受字符列表中的字符串中的字符,但这可能会很慢。这可能是因为你的大部分坏字符都在字符串的开始或结尾,如果这是你认为可以做出的假设,那么这可能会加速这个过程。

根据我上面向您展示的内容,如果您需要导入大量数据,您可能需要在SQL Server外部或作为SSIS导入的一部分构建其他进程。如果您不确定这是否是最好的方法,那么最好在一个新问题中回答。

我希望有帮助。

+0

很好的解释!从字面上看,它正在疯狂。在我的情况下,字符是“0x0B20”... unicode为零宽度空间。这意味着WTF,我不知道。 – wgpubs