バックグラウンド
最近、私は SQL Server 2005 の列として XML をより多く使用するようになりました。いくつかの結合をサポートする構造コードをさらに記述します。
SCOPE_IDENTITY()
これら 2 つのリンク テーブルのデータを実際に生成するために、2 つの XML フィールドをストアド プロシージャに渡します。ストアド プロシージャは、メイン レコードを書き込み、2 つの XML 変数を @tables に分解し、マスターからの新しい変数とともに実際のテーブルに挿入します。記録。
しばらくして、これらのテーブルを完全に廃止し、XML を XML フィールドに格納することにしました。ここで、一般的なクエリのパフォーマンスGROUP BY
が XML データでは機能しないなど、いくつかの落とし穴があることを理解しました。クエリは一般的に少しごちゃごちゃしていますが、全体的にはXElement
、データが戻ってきたときに作業できるようになったことが気に入っています。
また、この内容は変更されません。ワンショットなので改造の心配はありません。
このデータを実際に取得するための最良の方法について疑問に思っています。私のクエリの多くは、子レコードまたはサブ子レコードの条件に基づいてマスター レコードを取得することを伴います。データベース内のほとんどの sproc はこれを行いますが、はるかに精巧な規模であり、通常は UDF とサブクエリが効果的に機能する必要がありますが、いくつかのデータのクエリをテストするために簡単な例を作成しました...
INSERT INTO Customers VALUES ('Tom', '', '<PhoneNumbers><PhoneNumber Type="1" Value="01234 456789" /><PhoneNumber Type="2" Value="01746 482954" /></PhoneNumbers>')
INSERT INTO Customers VALUES ('Andy', '', '<PhoneNumbers><PhoneNumber Type="2" Value="07948 598348" /></PhoneNumbers>')
INSERT INTO Customers VALUES ('Mike', '', '<PhoneNumbers><PhoneNumber Type="3" Value="02875 482945" /></PhoneNumbers>')
INSERT INTO Customers VALUES ('Steve', '', '<PhoneNumbers></PhoneNumbers>')
今、私はそれをつかむ2つの方法を見ることができます.
方法 1
DECLARE @PhoneType INT
SET @PhoneType = 2
SELECT ct.*
FROM Customers ct
WHERE ct.PhoneNumbers.exist('/PhoneNumbers/PhoneNumber[@Type=sql:variable("@PhoneType")]') = 1
本当に?sql:variable は少し不健全に感じます。ただし、機能します。ただし、より意味のある方法でデータにアクセスすることは明らかに困難です。
方法 2
SELECT ct.*, pt.PhoneType
FROM Customers ct
CROSS APPLY ct.PhoneNumbers.nodes('/PhoneNumbers/PhoneNumber') AS nums(pn)
INNER JOIN PhoneTypes pt ON pt.ID = nums.pn.value('./@Type[1]', 'int')
WHERE nums.pn.value('./@Type[1]', 'int') = @PhoneType
これはもっと似ています。すでに簡単に拡張して、結合やその他すべての優れた機能を実行できます。CROSS APPLY
以前にテーブル値関数で使用したことがありますが、非常に優れていました。前のクエリとは対照的に、この実行計画は非常に高度です。確かに、私はこれらのテーブルに対してインデックス作成などを行っていませんが、バッチ コスト全体の 97% を占めています。
方法 2 (拡張)
SELECT ct.ID, ct.CustomerName, ct.Notes, pt.PhoneType
FROM Customers ct
CROSS APPLY ct.PhoneNumbers.nodes('/PhoneNumbers/PhoneNumber') AS nums(pn)
INNER JOIN PhoneTypes pt ON pt.ID = nums.pn.value('./@Type[1]', 'int')
WHERE nums.pn.value('./@Type[1]', 'int') IN (SELECT ID FROM PhoneTypes)
ここにいいIN
節があります。次のようなこともできますpt.PhoneType = 'Work'
ついに
したがって、基本的には必要な結果を取得していますが、このメカニズムを使用して少量の XML データを調査する場合に注意すべきことはありますか? 精巧な検索中にパフォーマンスが低下しますか? また、そのようなマークアップ スタイル データの保存はオーバーヘッドが大きすぎますか?
サイドノート
私は過去にリストをsprocに渡すためだけにsp_xml_preparedocument
やOPENXML
のようなものを使用しましたが、これは比較して新鮮な空気のようなものです!