Gunakan SQLCLR UDT. Ini mungkin bisa berhasil, meskipun tidak jelas apakah ini menyajikan keuntungan bersih dibandingkan dengan pendekatan yang dijelaskan di atas.
Ya, SQLCLR UDT dapat membuat operator pembandingnya ditimpa dengan algoritme khusus. Ini menangani situasi di mana nilainya dibandingkan dengan nilai lain yang sudah jenis kustom yang sama, atau yang perlu dikonversi secara implisit. Ini harus menangani filter rentang dalam WHERE
kondisi.
Berkenaan dengan mengurutkan UDT sebagai jenis kolom biasa (bukan kolom yang dihitung), ini hanya mungkin jika UDT adalah "byte dipesan". Menjadi "byte dipesan" berarti bahwa representasi biner dari UDT (yang dapat didefinisikan dalam UDT) secara alami mengurutkan dalam urutan yang sesuai. Dengan asumsi bahwa representasi biner ditangani mirip dengan pendekatan yang dijelaskan di atas untuk kolom VARCHAR (50) yang memiliki segmen panjang tetap yang diisi, yang akan memenuhi syarat. Atau, jika tidak mudah untuk memastikan bahwa representasi biner secara alami akan dipesan dengan cara yang tepat, Anda bisa mengekspos metode atau properti UDT yang menghasilkan nilai yang akan dipesan dengan benar, dan kemudian membuat PERSISTED
kolom yang dikomputasi pada metode atau properti. Metode harus deterministik dan ditandai sebagai IsDeterministic = true
.
Manfaat dari pendekatan ini adalah:
- Tidak perlu bidang "nilai asli".
- Tidak perlu memanggil UDF untuk memasukkan data atau membandingkan nilai. Dengan asumsi bahwa
Parse
metode UDT mengambil P7B18
nilai dan mengubahnya, maka Anda harus dapat dengan mudah memasukkan nilai-nilai secara alami P7B18
. Dan dengan metode konversi implisit yang diatur dalam UDT, kondisi WHERE juga memungkinkan untuk menggunakan P7B18` saja.
Konsekuensi dari pendekatan ini adalah:
- Cukup memilih bidang akan mengembalikan representasi biner, jika menggunakan byte yang dipesan UDT sebagai datatype kolom. Atau jika menggunakan
PERSISTED
kolom yang dihitung pada properti atau metode UDT, maka Anda akan mendapatkan representasi dikembalikan oleh properti atau metode. Jika Anda menginginkan nilai asli P7B18
, maka Anda perlu memanggil metode atau properti UDT yang dikodekan untuk mengembalikan representasi itu. Karena Anda tetap harus mengganti ToString
metode, itu adalah kandidat yang baik untuk menyediakan ini.
Tidak jelas (setidaknya bagi saya saat ini karena saya belum menguji bagian ini) seberapa mudah / sulit akan membuat perubahan pada representasi biner. Mengubah representasi yang tersimpan dan dapat disortir mungkin perlu dijatuhkan dan ditambahkan kembali bidang. Juga, menjatuhkan Majelis yang berisi UDT akan gagal jika digunakan dengan cara apa pun, jadi Anda ingin memastikan bahwa tidak ada yang lain di Majelis selain UDT ini. Anda dapat ALTER ASSEMBLY
mengganti definisi, tetapi ada beberapa batasan untuk itu.
Di sisi lain, VARCHAR()
bidang adalah data yang terputus dari algoritma sehingga hanya perlu memperbarui kolom. Dan jika ada puluhan juta baris (atau lebih) maka itu dapat dilakukan dalam pendekatan batch.
Terapkan perpustakaan ICU yang sebenarnya memungkinkan untuk melakukan pengurutan alfanumerik ini. Meskipun sangat fungsional, perpustakaan hanya tersedia dalam dua bahasa: C / C ++ dan Java. Yang berarti Anda mungkin perlu melakukan beberapa tweak untuk membuatnya berfungsi di Visual C ++, atau ada kemungkinan kode Java dapat dikonversi ke MSIL menggunakan IKVM . Ada satu atau dua proyek sampingan .NET yang ditautkan di situs itu yang menyediakan antarmuka COM yang dapat diakses dalam kode yang dikelola, tetapi saya percaya mereka belum diperbarui dalam beberapa saat dan saya belum mencobanya. Taruhan terbaik di sini adalah menangani ini di lapisan aplikasi dengan tujuan menghasilkan kunci sortir. Kunci sortir kemudian akan disimpan ke dalam kolom sortir baru.
Ini mungkin bukan pendekatan yang paling praktis. Namun, masih sangat keren bahwa kemampuan seperti itu ada. Saya memberikan walk-through yang lebih rinci dari contoh ini dalam jawaban berikut:
Apakah ada susunan untuk menyortir string berikut dalam urutan berikut 1,2,3,6,10,10A, 10B, 11?
Tetapi pola yang dibahas dalam pertanyaan itu sedikit lebih sederhana. Untuk contoh yang menunjukkan bahwa jenis pola yang ditangani dalam Pertanyaan ini juga berfungsi, silakan kunjungi halaman berikut:
Demo Pengumpulan ICU
Di bawah "Pengaturan", atur opsi "numerik" ke "pada" dan semua yang lain harus diatur ke "default". Selanjutnya, di sebelah kanan tombol "sortir", hapus centang opsi untuk "kekuatan diff" dan centang opsi untuk "kunci sortir". Kemudian ganti daftar item dalam area teks "Input" dengan daftar berikut:
P12B22
P7B18
P12B3
as456456hgjg6786867
P7Bb19
P7BA19
P7BB19
P007B18
P7Bb20
P7Bb19z23
Klik tombol "sortir". Area teks "Output" akan menampilkan yang berikut:
as456456hgjg6786867
29 4D 0F 7A EA C8 37 35 3B 35 0F 84 17 A7 0F 93 90 , 0D , , 0D .
P7B18
47 0F 09 2B 0F 14 , 08 , FD F1 , DC C5 DC 05 .
P007B18
47 0F 09 2B 0F 14 , 08 , FD F1 , DC C5 DC 05 .
P7BA19
47 0F 09 2B 29 0F 15 , 09 , FD FF 10 , DC C5 DC DC 05 .
P7Bb19
47 0F 09 2B 2B 0F 15 , 09 , FD F2 , DC C5 DC 06 .
P7BB19
47 0F 09 2B 2B 0F 15 , 09 , FD FF 10 , DC C5 DC DC 05 .
P7Bb19z23
47 0F 09 2B 2B 0F 15 5B 0F 19 , 0B , FD F4 , DC C5 DC 08 .
P7Bb20
47 0F 09 2B 2B 0F 16 , 09 , FD F2 , DC C5 DC 06 .
P12B3
47 0F 0E 2B 0F 05 , 08 , FD F1 , DC C5 DC 05 .
P12B22
47 0F 0E 2B 0F 18 , 08 , FD F1 , DC C5 DC 05 .
Harap dicatat bahwa kunci pengurutan adalah struktur dalam beberapa bidang, dipisahkan oleh koma. Setiap bidang perlu diurutkan secara independen, sehingga menyajikan masalah kecil lain untuk dipecahkan jika perlu mengimplementasikan ini dalam SQL Server.
P7B12
bisa menjadiP 07 B 12
, lalu (via ASCII)80 07 65 12
, jadi80076512