SQL Server 2008 XPath

Мы пытаемся отфильтровать набор XML на основе предоставленного нами значения.

У нас есть следующий XML в поле XML с нашей базой данных, и если пройти через число «5052095050830», нам нужно найти этот конкретный узел в XML. Предоставляемый нами номер может существовать любое количество раз.

Может ли кто-нибудь предоставить пример SQL для помощи?

Спасибо

<Attributes>
  <ProductVariantAttribute ID="4387">
    <ProductVariantAttributeValue>
      <Value>5052095050830</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="9999">
    <ProductVariantAttributeValue>
      <Value>5052095050830</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4388">
    <ProductVariantAttributeValue>
      <Value>104401330A</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4389">
    <ProductVariantAttributeValue>
      <Value>6905</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4390">
    <ProductVariantAttributeValue>
      <Value>6906</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4391">
    <ProductVariantAttributeValue>
      <Value>Monday, October 27, 2008</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
</Attributes>

person ajbrun    schedule 15.04.2011    source источник


Ответы (3)


Вы можете использовать метод .exist() - что-то вроде этого:

SELECT 
(list of columns) 
FROM
dbo.YourTable
WHERE
YourXmlColumn.exist('//Value[text()="5052095050830"]') = 1

Это проверяет конкретное значение, которое вы указали. Чем точнее вы сможете определить XPath, где ожидается найти это значение, тем лучше для вашей производительности.

YourXmlColumn.exist('//Value[text()="5052095050830"]') = 1

довольно плохо - он просматривает каждый узел <Value> в любом месте XML, чтобы найти это значение.

Что-то вроде этого:

YourXmlColumn.exist('/Attributes/ProductVariantAttribute/ProductVariantAttributeValue/Value[text()="5052095050830"]') = 1

будет гораздо более сфокусированным и, следовательно, намного лучше для производительности, но это будут только те конкретные узлы, которые определены этим самым оператором XPath.

person marc_s    schedule 15.04.2011
comment
Спасибо - я почти там сейчас. Я пытаюсь заставить что-то подобное работать. Это идет либо с нулевыми результатами. Что я делаю не так? DECLARE @Barcode VARCHAR SELECT @Barcode = '5052095050830' SELECT * FROM Nop_ProductVariantAttributeCombination WHERE AttributesXml.exist('/Attributes/ProductVariantAttribute/ProductVariantAttributeValue/Value[text()="sql:variable(@Barcode)"]') = 1 - person ajbrun; 15.04.2011
comment
@Adrian: не уверен, но вы должны попробовать с двойными кавычками вокруг sql:variable: /Value[text()=sql:variable(@Barcode)] - также вы можете указать длину своей переменной @Barcode при ее объявлении - иначе это VARCHAR(1), я думаю ... - person marc_s; 15.04.2011

Это возвращает значения как другой XML, я не уверен, как вы этого хотели.

DECLARE @xml AS XML
SET @xml =
'<Attributes>
  <ProductVariantAttribute ID="4387">
    <ProductVariantAttributeValue>
      <Value>5052095050830</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="9999">
    <ProductVariantAttributeValue>
      <Value>5052095050830</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4388">
    <ProductVariantAttributeValue>
      <Value>104401330A</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4389">
    <ProductVariantAttributeValue>
      <Value>6905</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4390">
    <ProductVariantAttributeValue>
      <Value>6906</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
  <ProductVariantAttribute ID="4391">
    <ProductVariantAttributeValue>
      <Value>Monday, October 27, 2008</Value>
    </ProductVariantAttributeValue>
  </ProductVariantAttribute>
</Attributes>'


SELECT @xml.query
('
    for $text in //Attributes/ProductVariantAttribute
    where $text/ProductVariantAttributeValue/Value[text()] = 5052095050830
    return string($text/@ID)
')
person SQLMason    schedule 15.04.2011
comment
Измените его на: ''104401330A'' для varchar, извините - person SQLMason; 15.04.2011

Если вы хотите получить атрибут @ID, вот он:

        DECLARE @xml AS XML
    SET @xml =
        '<Attributes>
        <ProductVariantAttribute ID="4387">
            <ProductVariantAttributeValue>
                <Value>5052095050830</Value>
            </ProductVariantAttributeValue>
        </ProductVariantAttribute>
        <ProductVariantAttribute ID="9999">
            <ProductVariantAttributeValue>
                <Value>5052095050830</Value>
            </ProductVariantAttributeValue>
        </ProductVariantAttribute>
        <ProductVariantAttribute ID="4388">
            <ProductVariantAttributeValue>
                <Value>104401330A</Value>
            </ProductVariantAttributeValue>
        </ProductVariantAttribute>
        <ProductVariantAttribute ID="4389">
            <ProductVariantAttributeValue>
                <Value>6905</Value>
        </ProductVariantAttributeValue>
        </ProductVariantAttribute>
        <ProductVariantAttribute ID="4390">
            <ProductVariantAttributeValue>
                <Value>6906</Value>
            </ProductVariantAttributeValue>
            </ProductVariantAttribute>
        <ProductVariantAttribute ID="4391">
            <ProductVariantAttributeValue>
                <Value>Monday, October 27, 2008</Value>
        </ProductVariantAttributeValue>
        </ProductVariantAttribute>
    </Attributes>'


    select 
    t.x.value('@ID' ,'varchar(50)') ProductVariantAttributeID
    from @xml.nodes('//ProductVariantAttribute') t(x)
    where t.x.value('(ProductVariantAttributeValue/Value)[1]' , 'nvarchar(50)') = '5052095050830'
person hkravitz    schedule 25.10.2013