Sql server 在SQL Server 2008和早期版本中读取带有奇怪字符的字符串时出现问题
我今天的问题是:我们将一些信息从文本文件加载到SQLServer表中。问题是,对于一个字段,我意识到字符串值有点奇怪 使用SQL Server client 2008或更早版本查询表时,得到以下结果集: 即使我尝试运行下面这样的查询,结果集也是空的:Sql server 在SQL Server 2008和早期版本中读取带有奇怪字符的字符串时出现问题,sql-server,sql-server-2008,tsql,unicode,Sql Server,Sql Server 2008,Tsql,Unicode,我今天的问题是:我们将一些信息从文本文件加载到SQLServer表中。问题是,对于一个字段,我意识到字符串值有点奇怪 使用SQL Server client 2008或更早版本查询表时,得到以下结果集: 即使我尝试运行下面这样的查询,结果集也是空的: select REPLACE(LTRIM(RTRIM(cust_po)), ' ', ' ') from dbo.test_char where cust_po like '%076929%' 奇怪的是:对于SQL Server 2016,
select REPLACE(LTRIM(RTRIM(cust_po)), ' ', ' ')
from dbo.test_char
where cust_po like '%076929%'
奇怪的是:对于SQL Server 2016,只打开表看起来很正常,尽管查询也不会返回任何结果:
现在,根据@SolomonRutzky的两条指令,我执行了下面的查询,以获得varbinary中的结果
新结果为:0x30003700360390032003900BC05BC05BC05BC05BC05BC05BC05BC05BC05BC05BC05BC05BC05BC05
如果没有奇怪的字符或空间或其他地方,怎么能把它作为varchar呢?怎么回事?
现在数据的VARBINARY
表示已经发布,问题就清楚多了
如我们所见,带有“奇数”字符的两行是:
0x300037003600390032003900BC05BC05BC05BC05BC05BC05BC05BC05BC05
此列为NVARCHAR
,这意味着编码为UTF-16 Little-Endian。UTF-16意味着我们查看每个2字节块(字符将是这些2字节块的1或2组),而小尾端意味着每个2字节块中的字节顺序相反。也就是说,第一个字符是3000
(2个字节),它等于代码点U+0030,即数字0
。下一个字符是3700
,它是代码点U+0037,它是编号7
。依此类推,直到值中的最后一个9
然后我们得到九组BC05
,这是代码点U+05BC,这是。这就是它变得有趣的地方,因为这里有三件不同的事情:
0
的左侧都有一个小点)选择N'4 11'+复制(NCHAR(0x05BC),10)+N'88 f';
返回:
4 11、88 f
请注意第二个1
左侧的单点。即使字符串中有10个单点(由于REPLICATE
),也只有一个单点。这就是我的浏览器显示的内容,如下图所示:
但我在我的结果表格中看到了以下内容:
注意点是如何位于第一个而不是第二个1
的左侧,以及11
在88
和f
之间的位置
如果我将结果网格复制并粘贴到查询编辑器中,我会看到:
请注意,有几个红点
为什么像“%076929%”这样的客户订单不返回任何行?
这是因为字符串比较做了它应该做的事情和应用语言规则。不管字节的顺序是什么,重要的是从人的角度来看它是如何呈现字符串的。而且由于这个特殊字符是一个组合字符,它不在前面的字符后面,它是PAR。也就是说,您的
076929
值中的第二个9
不再是9
,而是9
+Dagesh
选择1,其中
N'123'+复制(NCHAR(0x05BC),5)类似于N'%123'+复制(NCHAR(0x05BC),4)+N'%;
--没有返回行
选择2个位置
N'123'+复制(NCHAR(0x05BC),5)类似于N'%123'+复制(NCHAR(0x05BC),5)+N'%;
-- 2
选择3,其中N'9'+NCHAR(0x05BC)=N'9'
--没有返回行
你如何摆脱那些角色?
假设此U+05BC字符是数据中唯一的问题,您可以执行简单的替换。您已经尝试过此操作,但是replace
找不到匹配项。发生这种情况时,您需要使用二进制排序规则,如下所示:
选择替换(N'4 11'+复制(NCHAR(0x05BC),5)+N'88 f',
NCHAR(0x05BC)校对拉丁文1\u General\u 100\u BIN2,
N‘~’);
--4 11 ~~~~~88华氏度
首先-当@solomon Rutzky查看您的代码时,您会得到很好的帮助;)
我目前还没有NVarchar版本,但是,如果您只希望列中的数值,那么可以使用。解决方案看起来是这样的
-- sample data with a couple characters to screw you up.
DECLARE @table TABLE (somestring nvarchar(100));
INSERT @table
SELECT CONCAT(NCHAR(365), '123') UNION ALL
SELECT CONCAT(CHAR(0), '789');
-- solution
SELECT *
FROM @table t
CROSS APPLY dbo.DigitsOnlyEE(t.somestring);
结果:
somestring DigitsOnly
------------ ------------
ŭ123 123
789 789
这有用吗?为什么显示SSMS 2008的查询结果而显示SSMS 2016的表编辑器?看到与第一张图像相同的输出将很有帮助,但对于SSMS 2016(因为您在那里做了区分)。但是,不要执行最初使用的查询,而是执行以下命令,然后发布结果的图像:SELECT cust\u po,CONVERT(VARB