【问题标题】:Possible (invisible) characters in text pasted from Excel or XML to a TSQL query从 Excel 或 XML 粘贴到 SQL 查询的文本中可能出现的(不可见的)字符
【发布时间】:2021-03-29 16:16:52
【问题描述】:

我的 ASP.Net 应用程序接收上传的 Excel 文件,然后转换为 XML 以作为存储过程参数传递以进行处理。此文件包含许多通过文本匹配的条目以找到相应的值。

今天(在完美工作多年后)三个看似相同的值在文本匹配中导致混合结果。我只能举例说明:

  • 第一个值是 Excel 中的原始值(从 电子表格)。
  • 第二个值是 Web 应用程序的值 保存到 XML,并且是从探查器显示的原始值 参数值
  • 第三个值是当前存在的值 在表格中

代码是从 SSMS 粘贴过来的:

SELECT SkillGroupTitle FROM tbl_SkillGroups WHERE SkillGroupTitle = N'Quality Assurance Instruction (QAI)'; -- pasted from Excel
SELECT SkillGroupTitle FROM tbl_SkillGroups WHERE SkillGroupTitle = N'Quality Assurance Instruction (QAI)'; -- pasted from xml
SELECT SkillGroupTitle FROM tbl_SkillGroups WHERE SkillGroupTitle = N'Quality Assurance Instruction (QAI)'; -- pasted from SQL table (existing value)

有人可以告诉这里发生了什么吗?所有值在视觉上看起来相同,但在 Excel 的入站值中明显有些东西不同。

更新

将这两个值粘贴到十六进制转换器中,确实有三个不同。

Excel 数据:

51 75 61 6c 69 74 79 a0 41 73 73 75 72 61 6e 63 65 a0 49 6e 73 74 72 75 63 74 69 6f 6e 20 28 51 41 49 29 0a
                     --                            --                                                    --

SQL 数据:

51 75 61 6c 69 74 79 20 41 73 73 75 72 61 6e 63 65 20 49 6e 73 74 72 75 63 74 69 6f 6e 20 28 51 41 49 29

有人可以在这里解释一下吗?

【问题讨论】:

  • 嗯,很有趣。我将用调查结果更新问题(尽管我仍然不知道字符串中的这些差异是什么)
  • a0 是一个不间断的空格:en.wikipedia.org/wiki/Non-breaking_space。您需要先清理字符串,然后再将其发送以进行查询。
  • 惊人的指点,谢谢。我让它与REPLACE(N'Quality Assurance Instruction (QAI)', NCHAR(0x00A0), NCHAR(0x0020))匹配。如果可以,请迁移您的评论作为答案。

标签: sql-server excel tsql


【解决方案1】:

更新

首先,要识别导致字符串不相等的隐藏字符,您可以像这样利用ngrams8k

WITH tbl_SkillGroups(dSource, SkillGroupTitle) AS 
(
SELECT 'Excel', N'Quality Assurance Instruction (QAI)' -- pasted from Excel
UNION ALL
SELECT 'XML',   N'Quality Assurance Instruction (QAI)'+CHAR(10) -- pasted from xml
UNION ALL
SELECT 'SQL',   N'Quality Assurance Instruction (QAI)'+CHAR(13) -- pasted from SQL table (existing value)
)
SELECT 
  [Source]   = ts.dSource,
  Position   = ng.Position,
  Token      = ng.Token, 
  asciiValue = ASCII(ng.Token)
FROM        tbl_SkillGroups                     AS ts
CROSS APPLY samd.ngrams8k(ts.SkillGroupTitle,1) AS ng
--WHERE       ng.Position > 32 -- Zoom into the last few characters

返回:

Source Position  Token   asciiValue
------ --------- ------- -----------
Excel  33        A       65
Excel  34        I       73
Excel  35        )       41  -- Only 35 characters 
XML    33        A       65
XML    34        I       73
XML    35        )       41
XML    36                10 -- 36th character is a CHAR(10) (Looks like a space)
SQL    33        A       65
SQL    34        I       73
SQL    35        )       41
SQL    36                13 -- 36th character is a CHAR(13) (Also looks like a space)

接下来,要清除输入中的隐藏字符,您可以使用 PatReplace8k

WITH tbl_SkillGroups(dSource, SkillGroupTitle) AS 
(
SELECT 'Excel', N'Quality Assurance Instruction (QAI)' -- pasted from Excel
UNION ALL
SELECT 'XML',   N'Quality Assurance Instruction (QAI)'+CHAR(10) -- pasted from xml
UNION ALL
SELECT 'SQL',   N'Quality Assurance Instruction (QAI)'+CHAR(13) -- pasted from SQL table (existing value)
)
SELECT SkillGroupTitle
FROM tbl_SkillGroups as ts
CROSS APPLY PatReplace8K(ts.Skillgrouptitle,'[^a-zA-Z ()]','') as pr
WHERE SkillGroupTitle = pr.NewString

返回:

SkillGroupTitle
------------------------------------
Quality Assurance Instruction (QAI)
Quality Assurance Instruction (QAI)
Quality Assurance Instruction (QAI)

在这里,PatReplace8k 将删除任何与模式不匹配的字符(字母、空格和括号),从而使这三个值相等。

【讨论】:

  • 谢谢。挑战在于表格接受来自不同语言(例如英语和挪威语)的字符。我不确定这是否会使 Regex 模式不可行...?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多