XML型としてテーブルを作る
特に難しいことはなく、XMLと指定すればいいだけ。
create table CATALOG (
CATALOG_ID BIGINT not null
, CATALOG_NAME VARCHAR (128)
, DOCUMENT XML
, UPDATE_DATE DATE
, primary key (CATALOG_ID)
);
XMLデータ全体を挿入・更新(insertとupdate)
手っ取り早いのは、XMLを文字列として書き込めばいい。
insert
into CATALOG
values (
1
, 'catalog_name'
, '<customerinfo cid="1000">
<name>Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
<phone type="work">416-555-1358</phone>
</customerinfo>'
, current timestamp
)
UPDATEも同様に文字列として更新させる。
update CATALOG
set
DOCUMENT = '<customerinfo cid="1000">
<name>Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
<phone type="work">416-555-1358</phone>
</customerinfo>'
where
CATALOG_ID = 1
プログラムから挿入する場合は、XML型で入るようなAPIが準備されていると思いますので、わざわざ文字列にしなくてもいいかもしれません。
さて、以下のようなデータを挿入しました。次からはxmlquery関数を使って、XMLの一部を修正したいと思います。
<?xml version="1.0" encoding="UTF-8"?>
<customerinfo cid="1000">
<name>Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
<phone type="work">416-555-1358</phone>
</customerinfo>
XMLの要素の修正(xmlquery)
XMLの一部のデータを修正する場合は、xmlquery関数を使用し、FLOWERと呼ばれる形式で記述します。
どちらかというとプログラミング言語っぽく、習うより慣れろみたいな書き方なので、深く考えずに書いていくのがいいと思います。
要素、属性値の更新「do replace」
XMLデータの3か所を修正しています。それぞれ「要素の中身を更新」「属性値の更新」「要素自体の置き換え」とやっています。
update CATALOG
set
DOCUMENT = xmlquery(
'copy $new := $DOCUMENT
modify (
do replace value of $new/customerinfo/name with $name,
do replace value of $new/customerinfo/addr/@country with $country,
do replace $new/customerinfo/addr/pcode-zip with $zip
)
return $new'
passing
cast('Mike Tyson' as varchar(10)) as "name",
cast('America' as varchar(10)) as "country",
xmlparse(document '<pcode-zip2>123-456</pcode-zip2>') as "zip"
)
, UPDATE_DATE = current date
where
CATALOG_ID = 1
結果は以下
<?xml version="1.0" encoding="UTF-8"?>
<customerinfo cid="1000">
<name>Mike Tyson</name>
<addr country="America">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip2>123-456</pcode-zip2>
</addr>
<phone type="work">416-555-1358</phone>
</customerinfo>
要素、属性の挿入「do insert」
「要素を末尾に追加」「要素を先頭に追加」「指定した位置に追加」「属性の追加」となっております。
update CATALOG
set
DOCUMENT = xmlquery(
'copy $new := $DOCUMENT
modify (
do insert $gmail into $new/customerinfo,
do insert $nickname as first into $new/customerinfo,
do insert $phone after $new/customerinfo/phone[1],
do insert attribute userId {$userId} into $new/customerinfo/name
)
return $new'
passing
xmlparse(document '<mail type="gmail">hoge@gmail.co.jp</mail>') as "gmail",
xmlparse(document '<nickname>Tyson</nickname>') as "nickname",
xmlparse(document '<phone>1235689</phone>') as "phone",
cast('123' as varchar(10)) as "userId"
)
, UPDATE_DATE = current date
where
CATALOG_ID = 1
<?xml version="1.0" encoding="UTF-8"?>
<customerinfo cid="1000">
<nickname>Tyson</nickname>
<name userId="123">Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
<phone type="work">416-555-1358</phone>
<phone>1235689</phone>
<mail type="gmail">hoge@gmail.co.jp</mail>
</customerinfo>
要素が存在していれば更新、なければ挿入
「要素の更新、なければ挿入」です。属性に対しても存在チェックで挿入・更新可能。
update CATALOG
set
DOCUMENT = xmlquery(
'copy $new := $DOCUMENT
modify (
if($new/customerinfo/phone) then
do replace value of $new/customerinfo/phone with $phone
else
do insert <phone>{fn:data($phone)}</phone> into $new/customerinfo,
if($new/customerinfo/phone/@type) then
do replace value of $new/customerinfo/phone/@type with $type
else
do insert attribute type {$type} into $new/customerinfo/phone
)
return $new'
passing
cast('000-0000-0000' as varchar(20)) as "phone",
cast('private' as varchar(20)) as "type"
)
, UPDATE_DATE = current date
where
CATALOG_ID = 1
<?xml version="1.0" encoding="UTF-8"?>
<customerinfo cid="1000">
<name>Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
<phone type="private">000-0000-0000</phone>
</customerinfo>
要素、属性の削除「do delete」
update
CATALOG
set
DOCUMENT = xmlquery('copy $new := $DOCUMENT
modify (
do delete $new/customerinfo/phone,
do delete $new/customerinfo/@cid
)
return $new '),
UPDATE_DATE = current date
where
CATALOG_ID = 1
<?xml version="1.0" encoding="UTF-8"?>
<customerinfo>
<name>Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
</customerinfo>