XML query()有效,value()需要找到单独的xdt:untypedAtomic

时间:2009-08-19 19:15:53

标签: sql sql-server sql-server-2005 tsql xquery

我有一个存储为文本的类型化xml文档。所以我使用公用表表达式将数据类型CONVERT转换为xml,以便能够使用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 *'的操作数

我用google搜索说XPATH / XQUERY需要在括号内和/或需要“[1]” - 两者都没有用。 xml中只有一个student-id元素,但我想架构允许更多?

此外,我想要检索许多元素值 - 是否有一种方法可以声明命名空间一次而不是每次方法调用?

3 个答案:

答案 0 :(得分:66)

你需要使用它:

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],以便只选择该序列的第一个值。

答案 1 :(得分:8)

我相信这也可能会这样做:

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

答案 2 :(得分:3)

对于那些对性能感兴趣的人,我运行了一个查询来比较这些方法和第一个选项"()并添加[1]"比#34; .query(' strFranchise')。('。',...)"。

快得多。

在相同数据上一个接一个地运行时,执行计划的差异为15%到85%。所以()[1]快5倍!执行计划有很大不同。