外部キーによってリンクされた別のテーブルからの xml フラグメントを使用して、テーブル内の XML 列を更新 (具体的には .modify('insert into..')) する方法を探しています。
たとえば、私のテーブル構造は以下のようになります (簡略化):
- 各テーブルのフィールド 1 ~ 5 は無視できます。それらの唯一の目的は、フィールド Xx を説明することです。
- 各テーブルのフィールド Xx は XML として定義されており、タグのテーブル名内にテーブルのフィールドを含む XML フラグメントが事前に入力されています。XML フラグメントは、このリストの後に示されています。
- テーブル B とテーブル C には、テーブル A にリンクする外部キー FK_A があります。
ここで、達成する必要があることの前に、Xx フィールドのサンプル値に進みます。
<!-- Table A record 1 -->
<TableA PK_A="1">
<A1>Avalue</A1>
<A2>Avalue</A2>
<A3>Avalue</A3>
<A4>Avalue</A4>
<A5>Avalue</A5>
</TableA>
<!-- Table B record 1 -->
<TableB PK_B="1" FK_A="1">
<B1>Bvalue1</B1>
<B2>Bvalue1</B2>
<B3>Bvalue1</B3>
<B4>Bvalue1</B4>
<B5>Bvalue1</B5>
</TableB>
<!-- Table B record 2 -->
<TableB PK_B="2" FK_A="1">
<B1>Bvalue2</B1>
<B2>Bvalue2</B2>
<B3>Bvalue2</B3>
<B4>Bvalue2</B4>
<B5>Bvalue2</B5>
</TableB>
<!-- Table C record 1 -->
<TableC PK_C="1" FK_A="1">
<C1>Cvalue1</C1>
<C2>Cvalue1</C2>
<C3>Cvalue1</C3>
<C4>Cvalue1</C4>
<C5>Cvalue1</C5>
</TableC>
<!-- Table C record 2 -->
<TableC PK_C="2" FK_A="1">
<C1>Cvalue2</C1>
<C2>Cvalue2</C2>
<C3>Cvalue2</C3>
<C4>Cvalue2</C4>
<C5>Cvalue2</C5>
</TableC>
ここでの問題は、すべての XB と XC を最初 (または最後) として対応する XA に挿入して、テーブル A を更新するにはどうすればよいかということです。テーブル全体を更新する単一の操作を好みます。
操作後、XA は次のようになります。
<!-- Table A record 1 -->
<TableA PK_A="1">
<!-- Table B record 1 -->
<TableB PK_B="1" FK_A="1">
<B1>Bvalue1</B1>
<B2>Bvalue1</B2>
<B3>Bvalue1</B3>
<B4>Bvalue1</B4>
<B5>Bvalue1</B5>
</TableB>
<!-- Table B record 2 -->
<TableB PK_B="2" FK_A="1">
<B1>Bvalue2</B1>
<B2>Bvalue2</B2>
<B3>Bvalue2</B3>
<B4>Bvalue2</B4>
<B5>Bvalue2</B5>
</TableB>
<!-- Table C record 1 -->
<TableC PK_C="1" FK_A="1">
<C1>Cvalue1</C1>
<C2>Cvalue1</C2>
<C3>Cvalue1</C3>
<C4>Cvalue1</C4>
<C5>Cvalue1</C5>
</TableC>
<!-- Table C record 2 -->
<TableC PK_C="2" FK_A="1">
<C1>Cvalue2</C1>
<C2>Cvalue2</C2>
<C3>Cvalue2</C3>
<C4>Cvalue2</C4>
<C5>Cvalue2</C5>
</TableC>
<A1>Avalue</A1>
<A2>Avalue</A2>
<A3>Avalue</A3>
<A4>Avalue</A4>
<A5>Avalue</A5>
</TableA>
これまでに何を試しましたか?
これまでのところ、私の最善のリードは、分割とルールのアプローチ (2 つの部分からなるソリューションであり、うまくいきません) でした。
WITH CTEB (PK_A, XA, XB)
AS (SELECT A.PK_A,
a.XA,
b.XB
FROM TableA AS a
INNER JOIN
TableB AS b
ON b.FK_A = a.PK_A)
UPDATE CTEB
SET XA.modify('insert sql:column("XB") as last into (/TableA)[1]');
WITH CTEC (PK_A, XA, XC)
AS (SELECT A.PK_A,
a.XA,
c.XC
FROM TableA AS a
INNER JOIN
TableC AS c
ON c.FK_A = a.PK_A)
UPDATE CTEC
SET XA.modify('insert sql:column("XC") as last into (/TableA)[1]');
編集:
コピーペーストするテキスト値を指定していないことをお詫びします。どうぞ。
DECLARE @A TABLE (PK_A INT, XA XML);
DECLARE @B TABLE (PK_B INT, XB XML, FK_A INT);
DECLARE @C TABLE (PK_C INT, XC XML, FK_A INT);
INSERT INTO @A
VALUES (1, '<TableA PK_A="1"><A1>Avalue</A1><A2>Avalue</A2><A3>Avalue</A3><A4>Avalue</A4><A5>Avalue</A5></TableA>')
INSERT INTO @A
VALUES (2, '<TableA PK_A="2"><A1>Avalue</A1><A2>Avalue</A2><A3>Avalue</A3><A4>Avalue</A4><A5>Avalue</A5></TableA>')
INSERT INTO @B
VALUES (1,'<TableB PK_B="1" FK_A="1"><B1>Bvalue1</B1><B2>Bvalue1</B2><B3>Bvalue1</B3><B4>Bvalue1</B4><B5>Bvalue1</B5></TableB>', 1)
INSERT INTO @B
VALUES (2, '<TableB PK_B="2" FK_A="1"><B1>Bvalue2</B1><B2>Bvalue2</B2><B3>Bvalue2</B3><B4>Bvalue2</B4><B5>Bvalue2</B5></TableB>', 1)
INSERT INTO @B
VALUES (3, '<TableB PK_B="3" FK_A="2"><B1>Bvalue3</B1><B2>Bvalue3</B2><B3>Bvalue3</B3><B4>Bvalue3</B4><B5>Bvalue3</B5></TableB>', 2)
INSERT INTO @B
VALUES (4, '<TableB PK_B="4" FK_A="2"><B1>Bvalue4</B1><B2>Bvalue4</B2><B3>Bvalue4</B3><B4>Bvalue4</B4><B5>Bvalue4</B5></TableB>', 2)
INSERT INTO @C
VALUES (1, '<TableC PK_C="1" FK_A="1"><C1>Cvalue1</C1><C2>Cvalue1</C2><C3>Cvalue1</C3><C4>Cvalue1</C4><C5>Cvalue1</C5></TableC>', 1)
INSERT INTO @C
VALUES (2, '<TableC PK_C="2" FK_A="1"><C1>Cvalue2</C1><C2>Cvalue2</C2><C3>Cvalue2</C3><C4>Cvalue2</C4><C5>Cvalue2</C5></TableC>', 1)
INSERT INTO @C
VALUES (3, '<TableC PK_C="3" FK_A="2"><C1>Cvalue3</C1><C2>Cvalue3</C2><C3>Cvalue3</C3><C4>Cvalue3</C4><C5>Cvalue3</C5></TableC>', 2)
INSERT INTO @C
VALUES (4, '<TableC PK_C="4" FK_A="2"><C1>Cvalue4</C1><C2>Cvalue4</C2><C3>Cvalue4</C3><C4>Cvalue4</C4><C5>Cvalue4</C5></TableC>', 2);
WITH CTEB (PK_A, XA, XB)
AS (SELECT A.PK_A,
a.XA,
b.XB
FROM @A AS a, @B as b
WHERE b.FK_A = a.PK_A)
UPDATE CTEB
SET XA.modify('insert sql:column("XB") as first into (/TableA)[1]');
WITH CTEC (PK_A, XA, XC)
AS (SELECT A.PK_A,
a.XA,
c.XC
FROM @A AS a
INNER JOIN
@C AS c
ON c.FK_A = a.PK_A)
UPDATE CTEC
SET XA.modify('insert sql:column("XC") as first into (/TableA)[1]');
SELECT * FROM @A;
これにより、テーブル B とテーブル C の最初の XML フラグメントのみを使用して XML が更新されます。
更新: この質問に出くわす可能性のある人は、@Shnugo の回答とマークされた回答をご覧ください。どちらのアプローチも完璧です。彼が最初に返信したという理由だけで、@ gofr1 の解決策を回答としてマークしました。将来のクエスト ハンターのもう 1 つの考慮事項は、CTE が好きかサブセレクトが好きかということです (Shnugo が指摘したように)。