SQL 服务器添加?从 XML 转换时单元格值前后

SQL Server adding ? before and after cell value when converting from XML

我有一个 C# 应用程序需要一个 Excel (.xlsx) 文件,将其转换为 XML,然后将其传递给 SQL 服务器进行转换和验证。

这多年来一直运作良好,但我现在有一个文件,其中几个单元格 ? 添加到值的开头和结尾。 XML 没有反映它们,但一定有一个隐藏的特殊字符。

这里复制了XML和T-SQL看结果:

DECLARE @x xml = '<Root>
 <Row>
  <ITEMNO>1</ITEMNO>
  <PARTSOURCE>BUY</PARTSOURCE>
  <QTY>1</QTY>
  <CUSTPARTNO>‭10-0306‬</CUSTPARTNO>
  <CREV>XYS</CREV>
  <DESCRIPT>CAP,CER,10PF,50V,NP0,RF,0402</DESCRIPT>
  <REFDESG>‭C96‬</REFDESG>
  <WORKCENTER />
  <ASSYNUM>18-0074-01 REV J</ASSYNUM>
  <ASSYREV />
  <ASSYDESC />
  <CUSTNO>2519</CUSTNO>
 </Row>
</Root>'

SELECT DENSE_RANK() OVER(ORDER BY
  x.importBom.query('ITEMNO/text()').value('.','VARCHAR(MAX)')+
  x.importBom.query('DESCRIPT/text()').value('.', 'VARCHAR(MAX)'))rowNum,
  x.importBom.query('ITEMNO/text()').value('.','VARCHAR(MAX)') itemno,
  UPPER(x.importBom.query('PARTSOURCE/text()').value('.', 'VARCHAR(MAX)')) partSource,
  x.importBom.query('QTY/text()').value('.', 'VARCHAR(MAX)') qty,
  x.importBom.query('CUSTPARTNO/text()').value('.', 'VARCHAR(MAX)') custPartNo,
  x.importBom.query('CREV/text()').value('.', 'VARCHAR(MAX)')crev,
  x.importBom.query('DESCRIPT/text()').value('.', 'VARCHAR(MAX)')descript,
  UPPER(x.importBom.query('WORKCENTER/text()').value('.', 'VARCHAR(MAX)'))workCenter,
  x.importBom.query('REFDESG/text()').value('.', 'VARCHAR(MAX)')refDesg,
  x.importBom.query('CUSTNO/text()').value('.', 'VARCHAR(MAX)')custno,
  x.importBom.query('ASSYNUM/text()').value('.', 'VARCHAR(MAX)')assynum,
  x.importBom.query('ASSYREV/text()').value('.', 'VARCHAR(MAX)')assyrev,
  x.importBom.query('ASSYDESC/text()').value('.', 'VARCHAR(MAX)')assydesc
FROM @x.nodes('/Root/Row') AS X(importBom)
OPTION (OPTIMIZE FOR(@x = NULL))

CUSTPARTNOREFDESG 字段都在 SQL 服务器 table 中获得 ?,但其他列没有。这是 CUSTPARTNO 值的服务器示例:?10-0306?

创建 XML 时,我执行以下操作以删除末尾的一些特殊字符和不需要的空格:

cellValue = cellValue.Replace("\r", "") //carriage return
                     .Replace("\n", " ")//new line
                     .Replace("\t", "")//tab
                     .Trim();

这不影响结果。

如何"see"隐藏特殊字符?

而且,将它们从单元格中删除以便它们不会添加到 SQL 服务器 table 中的最佳方法是什么?

不知道这是否仍然是一个悬而未决的问题,但我很好奇...

如果你用光标慢慢地浏览,你会看到在给定的地方光标不会向前移动...这就是 HEX 编辑器显示的内容

在这两种情况下,您的值都由 unicode 字符 2D20 和 2C20 构成。 2D20 是 "georgian small letter hae",2C20 是 "glagolitic capital letter yeri"。也许这可以帮助您了解它的来源。

根据 Panagiotis Kanavos 的说法,如果您将 XML 的声明更改为

,它就会起作用
DECLARE @x xml = N'<Root> ...

然后在 .value() 调用中使用 NVARCHAR

顺便说一句:这样做可以缩短您使用 .query() 然后 .value() 的查询。

SELECT DENSE_RANK() OVER(ORDER BY
  x.importBom.value('ITEMNO[1]','NVARCHAR(MAX)')
    + x.importBom.value('DESCRIPT[1]', 'NVARCHAR(MAX)'))rowNum,
  x.importBom.value('ITEMNO[1]','NVARCHAR(MAX)') itemno,
  UPPER(x.importBom.value('PARTSOURCE[1]', 'NVARCHAR(MAX)')) partSource,
  x.importBom.value('QTY[1]', 'NVARCHAR(MAX)') qty,
  x.importBom.value('CUSTPARTNO[1]', 'NVARCHAR(MAX)') custPartNo,
  x.importBom.value('CREV[1]', 'NVARCHAR(MAX)')crev,
  x.importBom.value('DESCRIPT[1]', 'NVARCHAR(MAX)')descript,
  UPPER(x.importBom.value('WORKCENTER[1]', 'NVARCHAR(MAX)'))workCenter,
  x.importBom.value('REFDESG[1]', 'NVARCHAR(MAX)')refDesg,
  x.importBom.value('CUSTNO[1]', 'NVARCHAR(MAX)')custno,
  x.importBom.value('ASSYNUM[1]', 'NVARCHAR(MAX)')assynum,
  x.importBom.value('ASSYREV[1]', 'NVARCHAR(MAX)')assyrev,
  x.importBom.value('ASSYDESC[1]', 'NVARCHAR(MAX)')assydesc
FROM @x.nodes('/Root/Row') AS X(importBom)
OPTION (OPTIMIZE FOR(@x = NULL))