在 xml.modify 方法中使用子字符串和可能的替代方案

问题描述 投票:0回答:1

有人知道如何批量更新 SQL Server 数据库中的列吗?

情况如下:我有一个列

Config
定义为
nvarchar(max)
,但它包含格式化的 XML。

这是一个例子:

<?xml version="1.0" encoding="utf-16"?>  
<ArrayOfLearningPathItem xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">    
    <LearningPathItem xsi:type="type">      
        <Id>id</Id>      
        <Title>title</Title>      
        <Content>&lt;iframe allowfullscreen src="https://site.sharepoint.com/sites/site/SitePages/page.aspx" width="100%" height="100%" data-embedSize="3"&gt;&lt;/iframe&gt;</Content>      
        <EmbedType>typeType</EmbedType>    
    </LearningPathItem>  
</ArrayOfLearningPathItem>

我需要批量更新那里的内容元素,因此代码将被删除,只保留网址。

因此从这个示例来看,结果应该是 https://site.sharepoint.com/sites/site/SitePages/page.aspx

我尝试将列转换为xml,将其放入临时表,搜索带有sharepoint链接的所有元素并使用新内容更新它们,然后将临时表与旧表连接起来。

但是,我仍然找不到从代码中剪切 url 的方法。对于其他元素来说更容易,如果我只更改 EmbedType 参数,效果会很好:

UPDATE @TempTable
SET ConfigXML.modify('
    replace value of (/ArrayOfLearningPathItem/LearningPathItem[EmbedType="type1" and Content[contains(text()[1], "sharepoint.com")]]/EmbedType/text())[1] 
    with 
    "type2"
    ');

对于url我猜想这样的东西可以工作,如果substring-before和substring-after可以在xml修改方法中使用,但只能使用substring

UPDATE @TempTable
SET ConfigXML.modify('
    replace value of (/ArrayOfLearningPathItem/LearningPathItem[EmbedType="type1" and Content[contains(text()[1], "sharepoint.com")]]/Content/text())[1]
    with 
    substring-before(substring-after(/ArrayOfLearningPathItem/LearningPathItem[EmbedType="type1" and Content[contains(text()[1], "sharepoint.com")]]/Content/text(), "src=&quot;"), "&quot;")
');
sql sql-server xml t-sql xquery-sql
1个回答
0
投票

不幸的是,SQL Server 不支持大多数新的 XQuery 函数。您需要将数据提取到 SQL 中,使用

CHARINDEX
SUBSTRING
获取正确的数据,然后使用
sql:column

将其推回 XQuery
UPDATE t
SET ConfigXML.modify('
    replace value of (
      /ArrayOfLearningPathItem/LearningPathItem
      [EmbedType="type1" and Content[contains(text()[1], "sharepoint.com")]]
      /Content/text()
      )[1]
    with sql:column("v3.url")
')
FROM @TempTable t
CROSS APPLY (
    SELECT ContentValue =
      T.ConfigXML.value('
        (/ArrayOfLearningPathItem/LearningPathItem
          [EmbedType="type1" and Content[contains(text()[1], "sharepoint.com")]]
         /Content/text())[1]', 'nvarchar(max)')
) x1
CROSS APPLY (
    SELECT src = NULLIF(CHARINDEX('src="', x1.ContentValue), 0) + 5
) v1
CROSS APPLY (
    SELECT quote = NULLIF(CHARINDEX('"', x1.ContentValue, v1.src), 0)
) v2
CROSS APPLY (
    SELECT url = SUBSTRING(x1.ContentValue, v1.src, v2.quote - v1.src)
) v3;

db<>小提琴

© www.soinside.com 2019 - 2024. All rights reserved.