键/值对的SQL XQuery选择器

时间:2019-11-18 19:58:38

标签: sql xml xquery xquery-sql

我在这样的列中有一些xml。

<ScopedWorkflowConfiguration xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/workflow/2012/xaml/activities">
  <appSettings>
    <AppSetting>
      <Key>CurrentWebUri</Key>
      <Value>http://myurl.org</Value>
    </AppSetting>
    <AppSetting>
      <Key>SomethingElse</Key>
      <Value>1</Value>
    </AppSetting>
    <AppSetting>
      <Key>AnotherThing</Key>
      <Value>420</Value>
    </AppSetting>
  </appSettings>
</ScopedWorkflowConfiguration>

尝试选择“值”节点的值。

;WITH Casted AS (SELECT t.Id, t.[Configuration] As XmlData FROM dbo.MyTable AS t)
Select Distinct
     Id
    ,pv.value('//*:Key="CurrentWebUri"/Value', 'nvarchar(max)') As CurrentWebUri
From
    Casted
    Cross Apply Casted.XmlData.nodes(N'//*:ScopedWorkflowConfiguration//*:appSettings//*:AppSetting') AS A(pv)

我知道我已经接近了-但是我在这里的语法有麻烦: // :Key =“ CurrentWebUri” / Value *

上面的查询导致此错误:

  

/

需要一个节点或一组节点

你能帮忙吗?

添加结果集以供参考以进一步阐明我的追求:

+----+------------------+------------------+------------------+
| ID | CurrentWebUri    | SomethingElse    |  AnotherThing    |
+----+------------------+------------------+------------------+
|  1 | example.org      |        1         |       420        |
+----+------------------+------------------+------------------+
|  2 | example.com      |        6         |       29         |
+----+------------------+------------------+------------------+

1 个答案:

答案 0 :(得分:2)

缺少默认的名称空间声明,并且XPath表达式已关闭。并在最新说明所需输出的情况下,需要用于PIVOTing的动态SQL。

  

SQL

-- DDL and sample data population, start
USE tempdb;

DROP TABLE IF EXISTS dbo.tbl;

CREATE TABLE dbo.tbl (ID INT IDENTITY PRIMARY KEY, [Configuration] xml);

INSERT INTO dbo.tbl ([Configuration])
VALUES ('<ScopedWorkflowConfiguration xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
                             xmlns="http://schemas.microsoft.com/workflow/2012/xaml/activities">
    <appSettings>
        <AppSetting>
            <Key>CurrentWebUri</Key>
            <Value>http://myurl.org</Value>
        </AppSetting>
        <AppSetting>
            <Key>SomethingElse</Key>
            <Value>1</Value>
        </AppSetting>
        <AppSetting>
            <Key>AnotherThing</Key>
            <Value>420</Value>
        </AppSetting>
    </appSettings>
</ScopedWorkflowConfiguration>');
-- DDL and sample data population, end

DECLARE @columns AS NVARCHAR(MAX),
    @SQL AS NVARCHAR(MAX);

;WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/workflow/2012/xaml/activities')
SELECT TOP(1) @columns = STUFF([Configuration].query('for $s in /ScopedWorkflowConfiguration/appSettings/AppSetting/Key
                           return <x>{concat(",",$s)}</x>')
                   .value('.','varchar(max)'),1,1,'')
FROM dbo.tbl;

SET @SQL = 
N';WITH XMLNAMESPACES (DEFAULT ''http://schemas.microsoft.com/workflow/2012/xaml/activities''), rs AS
( 
    SELECT ID
        , c.value(''(Key/text())[1]'', ''NVARCHAR(MAX)'') AS [Key]
        , c.value(''(Value/text())[1]'', ''NVARCHAR(MAX)'') AS [Value]
    FROM dbo.tbl as tbl
        CROSS APPLY tbl.[Configuration].nodes(''/ScopedWorkflowConfiguration/appSettings/AppSetting'') AS t(c)
)
SELECT ID,' + @columns + N' FROM rs
PIVOT (
    MAX([Value])
    FOR [Key] IN (' + @columns + N')
) AS pvt;
';

EXEC sp_executesql @SQL;
  

输出

+----+------------------+---------------+--------------+
| ID |  CurrentWebUri   | SomethingElse | AnotherThing |
+----+------------------+---------------+--------------+
|  1 | http://myurl.org |             1 |          420 |
+----+------------------+---------------+--------------+