web-dev-qa-db-ja.com

XML query()は機能し、value()はxdt:untypedAtomicが見つかったシングルトンを必要とします

型指定されたxmlドキュメントがテキストとして保存されています。したがって、XMLメソッドを使用できるようにするために、共通テーブル式を使用してCONVERTデータ型をxmlに使用します。

WITH xoutput AS (
  SELECT CONVERT(xml, t.requestpayload) 'requestpayload'
    FROM TABLE t
   WHERE t.methodid = 1)
SELECT x.requestpayload.query('declare namespace s="http://blah.ca/api";/s:validate-student-request/s:student-id') as studentid
  FROM xoutput x

クエリが機能し、要素が返されます。しかし、私は値にのみ興味があります:

WITH xoutput AS (
  SELECT CONVERT(xml, t.requestpayload) 'requestpayload'
    FROM TABLE t
   WHERE t.methodid = 1)
SELECT x.requestpayload.value('declare namespace s="http://blah.ca/api";/s:validate-student-request/s:student-id', 'int') as studentid
  FROM xoutput x

これにより、次のエラーが発生します。

'value()'にはシングルトン(または空のシーケンス)が必要です、タイプ 'xdt:untypedAtomic *'のオペランドが見つかりました

私がグーグルで言ったことは、XPATH/XQUERYが括弧内にある必要がある、または "[1]"が必要である-どちらも機能していないということです。スキーマにはそれ以上を許可していると思いますが、xmlには1つのStudent-ID要素しかありません。

さらに、取得したい要素の値が多数あります。名前空間をメソッド呼び出しごとではなく1回宣言する方法はありますか?

32
OMG Ponies

これを使用する必要があります:

SELECT 
        x.requestpayload.value('declare namespace s="http://blah.ca/api";
            (/s:validate-student-request/s:student-id)[1]', 'int') 
    AS
        studentid
    FROM 
        xoutput x

XPathを( ... )に配置し、[1]を追加して、そのシーケンスの最初の値を選択する必要があります。

66
marc_s

私もこれがそうするかもしれないと信じています:

SELECT 
   x.requestpayload.query('declare namespace s="http://blah.ca/api";
                           /s:validate-student-request/s:student-id').value('.', 'int') 
  as studentid
FROM xoutput x
8
Ken

パフォーマンスに関心のある人のために、これらのアプローチを比較するクエリを実行し、最初のオプションを "()で追加して[1]"を追加したところ、 "。query( 'strFranchise')。value( '。'、... )」.

同じデータで次々と実行すると、実行計画の違いは15%から85%でした。したがって、()[1]は5倍以上速くなります!実行計画は大きく異なります。

3
David Coster