Membuat Jenis Buatan Pengguna khusus melalui SQLCLR adalah tidak , dengan cara apa pun, akan memberi Anda pengganti jenis asli apa pun. Ini sangat berguna untuk membuat sesuatu untuk menangani data khusus. Tetapi string, bahkan dari pengkodean yang berbeda, jauh dari khusus. Mengikuti rute ini untuk data string Anda akan menghancurkan kegunaan sistem Anda, belum lagi kinerja karena Anda tidak akan dapat menggunakan apa pun fungsi string bawaan.
Jika Anda dapat menghemat apa pun di ruang disk, keuntungan itu akan terhapus oleh apa yang akan hilang dalam kinerja keseluruhan. Menyimpan UDT dilakukan dengan membuat serialisasi ke VARBINARY
. Jadi untuk melakukan apa saja perbandingan string ATAU penyortiran, di luar perbandingan "biner" / "ordinal", Anda harus mengonversi semua nilai lain, satu per satu, kembali ke UTF-8 untuk kemudian melakukan perbandingan string yang dapat menjelaskan perbedaan linguistik. Dan konversi itu perlu dilakukan di dalam UDT. Ini berarti, seperti tipe data XML, Anda akan membuat UDT untuk menyimpan nilai tertentu, dan kemudian mengekspos metode UDT tersebut untuk menerima parameter string untuk melakukan perbandingan (yaitu Utf8String.Compare(alias.field1)
atau, jika mendefinisikan operator untuk tipe tersebut, maka Utf8string1 = Utf8string2
dan memiliki =
operator mendapatkan string dalam pengkodean UTF-8 dan kemudian melakukan CompareInfo.Compare()
).
Selain pertimbangan di atas, Anda juga perlu mempertimbangkan bahwa meneruskan nilai bolak-balik melalui API SQLCLR memiliki biaya, terutama bila menggunakan NVARCHAR(MAX)
atau VARBINARY(MAX)
sebagai lawan dari NVARCHAR(1 - 4000)
dan VARBINARY(1 - 4000)
masing-masing (jangan bingung membedakan ini sebagai menyiratkan apa pun tentang menggunakan SqlChars
/ SqlBytes
vs SqlString
/ SqlBinary
).
Terakhir (setidaknya dalam hal menggunakan UDT), jangan mengabaikan fakta bahwa UDT yang ditanyakan adalah kode contoh . Satu-satunya pengujian yang dicatat adalah murni fungsional, tidak ada skalabilitas atau "pelajaran yang didapat setelah bekerja dengan ini selama setahun". Kode uji fungsional ditampilkan di sini di halaman CodePlex berikut dan harus dilihat sebelum melanjutkan dengan keputusan ini karena memberikan gambaran tentang bagaimana Anda perlu menulis kueri Anda untuk berinteraksi dengannya (yang baik untuk bidang atau dua, tapi tidak untuk sebagian besar / semua bidang string):
Mengingat jumlah kolom dan indeks yang dihitung tetap ditambahkan, apakah ada ruang yang benar-benar disimpan?;-)
Di mana ruang (disk, memori, dll) menjadi perhatian, Anda memiliki tiga opsi:
-
Jika Anda menggunakan SQL Server 2008 atau yang lebih baru, dan menggunakan Edisi Perusahaan, maka Anda dapat mengaktifkan Kompresi Data . Kompresi Data dapat (tetapi tidak akan "selalu") mengompresi data Unicode di
NCHAR
danNVARCHAR
bidang. Faktor penentunya adalah:NCHAR(1 - 4000)
danNVARCHAR(1 - 4000)
gunakan Skema Kompresi Standar untuk Unicode , tetapi hanya dimulai di SQL Server 2008 R2, DAN hanya untuk data IN ROW, bukan OVERFLOW! Ini tampaknya lebih baik daripada algoritme kompresi ROW / PAGE biasa.NVARCHAR(MAX)
danXML
(dan saya rasa jugaVARBINARY(MAX)
,TEXT
, danNTEXT
) data yang IN ROW (tidak keluar baris di halaman LOB atau OVERFLOW) setidaknya dapat dikompresi PAGE, dan mungkin juga ROW dikompresi (tidak yakin tentang yang terakhir ini).- Data OFF ROW, LOB atau OVERLOW =Tanpa Kompresi Untuk Anda!
-
Jika menggunakan versi yang lebih lama dari 2008 atau tidak pada Edisi Perusahaan, Anda dapat memiliki dua bidang:satu
VARCHAR
dan satuNVARCHAR
. Misalnya, katakanlah Anda menyimpan URL yang sebagian besar adalah semua karakter ASCII dasar (nilai 0 - 127) dan karenanya cocok denganVARCHAR
, tetapi terkadang memiliki karakter Unicode. Skema Anda dapat menyertakan 3 bidang berikut:... URLa VARCHAR(2048) NULL, URLu NVARCHAR(2048) NULL, URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])), CONSTRAINT [CK_TableName_OneUrlMax] CHECK ( ([URLa] IS NOT NULL OR [URLu] IS NOT NULL) AND ([URLa] IS NULL OR [URLu] IS NULL)) );
Dalam model ini Anda hanya PILIH dari
[URL]
kolom yang dihitung. Untuk menyisipkan dan memperbarui, Anda menentukan bidang mana yang akan digunakan dengan melihat apakah konversi mengubah nilai yang masuk, yang harus berupaNVARCHAR
ketik:INSERT INTO TableName (..., URLa, URLu) VALUES (..., IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL), IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL) );
-
Jika Anda memiliki bidang yang seharusnya hanya memiliki karakter yang sesuai dengan Halaman Kode tertentu dari rangkaian karakter ASCII yang Diperluas, gunakan saja
VARCHAR
.
P.S. Untuk memperjelas hal ini:_SC
yang baru Pengumpulan yang diperkenalkan di SQL Server 2012 memungkinkan untuk:
- fungsi bawaan untuk menangani Karakter Tambahan / Pasangan Pengganti dengan benar, dan
- aturan linguistik untuk Karakter Tambahan yang digunakan untuk mengurutkan dan membandingkan
Tapi, bahkan tanpa _SC
baru Kolasi, Anda masih dapat menyimpan karakter Unicode apa pun ke dalam XML atau N
-tipe awalan, dan mengambilnya tanpa kehilangan data. Namun, saat menggunakan Kolasi yang lebih lama (yaitu tidak ada nomor versi dalam namanya), semua Karakter Tambahan disamakan satu sama lain. Anda harus menggunakan _90
dan _100
Kumpulan yang setidaknya memberi Anda perbandingan dan penyortiran titik biner / kode; mereka tidak dapat memperhitungkan aturan linguistik karena mereka tidak memiliki pemetaan khusus dari Karakter Tambahan (dan karenanya tidak memiliki bobot atau aturan normalisasi).
Coba yang berikut ini:
IF (N'𤪆' = N'𤪆') SELECT N'𤪆' AS [TheLiteral], NCHAR(150150) AS [Generated];
IF (N'𤪆' = N'𤪇') SELECT N'𤪇' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'𤪆' COLLATE Tatar_90_CI_AI = N'𤪇' COLLATE Tatar_90_CI_AI)
SELECT N'𤪇 COLLATE Tatar_90_CI_AI' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'𤪆' = N'?') SELECT N'?';
Dalam DB yang memiliki susunan default yang diakhiri dengan _SC
, hanya IF
pertama pernyataan akan mengembalikan kumpulan hasil, dan bidang "Dihasilkan" akan menampilkan karakter dengan benar.
Tetapi, jika DB tidak memiliki susunan default yang diakhiri dengan _SC
, dan susunannya bukan _90
atau _100
susunan seri, lalu dua IF
yang pertama pernyataan mengembalikan kumpulan hasil di mana bidang "Dihasilkan" akan mengembalikan NULL
, dan bidang "Literal" muncul dengan benar.
Untuk data Unicode, Collation tidak ada hubungannya dengan penyimpanan fisik.
PERBARUI 2018-10-02
Meskipun ini bukan opsi yang layak, SQL Server 2019 memperkenalkan dukungan asli untuk UTF-8 di VARCHAR
/ CHAR
tipe data. Saat ini ada terlalu banyak bug untuk digunakan, tetapi jika sudah diperbaiki, maka ini adalah opsi untuk beberapa skenario. Silakan lihat posting saya, "Dukungan UTF-8 Asli di SQL Server 2019:Juruselamat atau Nabi Palsu?
", untuk analisis mendetail tentang fitur baru ini.