Cara menghapus node anak XML menggunakan SQL Server 2016

Saya memiliki cuplikan contoh Xml berikut yang diambil dari file yang lebih besar:

<EntityAttributeValue>
  <Value />
  <Attribute>
    <Id>0</Id>
    <Name>Use 3</Name>
    <AttributeType>other</AttributeType>
  </Attribute>
  <AttributeValueId>999998</AttributeValueId>
  <ProductTypeId xsi:nil="true" />
</EntityAttributeValue>

Saya mencoba menghapus node <ProductTypeId> menggunakan SQL sehingga tampilan di atas akan seperti ini:

<EntityAttributeValue>
  <Value />
  <Attribute>
    <Id>13</Id>
    <Name>Use 3</Name>
    <AttributeType>other</AttributeType>
  </Attribute>
  <AttributeValueId>999998</AttributeValueId>
</EntityAttributeValue>

Saya telah menggunakan yang berikut ini untuk menanyakan SQL XML dan mengisolasi cuplikan di atas (yang pertama)

select t.c.query('.') as Attributes 
from @XMLData.nodes('/Item/ContentAttributeValues/EntityAttributeValue') t(c)
where t.c.value('(Attribute/Id)[1]','INT') = 0

saya telah mencoba

SET @XMLData.modify('delete (/Item/ContentAttributeValues/EntityAttributeValue/ProductTypeId)') 

untuk menghapus semua id produk, tetapi tidak berhasil, bantuan apa pun akan sangat diterima.

Bersulang


person William Mather    schedule 17.02.2020    source sumber
comment
Harap posting laporan lengkap mengenai masalah ini, karena xml.modify( tampaknya benar.   -  person David Browne - Microsoft    schedule 17.02.2020


Jawaban (4)


Dalam cuplikan XML yang Anda berikan, Anda memiliki root yang berbeda. Jadi, agar delete Anda berfungsi, yang Anda butuhkan hanyalah menyesuaikan jalurnya:

SET @XMLData.modify('delete /EntityAttributeValue/ProductTypeId');
person Roger Wolf    schedule 17.02.2020

Berikut adalah contoh lengkapnya. Saya harus menambahkan namespace ke root untuk mengakomodasi atribut xsi:nil="true".

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML NOT NULL);
INSERT INTO @tbl (xmldata) VALUES
(N'<Item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <ContentAttributeValues>
        <EntityAttributeValue>
            <Value/>
            <Attribute>
                <Id>0</Id>
                <Name>Use 3</Name>
                <AttributeType>other</AttributeType>
            </Attribute>
            <AttributeValueId>999998</AttributeValueId>
            <ProductTypeId xsi:nil="true"/>
        </EntityAttributeValue>
        <EntityAttributeValue>
            <Value/>
            <Attribute>
                <Id>10</Id>
                <Name>Use 7</Name>
                <AttributeType>other</AttributeType>
            </Attribute>
            <AttributeValueId>999770</AttributeValueId>
            <ProductTypeId xsi:nil="true"/>
        </EntityAttributeValue>
    </ContentAttributeValues>
</Item>');
-- DDL and sample data population, end

UPDATE @tbl
SET xmldata.modify('delete /Item/ContentAttributeValues/EntityAttributeValue/ProductTypeId');

SELECT * FROM @tbl;

XML keluaran

<Item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ContentAttributeValues>
    <EntityAttributeValue>
      <Value />
      <Attribute>
        <Id>0</Id>
        <Name>Use 3</Name>
        <AttributeType>other</AttributeType>
      </Attribute>
      <AttributeValueId>999998</AttributeValueId>
    </EntityAttributeValue>
    <EntityAttributeValue>
      <Value />
      <Attribute>
        <Id>10</Id>
        <Name>Use 7</Name>
        <AttributeType>other</AttributeType>
      </Attribute>
      <AttributeValueId>999770</AttributeValueId>
    </EntityAttributeValue>
  </ContentAttributeValues>
</Item>
person Yitzhak Khabinsky    schedule 17.02.2020

Dari kode yang saya ambil, Anda sedang mencari <ProductTypeId> dari elemen EAV, dimana <Attribute><Id> memiliki nilai 0.

Pertanyaan Anda tidak semuanya jelas, tapi saya rasa Anda mungkin mencari ini:

declare @tbl TABLE(ID INT IDENTITY, YourXml XML);
INSERT INTO @tbl VALUES
(N'<Item xmlns:xsi="blahblah">
  <ContentAttributeValues>
    <EntityAttributeValue>
      <Value />
      <Attribute>
        <Id>0</Id>                                     <!-- Id value = 0  -->
        <Name>Use 3</Name>
        <AttributeType>other</AttributeType>
      </Attribute>
      <AttributeValueId>999998</AttributeValueId>
      <ProductTypeId xsi:nil="true" />                 
    </EntityAttributeValue>
    <EntityAttributeValue>
      <Value />
      <Attribute>
        <Id>1</Id>                                      <!-- Other Id value!!!  -->
        <Name>Use 3</Name>
        <AttributeType>other</AttributeType>
      </Attribute>
      <AttributeValueId>999998</AttributeValueId>
      <ProductTypeId xsi:nil="true" />
    </EntityAttributeValue>
  </ContentAttributeValues>
</Item>');

UPDATE @tbl SET YourXml.modify(N'delete /Item
                                        /ContentAttributeValues
                                        /EntityAttributeValue[Attribute/Id = 0]
                                        /ProductTypeId');

SELECT * FROM @tbl;

XPath adalah singkatan dari: Selami elemen EAV dan filter elemen yang menjawab predikat. Di bawah elemen EAV ini temukan <ProductTypeID> dan hapus.

Hasilnya Anda akan menemukan, bahwa node tersebut dihapus hanya untuk elemen EAV pertama, yang memiliki Id=0.

person Shnugo    schedule 17.02.2020

Halo Semua dan terima kasih atas komentar Anda.

maaf karena tidak memperjelas kode saya, saya pikir itu ada di kepala saya dan sudah larut hari! tertawa terbahak-bahak.

SET @XMLData.modify('delete(/Item/ContentAttributeValues/EntityAttributeValue/ProductTypeId)') berhasil dengan baik.. Saya telah mencobanya sebelumnya tetapi saya mendapatkan kesalahan, saya tahu bahwa tanda kurung setelah penghapusan, adalah kunci agar itu berfungsi ha! terima kasih semuanya lagi!!

person William Mather    schedule 18.02.2020
comment
Senang mendengar bahwa solusi yang diusulkan berhasil untuk Anda. Harap tandai sebagai telah dijawab. Anda hanya perlu menandai jawaban sebagai benar (gambar centang hijau). Klik tanda centang bergaris hijau di sebelah kiri jawaban yang memecahkan masalah Anda. Ini menandai jawaban diterima - person Yitzhak Khabinsky; 18.02.2020