从先前转换为 XML 的 table 列中提取多个值
Extracting multiple values from a table column previously casted to XML
我有一个 table 列作为 nvarchar(max),其中包含以下 XML 数据:
<?xml version="1.0" encoding="utf-8"?>
<SerializableAlertDetail xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SerializableContextAlertDetail">
<ContextName>Evénements PTI mobile</ContextName>
<EnumValueName>Pré Alerte immobilisme</EnumValueName>
</SerializableAlertDetail>
我想 SELECT 'ContextName' 和 'EnumValueName' XML 元素的串联。
起初我只是尝试 return 一个元素,效果很好:
SELECT CAST(REPLACE(dbo.AlertDetail.Context, 'encoding="utf-8"', '') AS XML).value('(/SerializableAlertDetail/*[local-name() = "ContextName"])[1]', 'nvarchar(max)') As DisplayName FROM Table
因为我不想在查询中转换两次,所以我正在寻找一种方法将 XML 列从此处解构为 table 和 select 列。到目前为止,我遇到了以下无效查询:
SELECT T0.XML.value('ContextName', 'nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X)
CROSS APPLY T.X.nodes('SerializableAlertDetail') AS T0(XML)
但失败并显示以下错误消息:
XQuery [T.X.value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
感谢任何帮助。
编辑 1
我遇到了以下有效但可能不是最佳查询的查询:
SELECT T0.XML.query('./ContextName').value('.', 'nvarchar(max)') + T0.XML.query('./EnumValueName').value('.', 'nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X)
CROSS APPLY T.X.nodes('SerializableAlertDetail') AS T0(XML)
编辑 2
已将 ntext 替换为 nvarchar(max) ;)
你已经被告知,NTEXT
几个世纪以来一直被弃用 ;-)
只是一些背景:
NTEXT
是 2 字节 编码的文本,将转换为 NVARCHAR
。但是你的 XML 大喊 我是 UTF-8!!!!,这是一个明显的谎言。在 NTEXT
之内 - 当然! - 不是 UTF-8。有两种方法可以继续:
- 将您的
NTEXT
转换为 NVARCHAR
,然后转换为 VARCHAR
,最后转换为 XML。这将起作用,因为 UTF-8 在纯拉丁语中是 1 字节编码。
- 通过将
utf-8
替换为 1) 什么都没有(像你一样)、2) utf-16
或 3) ucs-2
(正确的东西)来消除谎言。
关于您的查询:这可以做得更简单一些,因为没有重复的内容,因此不需要派生 table。试试这个:
SELECT X.value('(/SerializableAlertDetail/ContextName/text())[1]','nvarchar(max)')
+ X.value('(/SerializableAlertDetail/EnumValueName/text())[1]','nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X);
这应该会更快...
在可读性方面你甚至可以尝试
SELECT X.value('(//ContextName)[1]','nvarchar(max)')
+ X.value('(//EnumValueName)[1]','nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X);
我有一个 table 列作为 nvarchar(max),其中包含以下 XML 数据:
<?xml version="1.0" encoding="utf-8"?>
<SerializableAlertDetail xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SerializableContextAlertDetail">
<ContextName>Evénements PTI mobile</ContextName>
<EnumValueName>Pré Alerte immobilisme</EnumValueName>
</SerializableAlertDetail>
我想 SELECT 'ContextName' 和 'EnumValueName' XML 元素的串联。
起初我只是尝试 return 一个元素,效果很好:
SELECT CAST(REPLACE(dbo.AlertDetail.Context, 'encoding="utf-8"', '') AS XML).value('(/SerializableAlertDetail/*[local-name() = "ContextName"])[1]', 'nvarchar(max)') As DisplayName FROM Table
因为我不想在查询中转换两次,所以我正在寻找一种方法将 XML 列从此处解构为 table 和 select 列。到目前为止,我遇到了以下无效查询:
SELECT T0.XML.value('ContextName', 'nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X)
CROSS APPLY T.X.nodes('SerializableAlertDetail') AS T0(XML)
但失败并显示以下错误消息:
XQuery [T.X.value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
感谢任何帮助。
编辑 1
我遇到了以下有效但可能不是最佳查询的查询:
SELECT T0.XML.query('./ContextName').value('.', 'nvarchar(max)') + T0.XML.query('./EnumValueName').value('.', 'nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X)
CROSS APPLY T.X.nodes('SerializableAlertDetail') AS T0(XML)
编辑 2
已将 ntext 替换为 nvarchar(max) ;)
你已经被告知,NTEXT
几个世纪以来一直被弃用 ;-)
只是一些背景:
NTEXT
是 2 字节 编码的文本,将转换为 NVARCHAR
。但是你的 XML 大喊 我是 UTF-8!!!!,这是一个明显的谎言。在 NTEXT
之内 - 当然! - 不是 UTF-8。有两种方法可以继续:
- 将您的
NTEXT
转换为NVARCHAR
,然后转换为VARCHAR
,最后转换为 XML。这将起作用,因为 UTF-8 在纯拉丁语中是 1 字节编码。 - 通过将
utf-8
替换为 1) 什么都没有(像你一样)、2)utf-16
或 3)ucs-2
(正确的东西)来消除谎言。
关于您的查询:这可以做得更简单一些,因为没有重复的内容,因此不需要派生 table。试试这个:
SELECT X.value('(/SerializableAlertDetail/ContextName/text())[1]','nvarchar(max)')
+ X.value('(/SerializableAlertDetail/EnumValueName/text())[1]','nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X);
这应该会更快...
在可读性方面你甚至可以尝试
SELECT X.value('(//ContextName)[1]','nvarchar(max)')
+ X.value('(//EnumValueName)[1]','nvarchar(max)')
FROM Table c
CROSS APPLY (SELECT CAST(REPLACE(c.Context, 'encoding="utf-8"', '') AS XML)) as T(X);