Saya memiliki tabel yang berisi Xml
kolom:
SELECT *
FROM Sqm
Contoh xml
data suatu baris adalah:
<Sqm version="1.2">
<Metrics>
<Metric id="TransactionCleanupThread.RecordUsedTransactionShift" type="timer" unit="µs" count="1" sum="21490" average="21490" minValue="73701" maxValue="73701" >73701</Metric>
<Metric id="TransactionCleanupThread.RefundOldTrans" type="timer" unit="µs" count="1" sum="184487" average="184487" minValue="632704" maxValue="632704" >632704</Metric>
<Metric id="Database.CreateConnection_SaveContextUserGUID" type="timer" unit="µs" count="2" sum="7562" average="3781" minValue="12928" maxValue="13006" standardDeviation="16" >12967</Metric>
<Metric id="Global.CurrentUser" type="timer" unit="µs" count="6" sum="4022464" average="670411" minValue="15" maxValue="13794345" standardDeviation="1642047">2299194</Metric>
<Metric id="Global.CurrentUser_FetchIdentityFromDatabase" type="timer" unit="µs" count="1" sum="4010057" average="4010057" minValue="13752614" maxValue="13752614" >13752614</Metric>
</Metrics>
</Sqm>
Dalam kasus data ini, saya ingin:
SqmId id type unit count sum minValue maxValue standardDeviation Value
===== =================================================== ===== ==== ===== ====== ======== ======== ================= ======
1 TransactionCleanupThread.RecordUsedTransactionShift timer µs 1 21490 73701 73701 NULL 73701
1 TransactionCleanupThread.RefundOldTrans timer µs 1 184487 632704 632704 NULL 632704
1 Database.CreateConnection_SaveContextUserGUID timer µs 2 7562 12928 13006 16 12967
1 Global.CurrentUser timer µs 6 4022464 15 13794345 1642047 2299194
1 Global.CurrentUser_FetchIdentityFromDatabase timer µs 1 4010057 13752614 13752614 NULL 13752614
2 ...
Pada akhirnya saya benar-benar akan melakukan SUM()
, MIN()
, MAX()
agregasi. Tetapi untuk saat ini saya hanya mencoba untuk menanyakan kolom xml.
Dalam pseudo-code, saya akan mencoba sesuatu seperti:
SELECT
SqmId,
Data.query('/Sqm/Metrics/Metric/@id') AS id,
Data.query('/Sqm/Metrics/Metric/@type') AS type,
Data.query('/Sqm/Metrics/Metric/@unit') AS unit,
Data.query('/Sqm/Metrics/Metric/@sum') AS sum,
Data.query('/Sqm/Metrics/Metric/@count') AS count,
Data.query('/Sqm/Metrics/Metric/@minValue') AS minValue,
Data.query('/Sqm/Metrics/Metric/@maxValue') AS maxValue,
Data.query('/Sqm/Metrics/Metric/@standardDeviation') AS standardDeviation,
Data.query('/Sqm/Metrics/Metric') AS value
FROM Sqm
Tetapi kueri SQL itu tidak berfungsi:
Psn 2396, Level 16,
Status 1, Baris 2 XQuery [Sqm.data.query ()]: Atribut mungkin tidak muncul di luar elemen
Saya telah berburu, dan sungguh menakjubkan betapa buruknya dokumentasi, atau contoh, kueri Xml. Sebagian besar sumber daya daripada membuat kueri tabel , kueri a variabel ; yang tidak saya lakukan. Sebagian besar sumber daya hanya menggunakan kueri xml untuk pemfilteran dan pemilihan, daripada membaca nilai. Sebagian besar resource membaca node turunan hard code (menurut indeks), bukan nilai sebenarnya.
Sumber terkait yang saya baca
- /programming/966441/xml-query-in-sql-server-2008
- Atribut xml kueri SQL Server untuk nilai elemen
- SQL meminta atribut XML
- SQL Server 2005 XQuery dan XML-DML - Bagian 1
- BOL: Dukungan XML di Microsoft SQL Server 2005
- Membuat kueri XML di SQL Server
- Kueri XML SQL Server Dasar
- BOL: Metode query () (Tipe Data xml)
- XML Workshop V - Membaca Nilai dari Kolom XML
- SQL SERVER - Pengantar Menemukan Metode Tipe Data XML - Primer
Perbarui: .value daripada .query
Saya mencoba menggunakan secara acak .value
, sebagai ganti .query
:
SELECT
Sqm.SqmId,
Data.value('/Sqm/Metrics/Metric/@id', 'varchar(max)') AS id,
Data.value('/Sqm/Metrics/Metric/@type', 'varchar(max)') AS type,
Data.value('/Sqm/Metrics/Metric/@unit', 'varchar(max)') AS unit,
Data.value('/Sqm/Metrics/Metric/@sum', 'varchar(max)') AS sum,
Data.value('/Sqm/Metrics/Metric/@count', 'varchar(max)') AS count,
Data.value('/Sqm/Metrics/Metric/@minValue', 'varchar(max)') AS minValue,
Data.value('/Sqm/Metrics/Metric/@maxValue', 'varchar(max)') AS maxValue,
Data.value('/Sqm/Metrics/Metric/@standardDeviation', 'varchar(max)') AS standardDeviation,
Data.value('/Sqm/Metrics/Metric', 'varchar(max)') AS value
FROM Sqm
Tapi itu juga tidak berhasil:
MSG 2389, Level 16, Status 1, Baris 3 XQuery [Sqm.data.value ()]:
'value ()' memerlukan singleton (atau urutan kosong), operan yang ditemukan dari tipe 'xdt: untypedAtomic *'
select m.*
untuk melihat tabel perantara, ajaib, dan rahasia yang dibangunnya. Apa sintaks untuk menanyakan nilai suatu elemen? misalnya nilai<Metric>8675309</Metric>
adalah "8675309"s
,m
danc
mewakili dalam query ini?m
adalah kumpulan hasil yang dikembalikan olehnodes()
fungsi,s
adalahsqm
tabel itu sendiri,c
adalah kolom dengan tipe data xml dalam kumpulan hasil yang dikembalikan olehnodes()
fungsiSaya telah mencoba melakukan sesuatu yang sangat mirip tetapi tidak menggunakan node. Namun, struktur xml saya sedikit berbeda.
Anda memilikinya seperti ini:
<Metrics> <Metric id="TransactionCleanupThread.RefundOldTrans" type="timer" ...>
Jika sudah seperti ini sebagai gantinya:
<Metrics> <Metric> <id>TransactionCleanupThread.RefundOldTrans</id> <type>timer</type> . . .
Kemudian Anda cukup menggunakan pernyataan SQL ini.
SELECT Sqm.SqmId, Data.value('(/Sqm/Metrics/Metric/id)[1]', 'varchar(max)') as id, Data.value('(/Sqm/Metrics/Metric/type)[1]', 'varchar(max)') AS type, Data.value('(/Sqm/Metrics/Metric/unit)[1]', 'varchar(max)') AS unit, Data.value('(/Sqm/Metrics/Metric/sum)[1]', 'varchar(max)') AS sum, Data.value('(/Sqm/Metrics/Metric/count)[1]', 'varchar(max)') AS count, Data.value('(/Sqm/Metrics/Metric/minValue)[1]', 'varchar(max)') AS minValue, Data.value('(/Sqm/Metrics/Metric/maxValue)[1]', 'varchar(max)') AS maxValue, Data.value('(/Sqm/Metrics/Metric/stdDeviation)[1]', 'varchar(max)') AS stdDeviation, FROM Sqm
Bagi saya ini jauh lebih membingungkan daripada menggunakan penerapan luar atau penerapan silang.
Saya harap ini membantu orang lain mencari solusi yang lebih sederhana!
sumber
/text()
setelah id dll untuk peningkatan kinerjagunakan
value
sebagai gantiquery
(harus menentukan indeks node yang akan dikembalikan di XQuery serta meneruskan tipe data sql untuk dikembalikan sebagai parameter kedua):select xt.Id , x.m.value( '@id[1]', 'varchar(max)' ) MetricId from XmlTest xt cross apply xt.XmlData.nodes( '/Sqm/Metrics/Metric' ) x(m)
sumber
Saya tidak mengerti mengapa beberapa orang menyarankan untuk menggunakan
cross apply
atauouter apply
mengubah xml menjadi tabel nilai. Bagi saya, itu hanya membawa terlalu banyak data.Inilah contoh saya bagaimana Anda akan membuat sebuah
xml
objek, lalu mengubahnya menjadi tabel.(Saya telah menambahkan spasi di string xml saya, hanya untuk membuatnya lebih mudah dibaca.)
DECLARE @str nvarchar(2000) SET @str = '' SET @str = @str + '<users>' SET @str = @str + ' <user>' SET @str = @str + ' <firstName>Mike</firstName>' SET @str = @str + ' <lastName>Gledhill</lastName>' SET @str = @str + ' <age>31</age>' SET @str = @str + ' </user>' SET @str = @str + ' <user>' SET @str = @str + ' <firstName>Mark</firstName>' SET @str = @str + ' <lastName>Stevens</lastName>' SET @str = @str + ' <age>42</age>' SET @str = @str + ' </user>' SET @str = @str + ' <user>' SET @str = @str + ' <firstName>Sarah</firstName>' SET @str = @str + ' <lastName>Brown</lastName>' SET @str = @str + ' <age>23</age>' SET @str = @str + ' </user>' SET @str = @str + '</users>' DECLARE @xml xml SELECT @xml = CAST(CAST(@str AS VARBINARY(MAX)) AS XML) -- Iterate through each of the "users\user" records in our XML SELECT x.Rec.query('./firstName').value('.', 'nvarchar(2000)') AS 'FirstName', x.Rec.query('./lastName').value('.', 'nvarchar(2000)') AS 'LastName', x.Rec.query('./age').value('.', 'int') AS 'Age' FROM @xml.nodes('/users/user') as x(Rec)
Dan inilah hasilnya:
sumber
Varbinary(max)
sebelum pemeran xml?