更新xml类型的列值时“修改附近的语法不正确”

时间:2018-02-05 14:42:46

标签: xml sql-server-2008 tsql xpath xquery

我在SQL Server 2008的“表”中有一个名为“Details”的XML类型列。此列的值为:

<output xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Request>
    <header>
      <message-id>300_500</message-id>
      <userid>eray</userid>
      <timestamp>2012-01-01T12:00:0.000</timestamp>
      <currentstatus>COMPLETED</currentstatus>
    </header>
    ...
  </Request>
</output>

我想要做的是使用update语句将Table的xml列(详细信息)中的timestamp值替换为Table2中的另一个时间戳值。这就是我想要的:

update t
set t.Details.modify('replace value of 
    (/output/Request/header/timestamp/text())[1] with 
    ("'+t2.MessageTimestamp+'")')
from Table t
inner join Table2 t2 on t2.apptId = t1.apptId

然而,它无效并给我错误:

  

'modify'

附近的语法不正确

我尝试通过在线阅读很多文章来修复它一段时间,但是看不出这里有什么问题。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

我认为你正在寻找

DECLARE @mockupT1 TABLE(ID INT,apptId INT,Details XML);
INSERT INTO @mockupT1 VALUES
(1,1,N'<output xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Request>
    <header>
      <message-id>300_500</message-id>
      <userid>eray</userid>
      <timestamp>2012-01-01T12:00:0.000</timestamp>
      <currentstatus>COMPLETED</currentstatus>
    </header>
    ...
  </Request>
</output>');

DECLARE @mockupT2 TABLE(apptId INT,MessageTimeStamp DATETIME);
INSERT INTO @mockupT2 VALUES(1,GETDATE());

update t1
set Details.modify('replace value of
 (/output/Request/header/timestamp/text())[1] with sql:column("t2.MessageTimeStamp")')
from @mockupT1 AS t1
inner join @mockupT2 t2 on t2.apptId = t1.apptId;

SELECT * FROM @mockupT1;

XQuery范围内,只允许使用文字。但是T-SQL已将sql:variable()sql:column()添加到XQuery。这允许使用声明的变量的值或列的值。

答案 1 :(得分:1)

问题是,当您尝试通过完整路径(如'tableAlias.XMLfield.modify')寻址到字段时,'XMLfield.modify'不起作用。导致相同的错误:'modify'附近的语法不正确。

这里有一个简短的示例来演示它(第二次更新失败,但是第一次成功)

if OBJECT_ID('tempdb..#a') is not null drop table #a
create table #a(a xml,b nvarchar(max))
insert into #a(a,b) values('<a/>','123')
update t set a.modify('insert (<b>{sql:column("b")}</b>)    as last into (//a)[1]') from #a t
select * from #a
update t set t.a.modify('insert (<b>{sql:column("b")}</b>)  as last into (//a)[1]') from #a t

答案 2 :(得分:0)

我将代码更改为下面的代码,现在工作正常。我找不到直接使用另一个表的值的方法,所以我将值保存到@timestamp变量并在替换为sql:variable("@timestamp")时使用它。

declare @timestamp varchar(50) 
set @timestamp = (
    select cast(t2.MessageTimeStamp as varchar(50))
    from Table t
    inner join Table2 t2 on t2.apptId = t1.apptId
    where t.Id = @Id
)

update t
set Details.modify('replace value of 
        (/output/Request/header/timestamp/text())[1] with 
        sql:variable("@timestamp")')
from Table t
where Id = @Id