SQL ServerでXQueryするには?(準備編3)
前回のおさらい
SQL Serverを使用して、「XQuery用のXML」を取得することに成功。しかし「NULLの項目が出力されない」問題が。試行錯誤の末に「NULLを出力するオプション」をついに発見。「テーブル」→「XML」を実現した。今回は「XML」→「テーブル」に挑戦する。
TAXCODE | TAXNAME | TAXRATE | MODIFIED |
0 | 非課税 | 0 | 2000/01/01 0:00:00 |
1 | 課税 | 5 | 2001/01/01 0:00:00 |
8 | 旧消費税 | 3 | 2008/01/01 0:00:00 |
9 | その他 | NULL | 2009/01/01 0:00:00 |
1 |
SELECT |
1 |
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
INSERT
一番最初の「XML」→「テーブル」の例として、まずは「INSERT」からやってみます。
1 |
/* XML文書のハンドル */ |
実行。F5!
TAXCODE | TAXNAME | TAXRATE | MODIFIED |
0 | 非課税 | 0 | 2000/01/01 0:00:00 |
1 | 課税 | 5 | 2001/01/01 0:00:00 |
13 | じゅうさん | 13 | 2013/01/01 0:00:00 |
14 | じゅうよん | 14 | 2014/01/01 0:00:00 |
8 | 旧消費税 | 3 | 2008/01/01 0:00:00 |
9 | その他 | NULL | 2009/01/01 0:00:00 |
OKです。TAXCODEは文字型なので、「13」と「14」は真ん中にきています。
それでは、この処理を実際に担当している処理を見ていきます。
XML三人衆
XMLでテーブルに更新を掛けるには、合計三つの機能が必要です。これを仮に「XML三人衆」と名づけます。
この三人衆のコンビネーションを順番に見ていきます。
sp_xml_preparedocument
深い内容は、上のリンクから「MSDN」を直接ご参照いただくとして、簡単な内容を掻い摘んで説明すると、このコラムでは1~30行目の処理になります。このストアドプロシージャが行っていることは、第2引数「xmltext」から受け取ったXML文書をメモリ上に展開し、第1引数「hdoc」にXML文書のハンドルを取得します。
ハンドルとは、例えば、「車のハンドル」を思い浮かべていただければOKです。「車のハンドル」を握れば、「車」をコントロールできます。同様に、「XML文書のハンドル」を握れば、「XML文書」をコントロールできます。その為に、この「sp_xml_preparedocument」というストアドプロシージャが必要なのです。
実は、「sp_xml_preparedocument」の処理には、少しコツが必要です。それは、第2引数である「xmltext」についてです。ここには、「char、nchar、varchar、nvarchar、text、ntext、または xml 型」が入ります。しかし、日本語を正しく処理できるのは、「nchar、nvarchar、ntext、xml型」でした(SQL Serverのある設定をいじれば、対応可能なのかもしれませんが……)。
日本語を正しく処理できる「nchar、nvarchar、ntext、xml型」の中で、私のオススメは「nvarchar型」です。理由としては、「nvarchar型」が一時的な利用にちょうど良いサイズだからです。本来ここはXMLの処理なので、「xml型」でいくべきだと考えたのですが、「xml型」は直接手書きできないという制限がありました。「xml型」を作成するには、テーブルに対して「FOR XML」をつけてSELECTするか、一度「nvarchar型」などでXMLを記述してから、「xml型」にキャストする必要がありました。
そもそも「sp_xml_preparedocument」の第2引数には、「nvarchar型」でOKなのですから、わざわざ「xml型」にこだわる必要はなかったのです。ここは是非、「nvarchar型」を使用してください。
OPENXML
XMLを動的なビューとして表現します。42~43行目が特に重要な部分です。第1引数は、先ほど取得したXML文書のハンドル「@hdoc」を設定します。第2引数は、実データへのXPATHを記述します。「N'/export/data'」を設定します。頭の「N」は日本語の混じったXPATH対応用です。今回は必要ありませんが、念のため入れています。第3引数は、XMLの文書タイプです。今回の文書タイプは、「要素」なので「2」を設定します。
最後に、「WITH」に続けてスキーマを記述します。SQL Serverには暗黙変換の機能がありますが、対応するフィールドと同じ型に揃えておきます。
TAXCODE VARCHAR(50) | → | val1 VARCHAR(50) |
TAXNAME VARCHAR(50) | → | val2 VARCHAR(50) |
TAXRATE INT | → | val3 INT |
MODIFIED DATETIME | → | val4 DATETIME |
sp_xml_removedocument
メモリ上に展開されているXML文書を解放します。第1引数に「sp_xml_preparedocument」で取得しておいたXML文書のハンドル「@hdoc」を指定します。これを忘れると、SQL Serverがメモリ不足になることがあるそうです。49行目にこの処理を行っています。
以上で、コンビネーションの説明は終わりです。お疲れ様でした。
さてさて、XMLで「INSERT」ができるならば、「UPDATE」も可能なのでしょうか? その答えは「Yes」です。
UPDATE
INSERTの場合と、やっていることは同じです。例として「TAXNAME」を漢字にしてみます。
1 |
/* XML文書のハンドル */ |
実行。F5!
TAXCODE | TAXNAME | TAXRATE | MODIFIED |
0 | 非課税 | 0 | 2000/01/01 0:00:00 |
1 | 課税 | 5 | 2001/01/01 0:00:00 |
13 | 十三 | 13 | 2013/01/01 0:00:00 |
14 | 十四 | 14 | 2014/01/01 0:00:00 |
8 | 旧消費税 | 3 | 2008/01/01 0:00:00 |
9 | その他 | NULL | 2009/01/01 0:00:00 |
できました。
主キーの「TAXCODE」と、更新対象の「TAXNAME」の分だけXMLを用意すればOKです。
DELETE
最後に「DELETE」です。「INSERT」した「13」と「14」のレコードを削除します。
1 |
/* XML文書のハンドル */ |
実行。F5!
TAXCODE | TAXNAME | TAXRATE | MODIFIED |
0 | 非課税 | 0 | 2000/01/01 0:00:00 |
1 | 課税 | 5 | 2001/01/01 0:00:00 |
8 | 旧消費税 | 3 | 2008/01/01 0:00:00 |
9 | その他 | NULL | 2009/01/01 0:00:00 |
テーブルが最初の状態に戻りましたね。
ありがとうございました
さて、これで「XML」→「テーブル」を一通り行ったことになります。「XML三人衆」さえ使いこなせれば、普通のT-SQLの処理なんだなーと感じました。
今回の「SQL ServerでXQueryするには?(準備編3)」をもって、準備編は終了です。そして、XQueryの次のテーマは、「FLWOR式」です。しかし、.NET技術者としては、「Linq To SQL」や「Linq To XML」という技術もあります。正直悩ましいところです。
とりあえず、次回からは「XQuery」とは別の話題でいきたいと思っています。