[英]Update XML node value based on a match from XML type column
I have a SQL table with a XML column.我有一个带有 XML 列的 SQL 表。
Table structure is表结构是
CREATE TABLE [dbo].[UserSettings](
[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NOT NULL,
[UserName] [varchar](100) NULL,
[Setting] [xml] NULL,
[CreateDate] [datetime] NOT NULL
)
The Setting xml column looks like this:设置 xml 列如下所示:
<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<UserID>1</UserID>
<Reports>
<string>Report - 1</string>
<string>Report - 2</string>
<string>Report - 3</string>
<string>Report - 4</string>
</Reports>
</UserSettings>
I want to update Report - 1 to Report - One, Report - 2 to Report - Two in <Reports>
我想将
<Reports>
Report - 1 更新为 Report - One,将 Report - 2 更新为 Report - Two
And also, if there is a value Report - 4 then I want to remove it from <Reports>
而且,如果有一个值 Report - 4 那么我想从
<Reports>
删除它
So my end result for in the column should look like this:所以我在专栏中的最终结果应该是这样的:
<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<UserID>1</UserID>
<Reports>
<string>Report - One</string>
<string>Report - Two</string>
<string>Report - Three</string>
</Reports>
</UserSettings>
EDIT: I have tried the REPLACE approach.编辑:我尝试过 REPLACE 方法。 I am not sure if that is the most effective way to do this.
我不确定这是否是最有效的方法。
update UserSettings
set Setting=REPLACE(convert(varchar(max),Setting),'<string>Report - 1</string>','<string>Report - One</string>')
where convert(varchar(max),Setting) like '%<string>Report - 1</string>%'
EDIT: I read about modify() method but the sequence of report could be in any order.编辑:我阅读了modify() 方法,但报告的顺序可以是任何顺序。 I couldn't get my query to work with it.
我无法让我的查询使用它。
simple way is to use Replace as string, however this method is not useful if you don't want to replace that value everywhere ( for example outside of <Reports>
tag)简单的方法是使用 Replace as string,但是如果您不想在任何地方替换该值(例如在
<Reports>
标记之外),则此方法没有用
-- to update report 1 to 3 ( I just did it for 1):
update UserSettings
set Setting = replace(cast(Setting as nvarchar(max)) , '<string>Report - 1</string>','<string>Report - one</string>')
-- to remove report 4
update UserSettings
set Setting = replace(cast(Setting as nvarchar(max)) , '<string>Report - 4</string>','')
You can try a different approach.您可以尝试不同的方法。
Instead of find-and-replace, iemodify, it is possible to compose XML on the fly via XQuery and its FLWOR expression.代替查找和替换,即修改,可以通过 XQuery 及其 FLWOR 表达式动态组合 XML。
SQL SQL
-- DDL and sample data population, start
DECLARE @UserSettings TABLE (
[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NOT NULL,
[UserName] [varchar](100) NULL,
[Setting] [xml] NULL,
[CreateDate] [datetime] NOT NULL
);
INSERT INTO @UserSettings (UserID, UserName, Setting, CreateDate)
VALUES
(0, 'John', N'<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<UserID>1</UserID>
<Reports>
<string>Report - 1</string>
<string>Report - 2</string>
<string>Report - 3</string>
<string>Report - 4</string>
</Reports>
</UserSettings>',
GETDATE()
);
-- DDL and sample data population, end
UPDATE @UserSettings
SET Setting = Setting.query('<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
{
for $x in /UserSettings/*[local-name()!="Reports"]
return $x,
element Reports {
for $y in ("One","Two","Three")
return <string>{concat("Report - ", $y)}</string>
}
}
</UserSettings>');
-- test
SELECT * FROM @UserSettings;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.