Saya memiliki XML
kolom yang berisi data dengan struktur serupa:
<Root>
<Elements>
<Element Code="1" Value="aaa"></Element>
<Element Code="2" Value="bbb"></Element>
<Element Code="3" Value="ccc"></Element>
</Elements>
</Root>
Bagaimana saya bisa memodifikasi data menggunakan SQL Server untuk mengubah setiap Value
atribut menjadi elemen?
<Root>
<Elements>
<Element Code="1">
<Value>aaa</Value>
</Element>
<Element Code="2">
<Value>bbb</Value>
</Element>
<Element Code="3">
<Value>ccc</Value>
</Element>
</Elements>
</Root>
Memperbarui:
XML saya terlihat lebih seperti ini:
<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="bbb" ExtraData="extra" />
<Element Code="3" Value="ccc" ExtraData="extra" />
<Element Code="4" Value="" ExtraData="extra" />
<Element Code="5" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>
Saya hanya ingin memindahkan Value
atribut dan mempertahankan semua atribut dan elemen lainnya.
sql-server
xml
xquery
Wojteq
sumber
sumber
<Value>
elemen per masing-masing<Element>
. Jika tidak, maka memindahkan atribut ke elemen hanya membuat XML lebih kembung, dan mungkin kurang efisien.<Value>
elemen atau sebagai gantinya.Jawaban:
Anda dapat menghancurkan XML dan membangunnya kembali menggunakan XQuery.
Hasil:
Jika
Elements
bukan elemen pertama di bawahRoot
kueri perlu dimodifikasi untuk menambahkan semua elemen sebelum elemenElements
pertama danElements
sesudahnya.sumber
Anda juga dapat menggunakan metode tipe data XML (misalnya, modifikasi ) dan beberapa XQuery untuk memodifikasi xml, misalnya
Metode ini tidak cenderung untuk menskalakan XML dalam jumlah besar tetapi mungkin lebih cocok untuk Anda daripada penggantian XML secara grosir.
Anda juga dapat dengan mudah mengadaptasi metode ini jika XML Anda disimpan dalam sebuah tabel. Sekali lagi dari pengalaman saya tidak akan merekomendasikan menjalankan pembaruan tunggal terhadap tabel juta baris. Jika meja Anda besar, pertimbangkan menjalankan kursor melewatinya atau mengelompokkan pembaruan. Inilah tekniknya:
sumber
MEMPERBARUI:
Saya telah memperbarui kode, serta input dan output XML dalam contoh pertanyaan di bawah ini untuk mencerminkan persyaratan terbaru, dinyatakan dalam komentar pada jawaban baik @ Mikael , yaitu:
Sementara satu ekspresi dapat dengan benar mencocokkan variasi baru ini, tampaknya tidak ada cara untuk menghilangkan
<Value/>
elemen kosong dalam satu lintasan karena logika kondisional tidak diperbolehkan dalam string pengganti. Jadi, saya telah mengadaptasi ini menjadi modifikasi 2 bagian: satu pass untuk mendapatkan@Value
atribut yang tidak kosong dan satu pass untuk mendapatkan@Value
atribut kosong . Tidak perlu menangani atribut<Element>
yang hilang@Value
karena keinginannya adalah untuk tidak memiliki<Value>
elemen.Salah satu pilihan adalah memperlakukan XML sebagai string biasa dan mengubahnya berdasarkan suatu pola. Ini mudah dilakukan dengan menggunakan Ekspresi Reguler (khususnya fungsi "Ganti") yang dapat disediakan melalui kode SQLCLR.
Contoh di bawah ini menggunakan skalar UDF RegEx_Replace dari pustaka SQL # (yang saya penulis, tetapi fungsi RegEx ini tersedia dalam versi Gratis, bersama dengan banyak lainnya):
The
PRINT
pernyataan berada di sana hanya untuk membuat lebih mudah perbandingan sisi-by-side di tab "Pesan". Output yang dihasilkan adalah (saya memodifikasi XML asli sedikit untuk membuatnya sangat jelas bahwa hanya bagian yang diinginkan yang disentuh dan tidak ada yang lain):Jika Anda ingin memperbarui bidang dalam tabel, Anda bisa menyesuaikan yang di atas sebagai berikut:
sumber
Mungkin ada cara yang lebih baik untuk melakukannya di luar SQL Server. Namun, inilah salah satu cara melakukannya.
Xml CTE mengubah variabel xml Anda menjadi sebuah tabel.
Pilih utama kemudian mengubah CTE kembali ke xml.
Itu juga bisa dilakukan menggunakan
For XML Explicit
.sumber