更新 XML 在 Table 中存储为 varchar
Update XML Stored as varchar in a Table
我有一个名为 table 的方案,其中 XML
结构化文件存储为 VARCHAR
在 column.The XML 文件中,如下所示,
<Process>
<Timers>
<Timer Name="SendNotificationStaffLevel1" Type="Interval" Value="25m"
NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel1" Type="Interval" Value="600m"
NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel1" Type="Interval"
Value="605m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationStaffLevel2" Type="Interval" Value="5m"
NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel2" Type="Interval" Value="10m"
NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel2" Type="Interval"
Value="12m" NotOverrideIfExists="true" />
<Timer Name="DeactivateUrlOfFileResubmission" Type="Interval" Value="15m"
NotOverrideIfExists="true" />
</Timers>
</process>
我需要通过提供名称属性即更新每个计时器的值。 "SendNotificationStaffLevel1" 作为存储过程的参数。
我试过了
update YourTable set
XMLText.modify('replace value of (/Process/Timers/Timer/@Value)[1] with "40m"')
where XMLText.value('(/Process/Timers/Timer/@Value)[1]', 'varchar') = 25m
但是我需要指定 name 属性来更新 value.How 可以吗?提前致谢。
您可以将属性的过滤器值添加到 谓词 到 Xpath
中,如下所示:
DECLARE @xml XML=
'<Process>
<Timers>
<Timer Name="SendNotificationStaffLevel1" Type="Interval" Value="25m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel1" Type="Interval" Value="600m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel1" Type="Interval" Value="605m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationStaffLevel2" Type="Interval" Value="5m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel2" Type="Interval" Value="10m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel2" Type="Interval" Value="12m" NotOverrideIfExists="true" />
<Timer Name="DeactivateUrlOfFileResubmission" Type="Interval" Value="15m" NotOverrideIfExists="true" />
</Timers>
</Process>';
DECLARE @Name VARCHAR(100)='SendNotificationStaffLevel1';
SET @xml.modify('replace value of (/Process/Timers/Timer[@Name=sql:variable("@Name")]/@Value)[1] with "40m"');
SELECT @xml;
您可以将 Xpath
解读为:
- 开始于
<Process>
- 深入
<Timers>
,然后 <Timer>
- 找到第一个(
[1]
)个属性名称与外部变量相似的地方
- 更改属性
@Value
有table数据
您可以轻松调整以上内容以针对 table 的列工作,但是:
如果 XML 被保存为 VARCHAR(x)
你必须把它弄出来。 .modify()
需要本机 XML 类型,您无法更新强制转换的列。我建议写一个中间 table,在那里更新并写回:
一个模型table:
DECLARE @mockup TABLE(ID INT IDENTITY, YourXmlAsString VARCHAR(MAX));
INSERT INTO @mockup VALUES
('<Process>
<Timers>
<Timer Name="SendNotificationStaffLevel1" Type="Interval" Value="25m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel1" Type="Interval" Value="600m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel1" Type="Interval" Value="605m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationStaffLevel2" Type="Interval" Value="5m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel2" Type="Interval" Value="10m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel2" Type="Interval" Value="12m" NotOverrideIfExists="true" />
<Timer Name="DeactivateUrlOfFileResubmission" Type="Interval" Value="15m" NotOverrideIfExists="true" />
</Timers>
</Process>');
--将转换的列写到临时table
SELECT ID
,YourXmlAsString --<-- You don't need this actually
,CAST(YourXmlAsString AS XML) YourXmlAsXml
INTO #tmpTable
FROM @mockup ;
--执行更新
DECLARE @Name VARCHAR(100)='SendNotificationStaffLevel1';
UPDATE #tmpTable
SET YourXmlAsXml .modify('replace value of (/Process/Timers/Timer[@Name=sql:variable("@Name")]/@Value)[1] with "40m"');
--更新原来的table
UPDATE t
SET YourXmlAsString=CAST(tmp.YourXmlAsXml AS VARCHAR(MAX))
FROM #tmpTable tmp
INNER JOIN @mockup t ON tmp.ID=t.ID;
--检查结果
SELECT * FROM @mockup;
提示:
如果有任何机会将列的类型更改为 XML,您确实应该这样做...
我找到的例子有点不同
UPDATE HR_XML
SET Salaries.modify('replace value of
(/Salaries/Marketing/Employee[@ID=("2")]/Salary/text())[1] with ("60000")')
GO
对于你的情况,我猜是
update YourTable set
XMLText.modify('replace value of
(/Process/Timers/Timer[@Name=("SendNotificationSecretaryLevel2")]/@Value)[1] with "40m"')
GO
不过我不确定你更新的位置。
我有一个名为 table 的方案,其中 XML
结构化文件存储为 VARCHAR
在 column.The XML 文件中,如下所示,
<Process>
<Timers>
<Timer Name="SendNotificationStaffLevel1" Type="Interval" Value="25m"
NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel1" Type="Interval" Value="600m"
NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel1" Type="Interval"
Value="605m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationStaffLevel2" Type="Interval" Value="5m"
NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel2" Type="Interval" Value="10m"
NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel2" Type="Interval"
Value="12m" NotOverrideIfExists="true" />
<Timer Name="DeactivateUrlOfFileResubmission" Type="Interval" Value="15m"
NotOverrideIfExists="true" />
</Timers>
</process>
我需要通过提供名称属性即更新每个计时器的值。 "SendNotificationStaffLevel1" 作为存储过程的参数。
我试过了
update YourTable set
XMLText.modify('replace value of (/Process/Timers/Timer/@Value)[1] with "40m"')
where XMLText.value('(/Process/Timers/Timer/@Value)[1]', 'varchar') = 25m
但是我需要指定 name 属性来更新 value.How 可以吗?提前致谢。
您可以将属性的过滤器值添加到 谓词 到 Xpath
中,如下所示:
DECLARE @xml XML=
'<Process>
<Timers>
<Timer Name="SendNotificationStaffLevel1" Type="Interval" Value="25m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel1" Type="Interval" Value="600m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel1" Type="Interval" Value="605m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationStaffLevel2" Type="Interval" Value="5m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel2" Type="Interval" Value="10m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel2" Type="Interval" Value="12m" NotOverrideIfExists="true" />
<Timer Name="DeactivateUrlOfFileResubmission" Type="Interval" Value="15m" NotOverrideIfExists="true" />
</Timers>
</Process>';
DECLARE @Name VARCHAR(100)='SendNotificationStaffLevel1';
SET @xml.modify('replace value of (/Process/Timers/Timer[@Name=sql:variable("@Name")]/@Value)[1] with "40m"');
SELECT @xml;
您可以将 Xpath
解读为:
- 开始于
<Process>
- 深入
<Timers>
,然后<Timer>
- 找到第一个(
[1]
)个属性名称与外部变量相似的地方 - 更改属性
@Value
有table数据
您可以轻松调整以上内容以针对 table 的列工作,但是:
如果 XML 被保存为 VARCHAR(x)
你必须把它弄出来。 .modify()
需要本机 XML 类型,您无法更新强制转换的列。我建议写一个中间 table,在那里更新并写回:
一个模型table:
DECLARE @mockup TABLE(ID INT IDENTITY, YourXmlAsString VARCHAR(MAX));
INSERT INTO @mockup VALUES
('<Process>
<Timers>
<Timer Name="SendNotificationStaffLevel1" Type="Interval" Value="25m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel1" Type="Interval" Value="600m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel1" Type="Interval" Value="605m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationStaffLevel2" Type="Interval" Value="5m" NotOverrideIfExists="true" />
<Timer Name="SendNotificationSecretaryLevel2" Type="Interval" Value="10m" NotOverrideIfExists="true" />
<Timer Name="ReAssigningRequestToSecretaryLevel2" Type="Interval" Value="12m" NotOverrideIfExists="true" />
<Timer Name="DeactivateUrlOfFileResubmission" Type="Interval" Value="15m" NotOverrideIfExists="true" />
</Timers>
</Process>');
--将转换的列写到临时table
SELECT ID
,YourXmlAsString --<-- You don't need this actually
,CAST(YourXmlAsString AS XML) YourXmlAsXml
INTO #tmpTable
FROM @mockup ;
--执行更新
DECLARE @Name VARCHAR(100)='SendNotificationStaffLevel1';
UPDATE #tmpTable
SET YourXmlAsXml .modify('replace value of (/Process/Timers/Timer[@Name=sql:variable("@Name")]/@Value)[1] with "40m"');
--更新原来的table
UPDATE t
SET YourXmlAsString=CAST(tmp.YourXmlAsXml AS VARCHAR(MAX))
FROM #tmpTable tmp
INNER JOIN @mockup t ON tmp.ID=t.ID;
--检查结果
SELECT * FROM @mockup;
提示:
如果有任何机会将列的类型更改为 XML,您确实应该这样做...
我找到的例子有点不同
UPDATE HR_XML
SET Salaries.modify('replace value of
(/Salaries/Marketing/Employee[@ID=("2")]/Salary/text())[1] with ("60000")')
GO
对于你的情况,我猜是
update YourTable set
XMLText.modify('replace value of
(/Process/Timers/Timer[@Name=("SendNotificationSecretaryLevel2")]/@Value)[1] with "40m"')
GO
不过我不确定你更新的位置。