0

我有一个带有两个 XML 列和以下结构的 SQL Server 2008 表:

JOB_ID int,
RECORD_NO int,
SOURCE_DATA xml,
TARGET_DATA xml

一些样本数据:

JOB_ID RECORD_NO SOURCE_DATA                                   TARGET_DATA
------ --------- --------------------------------------------  ----------------
     1         1 <data><field id="C_ID">1684</field>...</data> <data/>
     1         2 <data><field id="C_ID">9817</field>...</data> <data/>
     1         3 <data><field id="C_ID">6508</field>...</data> <data/>

SOURCE_DATA 中的根 <data> 节点保证有一组已知的子 <field> 节点,每个子节点由“id”属性唯一标识。例如,典型的行可能包含如下所示的 SOURCE_DATA 列:

<data>
  <field id="C_ID">1684</field>
  <field id="C_FNAME">John</field>
  <field id="C_LNAME">Doe</field>
  <field id="C_ADDR1">123 Elm Street</field>
  <field id="C_ADDR2"/>
  <field id="C_CITY">Greenville</field>
  <field id="C_STATE">NC</field>
</data>

我需要将 SOURCE_DATA 中的 <field> 节点复制为 TARGET_DATA 列的 <data> 列的子节点,但具有不同的“id”属性值。例如,上面显示的 SOURCE_DATA 值需要在 TARGET_DATA 的同一行上如下所示:

<data>
  <field id="Q1">1684</field>
  <field id="Q2">John</field>
  <field id="Q3">Doe</field>
  <field id="Q4">123 Elm Street</field>
  <field id="Q5"/>
  <field id="Q6">Greenville</field>
  <field id="Q7">NC</field>
</data>

编辑添加: SOURCE_DATA 列中的字段 ID 到 TARGET_DATA 列中的字段 ID 的外部预定义映射,因此不能假设 TARGET_DATA 中的字段 ID 具有有序的升序。例如,TARGET_DATA 列可以很容易地是这样的:

<data>
  <field id="Q43_1">1684</field>
  <field id="Q8">John</field>
  <field id="Q9">Doe</field>
  <field id="Q15_1">123 Elm Street</field>
  <field id="Q15_2"/>
  <field id="Q17_1">Greenville</field>
  <field id="Q17_A_1">NC</field>
</data>

现在可以肯定,我可以将一个行集拖到我的 C# 客户端,在本地操作 XML,然后执行一系列更新,但除了占用带宽之外,我还要处理 100,000 多行,所以这需要很长时间。

我一直在拼命想弄清楚如何在一个操作中完成这个服务器端(甚至是一系列语句,这可能是必要的,因为必须有一个字段 ID 的外部映射在传输过程中应用)使用某种形式的 update-from-select 语法,但 SQL Server XML DML 命令似乎不想处理字符串文字以外的任何内容(或者更可能我只是不知道该怎么做)。

任何有关如何将 SQL Server 2008 弯曲到我的意愿的建议,我都会非常高兴和感激地感谢!

4

1 回答 1

1

尝试这个:

declare @t table(SOURCE_DATA xml, TARGET_DATA xml)

insert @t values('<data>
  <field id="C_ID">1684</field>
  <field id="C_FNAME">John</field>
  <field id="C_LNAME">Doe</field>
  <field id="C_ADDR1">123 Elm Street</field>
  <field id="C_ADDR2"/>
  <field id="C_CITY">Greenville</field>
  <field id="C_STATE">NC</field>
</data>', null)


update @t
set TARGET_DATA = 
SOURCE_DATA.query('
<data>
{for $field in data/field
    return
        <field id="{concat("Q", xs:string(count(/data/field[. << $field]) + 1))}">
            {$field/text()}
        </field>
}       
</data>
')

select *
from @t

输出:

<data>
  <field id="Q1">1684</field>
  <field id="Q2">John</field>
  <field id="Q3">Doe</field>
  <field id="Q4">123 Elm Street</field>
  <field id="Q5" />
  <field id="Q6">Greenville</field>
  <field id="Q7">NC</field>
</data>
于 2013-10-21T23:28:19.057 回答