如何批量更新SQL Server数据库中的列?

情况如下:我有一个被定义为nvarchar(max)的列Config,但它包含格式化的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>

我需要批量更新内容元素,这样代码将被删除,只有URL应该留下来.

所以从这个例子中,结果应该是

<Content>https://site.sharepoint.com/sites/site/SitePages/page.aspx</Content> 

我try 将列转换为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,我猜应该是这样的,如果在XML Modify方法中可以使用子字符串-BEFORE和SUBSTRING-AFTER,但只能使用子字符串

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 Server不支持大多数新的(ISH)XQuery函数.您需要将数据提取到SQL中,使用CHARINDEXSUBSTRING获取正确的数据,然后使用sql:column将其推送回XQuery

UPDATE t
SET ConfigXML.modify('
    replace value of (
         /ArrayOfLearningPathItem/LearningPathItem
          [EmbedType="type1"]
         /Content/text()[contains(data(.), "sharepoint.com")]
        )[1]
    with sql:column("v3.url")
')
FROM @TempTable t
CROSS APPLY (
    SELECT ContentValue =
      T.ConfigXML.value('
        (/ArrayOfLearningPathItem/LearningPathItem
          [EmbedType="type1"]
         /Content/text()[contains(data(.), "sharepoint.com")]
        )[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<>fiddle

Sql相关问答推荐

Oracle SQL对列进行汇总并在列表底部显示总计

无法找到正确的SQL查询需求

如何退回当年的所有参赛作品?""

当交叉联接3个或更多表时,实体框架中是否会传输冗余的行数据并占用数据库带宽?

直接加法(1+1)与聚合函数SUM(1+1)的区别是什么

从包含PostgreSQL中的JSON值的列中提取列表或目录

是否可以为表中的所有列生成散列值?

WooCommerce产品的SQL查询:获取sku和产品标签

STContains、STIntersections和STWithin返回错误的地理结果

SQL Server 查询 WHERE LIKE

试图找到两个身份列表的交集(列表的长度不同),但获取列 id 不明确?

如何在 SQL 中将两行(或多行)jsonb 数组合并为一行

查询中获取审批者不起作用

MS ACCESS 错误插入 X(...) 从 A 联合 Select ... 从 B

如何根据与 BigQuery 中另一个表的匹配更新一个表中的列?

如何按日期和位置对最近 3 个报告日期的 SQL 查询结果进行透视?

在 PostgreSQL 中使用重音敏感排序进行重音不敏感搜索

在 sql 中合并系列以删除重复项

从多个连接返回 1 行到同一个表 - SQL Server

SQL 中的问题与包含最大日期的记录连接