дополнительные пары значений ключей данных XML в SQL - PullRequest
0 голосов
/ 03 октября 2019

Вот XML-код, который я пытаюсь извлечь из

<?xml version="1.0" encoding="utf-16"?>
<dictionary>
<item>
<key><string>MemberNumber</string></key>
<value><string>66962336209</string></value>
</item></dictionary>

Создать таблицу № 1 (ID int identity (1,1), дополнительные данные xml)

INSERT INTO #1
Select '<dictionary><item><key><string>MemberNumber</string></key><value><string>66962336209</string></value></item></dictionary>'


SELECT extradata.value('/*:dictionary[1]/*:Item[1]/*:Key[1]','NVARCHAR(MAX)')
FROM #1;

select
    a.c.value('*:Value[1]','nvarchar(max)') as [value]
from #1 as t
    outer apply t.extradata.nodes('
        *:dictionary/*:Item[*:Key="code"]'
    ) as a(c)

Я сохраняювозврат значений NULL.

Я хочу получить пары ключ-значение в двух разных строках, я могу преобразовать данные оттуда.

Ответы [ 3 ]

1 голос
/ 03 октября 2019

В вашем коде SQL используется пространство имен с подстановочными знаками, хотя в вашем примере XML его нет. Кроме того, выражения XPath полностью отключены. Пожалуйста, попробуйте следующее:

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, xml_data XML);
INSERT INTO @tbl (xml_data)
VALUES
(N'<dictionary>
    <item>
        <key>
            <string>MemberNumber</string>
        </key>
        <value>
            <string>66962336209</string>
        </value>
    </item>
</dictionary>');
-- DDL and sample data population, end

SELECT ID
    , col.value('(value/string/text())[1]','VARCHAR(30)') AS [value]
FROM @tbl tbl
    CROSS APPLY tbl.[xml_data].nodes('/dictionary/item[key/string/text() = "MemberNumber"]') AS tab(col);

Вывод:

+----+-------------+
| ID |    value    |
+----+-------------+
|  1 | 66962336209 |
+----+-------------+
0 голосов
/ 04 октября 2019

Я хотел бы разместить альтернативу:

(Кредиты Ицхаку Хабинскому для MCVE - +1 с моей стороны):

DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, xml_data XML);
INSERT INTO @tbl (xml_data)
VALUES
(N'<dictionary>
    <item>
        <key>
            <string>MemberNumber</string>
        </key>
        <value>
            <string>66962336209</string>
        </value>
    </item>
</dictionary>');

- Мы можем использовать внешнийпеременная, чтобы получить это более общее

DECLARE @KeyName VARCHAR(100)='MemberNumber';

- запрос

SELECT t.ID
      ,t.xml_data.value('(/dictionary
                          /item[key/string/text()=sql:variable("@KeyName")] 
                          /value
                          /string
                          /text())[1]','varchar(30)')
FROM @tbl t
--This WHERE is not mandatory, but it might speed things up 
--(if there are many items and many rows without this key)
WHERE t.xml_data.exist('/dictionary[item/key/string/text()=sql:variable("@KeyName")]')=1;

Идея вкратце:

  • Мы объявляем имя ключа мынаходясь в поиске. Это позволяет использовать переменную для получения универсального значения apprach.
  • В WHERE -классе вызывается .exist(). Попробуйте это. Вам это не нужно, но оно может получить некоторую скорость (в зависимости от ваших данных).
  • Функция .value() понижается до /dictionary/item, но использует предикат для фильтрации для одного <item>, где есть ключ с указанным именем. Используя это <item>, мы углубляемся в <value> и читаем его содержимое.
0 голосов
/ 03 октября 2019

Спасибо, это помогло. Новый в извлечении xml, собирал код из различных источников. Также добавлено имя ключа.

DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, xml_data XML);
INSERT INTO @tbl (xml_data)
VALUES
(N'<dictionary>
    <item>
        <key>
            <string>MemberNumber</string>
        </key>
        <value>
            <string>66962336209</string>
        </value>
    </item>
</dictionary>');
-- DDL and sample data population, end

SELECT ID
    , col.value('(key/string/text())[1]','VARCHAR(30)') AS [key]
    , col.value('(value/string/text())[1]','VARCHAR(30)') AS [value]
FROM @tbl tbl
    CROSS APPLY tbl.[xml_data].nodes('/dictionary/item[key/string/text() = "MemberNumber"]') AS tab(col);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...