Mengonversi VARCHAR ke VARBINARY

17

Saya telah menyimpan log kueri berjalan mahal, bersama dengan rencana kueri mereka, dalam tabel untuk memungkinkan kami memantau tren kinerja dan mengidentifikasi area yang perlu dioptimalkan.

Namun, itu sampai pada titik di mana rencana kueri mengambil terlalu banyak ruang (karena kami menyimpan seluruh rencana terhadap setiap kueri).

Karena itu saya mencoba menormalkan data yang ada dengan mengekstraksi QueryPlanHash dan QueryPlan ke tabel lain.

CREATE TABLE QueryPlans
(
    QueryPlanHash VARBINARY(25),
    QueryPlan XML,
    CONSTRAINT PK_QueryPlans PRIMARY KEY
    (
      QueryPlanHash
    )
);

Karena definisi query_plan_hashin sys.dm_exec_query_statsadalah bidang biner (dan saya akan secara teratur memasukkan data baru), saya menggunakan VARBINARYtipe data di tabel baru saya.

Namun, masukkan di bawah gagal ...

INSERT INTO QueryPlans
    ( QueryPlanHash, QueryPlan )
SELECT queryplanhash, queryplan
FROM
(
    SELECT 
      p.value('(./@QueryPlanHash)[1]', 'varchar(20)') queryplanhash,
      QueryPlan,
      ROW_NUMBER() OVER (PARTITION BY p.value('(./@QueryPlanHash)[1]', 'varchar(20)') ORDER BY DateRecorded) rownum
    FROM table
    CROSS APPLY QueryPlan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple[@QueryPlanHash]') t(p)
) data
WHERE rownum = 1

.... dengan kesalahan

Implicit conversion from data type varchar to varbinary is not allowed. Use the CONVERT function to run this query.

Masalahnya adalah bahwa hash rencana kueri sudah dalam format biner, namun disimpan sebagai VARCHAR dalam Paket Kueri XML misalnya

0x9473FBCCBC01AFE

dan CONVERT to BINARY memberikan nilai yang sama sekali berbeda

0x3078393437334642434342433031414645

Saya mencoba mengubah definisi nilai dalam pilih XQuery ke biner, tetapi kemudian tidak mengembalikan nilai.

Bagaimana cara mengekstrak nilai dari 0x9473FBCCBC01AFEpaket kueri XML sebagai VARBINARY, bukan sebagai VARCHAR?

Mark Sinkinson
sumber

Jawaban:

28

Anda perlu menggunakan gaya tertentu saat Anda berharap untuk mempertahankan nilai biner yang sama saat mengkonversi dari string. Kalau tidak, SQL Server mencoba untuk menyandikan string dengan cara yang sama seperti itu akan menyandikan 'bob'atau 'frank'.

Karena itu, string input Anda tidak terlihat benar - ada byte yang hilang atau satu byte yang terlalu banyak. Ini berfungsi dengan baik jika saya menghentikan trailing E:

SELECT CONVERT(VARBINARY(25), '0x9473FBCCBC01AF', 1);
------------ the ,1 is important ---------------^^^

Hasilnya adalah biner:

----------------
0x9473FBCCBC01AF
Aaron Bertrand
sumber
1
Ah, ,1itulah yang saya lewatkan. Itu lebih mudah dari yang saya harapkan! Terima kasih!
Mark Sinkinson
Tidak yakin tentang byte yang hilang / ekstra. Dalam 2666 catatan yang saya miliki, ada 183 yang gagalTRY_CONVERT
Mark Sinkinson
Mungkin perlu menambahkan karakter (misalnya, 0) ke string apa pun dengan jumlah karakter aneh. Itu mengubah nilai, tetapi harus selalu mengubah nilai yang sama dengan cara yang sama (dan saya tidak curiga Anda akan memiliki tabrakan dengan atau tanpa 0).
Aaron Bertrand
Apakah itu bukan bug? Kueriplanhash dalam xml secara eksplisit diatur ke nilai itu ... Tentunya a TRY_CONVERTke a BINARYtidak boleh kembaliNULL
Mark Sinkinson
Dari membandingkan nilai yang disimpan di tabel saya ke xml itu sebenarnya 0 terkemuka yang hilang. Jadi nilainya harus 0x09473FBCCBC01AF. Saya dapat memperbaikinya dengan REPLACE sederhana, tapi saya yakin itu adalah bug ...
Mark Sinkinson
0

Bagaimana cara mengekstrak nilai 0x9473FBCCBC01AFE dari paket kueri XML sebagai VARBINARY, dan bukan VARCHAR?

Saya menghadapi sesuatu seperti itu menggunakan HeidiSQL untuk kueri pada tabel CASD, dan diselesaikan dengan fn_varbintohexstr () , seperti ini:

SELECT master.dbo.fn_varbintohexstr(table.hexfield) FROM table;

Dengan HeidiSQL, nilainya salah seperti '0x3F3F3F3F3F3F3F3F' dan menjadi benar seperti '0x158B1DB75616484695684007CE98E21C'.

OBS: Berfungsi sejak MSSQL 2008! Semoga ini bisa membantu!

MMJ
sumber
2
Perhatikan peringatan untuk menggunakan yang fn_varbintohexstr() disebutkan di sini .
Erik