Bagaimana mengembalikan null dari tag XML kosong di SQL server hanya menggunakan Xpath?

8

Saya memiliki aplikasi yang menyimpan berbagai titik data yang ditentukan pengguna tentang catatan dalam kolom XML. Saya tidak memiliki kendali atas bagaimana ini disimpan atau diperbarui.

Ketika saya meminta sebuah kolom, ia dapat mengembalikan 1 dari 3 nilai:

  1. Nilai
  2. Batal
  3. String kosong

$ 64 pertanyaan saya ingin mengembalikan string kosong tersebut sebagai null menggunakan xpath.

Saya telah menemukan banyak jawaban tentang mengembalikan null sebagai sengatan kosong tetapi tidak dengan cara ini.

Mereka berakhir seperti itu ketika seseorang telah menghapus nilai, dan alih-alih menghapus tag itu kosong menjadi <value />tag. Nol terjadi ketika nilainya tidak pernah ditetapkan. Mereka belum memasukkan xsi: nihil.

Saya sudah melakukannya dengan pernyataan kasus:

    select
    so.SalesOrderId,
    Case
        when sopc.value('(Value)[1]','smalldatetime') IS null then Null
        when sopc.value('(Value)[1]','smalldatetime') ='' then Null
        Else sopc.value('(Value)[1]','smalldatetime')
    End as sopc
    From
    SalesOrders so
    Outer apply so.CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[Name="ProjCompleted"]') sopc(sopc)

tetapi ini terasa tidak efisien dan ini bukan satu-satunya kolom sehingga membuat kode panjang dan sulit untuk dipelihara.

Edit untuk memasukkan data sampel

SalesOrderId    CustomColumns
SO 1            "<CustomColumnsCollection>
                   <CustomColumn>
                     <Name>ProjCompleted</Name>
                     <DataType>1</DataType>
                     <Value />
                   </CustomColumn>
                 </CustomColumnsCollection>"
SO 2           "<CustomColumnsCollection>
                  <CustomColumn>
                     <Name>ProjCompleted</Name>
                     <DataType>1</DataType>
                     <Value>'2017-11-21'</Value>
                  </CustomColumn>
                </CustomColumnsCollection>"
SO 3           "<CustomColumnsCollection>
                </CustomColumnsCollection>"

**Output**
Current      Desired
''           null
2017-11-21   2017-11-21
null         null

Terima kasih sebelumnya.

TimNewman
sumber
Terima kasih Scott - seperti yang Anda lihat, ini adalah pertanyaan pertama saya, apakah ada format yang disukai?
TimNewman
Cukup perbarui pertanyaan Anda dengan blok kode (mirip dengan kode yang sudah Anda posting) yang memiliki sampel XML dan sertakan blok kode lain dari hasil yang diharapkan. Lihat Cara membuat contoh Minimal, Lengkap, dan dapat diverifikasi
Scott Hodgin
Terima kasih - Saya telah menerima jawaban tetapi saya masih akan mengedit pertanyaan untuk membuatnya berguna bagi siapa saja yang menemukan ini.
TimNewman

Jawaban:

11

Tentukan text()simpul di dalam Valueelemen. Node itu hilang ketika Anda memiliki tag kosong.

Coba ini:

declare @X xml;
set @X = '<Value/>';

select @X.value('(Value/text())[1]', 'smalldatetime'),
       @X.value('(Value/text())[1]', 'varchar(max)'),
       @X.value('(Value/text())[1]', 'int'),
       @X.value('(Value)[1]', 'smalldatetime'),
       @X.value('(Value)[1]', 'varchar(max)'),
       @X.value('(Value)[1]', 'int');

Hasil:

------------------- ---------- ----------- ----------------------- ---------- -----------
NULL                NULL       NULL        1900-01-01 00:00:00                0

Merupakan hal yang baik secara umum untuk selalu menentukan text()node. Rencana kueri lebih sederhana dan lebih efisien.

masukkan deskripsi gambar di sini

Mikael Eriksson
sumber