在 SQL 服务器 table 中键入 XML 更新
Typed XML Update in SQL Server table
我有第 3 方 table 和 XML 列,如果 key\string = 'recipient'。这是原始 XML 的一部分,包含 2 个项目:
DECLARE @myDoc XML
SET @myDoc = '<Root>
<item>
<key>
<string>subject</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">test subject</anyType>
</value>
</item>
<item>
<key>
<string>recipient</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">prodops@company.com</anyType>
</value>
</item>
</Root>'
SET @myDoc.modify('
declare namespace q1="http://www.w3.org/2001/XMLSchema"; declare namespace p5="http://www.w3.org/2001/XMLSchema-instance";
replace value of (/q1:Root/q1:item/q1:value/p5:type="q1:string")[1]
with ("devops@company.com")
')
SELECT @myDoc
我有点黑了我的方式到这一点 - XML 不是我的强项。基于 BOL,我需要在 modify()
?正确的?我确定我缺少一个 if 语句,但对于如何为收件人取消引用该值只是一个谜。以前有人这样做过——我敢肯定。目标是在刷新生产数据后合并到 post-restore 脚本中进行测试。
请注意,这会按原样失败
Msg 2337, Level 16, State 1, Line 125
XQuery [modify()]: The target of 'replace' must be at most one node, found 'xs:boolean ?'"
您需要指定text()
来替换节点的内部文本。您还需要引用anyType
节点,您没有.
从表面上看,none 个相关节点实际上使用了命名空间,因此我们根本不需要它们。
SET @myDoc.modify('
replace value of (/Root/item[key[string[text()="recipient"]]]/value/anyType/text())[1]
with ("devops@company.com")
');
解释:
- 下降到
/Root
,不需要命名空间
- 使用谓词下降到
/item[
...
- ... 必须有
key[
个节点 ...
- ... 有
string[
个节点 ...
- ... 内部有
text()="recipient"]]]
- 回到原来的
item
我们下降/value
然后/anyType
然后内部/text()
- 所有括起来到
[1]
以确保单个节点
问题的标题指定“在 SQL 服务器 table 中键入 XML 更新”。
所提供的 XML 不受任何 XSD 架构的约束。这就是为什么不输入 XML 的原因。一个真正类型的 XML 更新不同。
请尝试以下解决方案。它具有以下内容:
- 更简单的 XPath 谓词表达式。
- 使用 SQL 变量作为新值。
所有功劳归功于@Charlieface。
SQL
DECLARE @myDoc XML =
N'<Root>
<item>
<key>
<string>subject</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
p5:type="q1:string">test subject</anyType>
</value>
</item>
<item>
<key>
<string>recipient</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
p5:type="q1:string">prodops@company.com</anyType>
</value>
</item>
</Root>';
DECLARE @anyType VARCHAR(30) = 'devops@company.com';
SET @myDoc.modify('
replace value of (/Root/item[key/string/text()="recipient"]/value/anyType/text())[1]
with (sql:variable("@anyType"))
');
-- test
SELECT @myDoc;
我有第 3 方 table 和 XML 列,如果 key\string = 'recipient'。这是原始 XML 的一部分,包含 2 个项目:
DECLARE @myDoc XML
SET @myDoc = '<Root>
<item>
<key>
<string>subject</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">test subject</anyType>
</value>
</item>
<item>
<key>
<string>recipient</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">prodops@company.com</anyType>
</value>
</item>
</Root>'
SET @myDoc.modify('
declare namespace q1="http://www.w3.org/2001/XMLSchema"; declare namespace p5="http://www.w3.org/2001/XMLSchema-instance";
replace value of (/q1:Root/q1:item/q1:value/p5:type="q1:string")[1]
with ("devops@company.com")
')
SELECT @myDoc
我有点黑了我的方式到这一点 - XML 不是我的强项。基于 BOL,我需要在 modify()
?正确的?我确定我缺少一个 if 语句,但对于如何为收件人取消引用该值只是一个谜。以前有人这样做过——我敢肯定。目标是在刷新生产数据后合并到 post-restore 脚本中进行测试。
请注意,这会按原样失败
Msg 2337, Level 16, State 1, Line 125 XQuery [modify()]: The target of 'replace' must be at most one node, found 'xs:boolean ?'"
您需要指定text()
来替换节点的内部文本。您还需要引用anyType
节点,您没有.
从表面上看,none 个相关节点实际上使用了命名空间,因此我们根本不需要它们。
SET @myDoc.modify('
replace value of (/Root/item[key[string[text()="recipient"]]]/value/anyType/text())[1]
with ("devops@company.com")
');
解释:
- 下降到
/Root
,不需要命名空间 - 使用谓词下降到
/item[
... - ... 必须有
key[
个节点 ... - ... 有
string[
个节点 ... - ... 内部有
text()="recipient"]]]
- 回到原来的
item
我们下降/value
然后/anyType
然后内部/text()
- 所有括起来到
[1]
以确保单个节点
问题的标题指定“在 SQL 服务器 table 中键入 XML 更新”。
所提供的 XML 不受任何 XSD 架构的约束。这就是为什么不输入 XML 的原因。一个真正类型的 XML 更新不同。
请尝试以下解决方案。它具有以下内容:
- 更简单的 XPath 谓词表达式。
- 使用 SQL 变量作为新值。
所有功劳归功于@Charlieface。
SQL
DECLARE @myDoc XML =
N'<Root>
<item>
<key>
<string>subject</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
p5:type="q1:string">test subject</anyType>
</value>
</item>
<item>
<key>
<string>recipient</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
p5:type="q1:string">prodops@company.com</anyType>
</value>
</item>
</Root>';
DECLARE @anyType VARCHAR(30) = 'devops@company.com';
SET @myDoc.modify('
replace value of (/Root/item[key/string/text()="recipient"]/value/anyType/text())[1]
with (sql:variable("@anyType"))
');
-- test
SELECT @myDoc;