Kesulitan terbesar dalam mencapai solusi yang tepat adalah dalam menentukan dengan tepat karakter apa yang akan dimasukkan (atau dikecualikan, arah mana pun yang lebih masuk akal untuk operasi). Berarti:
- Apakah kita berbicara tentang
VARCHAR
data / ASCII atau NVARCHAR
/ data Unicode? Daftar karakter tanda baca untuk data ASCII tergantung pada Halaman Kode yang pada gilirannya tergantung pada Collation. ( dalam Pertanyaan ini kita berurusan dengan data ASCII ).
- Apakah kita berurusan dengan pencarian case-sensitive atau case-sensitive?
- Untuk apa Collation diatur? Collation akan memberi tahu kami baik Halaman Kode dan sensitivitas kasus. ( dalam pertanyaan ini kita berurusan dengan
Latin1_General_CI_AS
)
- adalah istilah "tanda baca" berarti hanya standar karakter tanda baca (misalnya
.
, ,
, ;
, :
, dll) atau apakah itu karakter non-alfanumerik berarti?
- Apakah karakter spasi putih disertakan?
- Apakah karakter Kontrol termasuk?
- Bagaimana simbol mata uang seperti
¢
, £
, ¥
, dll?
- Bagaimana dengan simbol seperti
©
dan ™
?
- Karakter apa yang dianggap "alpha"? Apakah karakter non-Inggris seperti
Â
, É
, Ñ
, ß
, Þ
disertakan?
- Sejak Pertanyaan ini berkaitan dengan keyboard UK (lihat diskusi untuk pertanyaan ini), bagaimana dengan
Æ
/ æ
karakter?
Untuk membantu memfasilitasi kejelasan mengenai perilaku yang diharapkan, permintaan berikut akan menampilkan semua 256 karakter dari set karakter Latin1 (yaitu Kode Page 1252) dan bagaimana dua variasi dari solusi yang diusulkan @ Shaneis beroperasi. Kolom pertama (diberi label sebagai Latin1_General_CI_AS
) menunjukkan LIKE
klausa seperti yang diusulkan oleh @Shaneis (pada tulisan ini) dan kolom kedua (diberi label sebagai Latin1_General_100_BIN2
) menunjukkan modifikasi di mana saya mengesampingkan Collation untuk menentukan yang biner (yaitu Collation yang diakhiri dengan _BIN2
; _BIN
Kolasi sudah tidak digunakan lagi jadi jangan menggunakannya jika Anda memiliki akses ke _BIN2
versi) yang berarti saya juga perlu menambahkan A-Z
rentang untuk menyaring huruf besar karena Kolasi saat ini tidak peka terhadap huruf besar-kecil:
;WITH nums AS
(
SELECT TOP (256) (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) AS [Decimal]
FROM [master].[sys].[all_objects]
)
SELECT nm.[Decimal],
CHAR(nm.[Decimal]) AS [Character],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9]%'
THEN 'x' ELSE '' END AS [Latin1_General_CI_AS],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9A-Z]%' COLLATE Latin1_General_100_BIN2
THEN 'x' ELSE '' END AS [Latin1_General_100_BIN2]
FROM nums nm;
MEMPERBARUI
Harus disebutkan bahwa JIKA seseorang benar-benar mencari untuk menemukan karakter yang diklasifikasikan sebagai "tanda baca" (dan bukan "simbol mata uang", "simbol matematika", dll), dan JIKA seseorang tidak dilarang menggunakan SQLCLR / memuat kebiasaan Assembly (SQLCLR diperkenalkan dengan SQL Server 2005, dan saya belum menemukan alasan yang bagus untuk tidak mengizinkannya, terutama karena Azure SQL Database V12 mendukung SAFE
Assemblies), maka Anda dapat menggunakan Ekspresi Reguler, tetapi bukan karena kebanyakan orang akan menebak.
Daripada menggunakan Ekspresi Reguler untuk membangun rentang karakter yang lebih fungsional, atau bahkan daripada menggunakan sesuatu seperti \w
(artinya karakter "kata"), Anda dapat menentukan Kategori Unicode dari karakter yang ingin Anda filter, dan ada beberapa kategori yang ditentukan :
https://www.regular-expressions.info/unicode.html#category
Anda bahkan dapat menentukan Blok Unicode untuk difilter, seperti "InBengali" atau "InDingbats" atau "InOptical_Character_Recognition", dll:
https://www.regular-expressions.info/unicode.html#block
Ada banyak contoh membuat fungsi RegEx untuk SQL Server (meskipun kebanyakan contoh tidak mengikuti praktik terbaik SQLCLR), atau Anda dapat mengunduh versi gratis dari pustaka SQL # (yang saya buat), dan menggunakan fungsi skalar RegEx_IsMatch sebagai berikut :
SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)
The \p{P}
ekspresi berarti \p
= Unicode Kategori, dan {P}
= semua tanda baca (sebagai lawan jenis tertentu tanda baca, seperti "Connector Tanda baca"). DAN, kategori "Tanda Baca" mencakup semua tanda baca di semua bahasa! Anda dapat melihat daftar lengkap di situs Unicode.org melalui tautan berikut (saat ini ada 717 Poin Kode dalam kategori itu):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D
Versi terbaru dari kueri pengujian yang ditunjukkan di atas, termasuk bidang lain yang menggunakan SQL # .RegEx_IsMatch dengan \p{P}
, dan hasil dari semua 3 tes di semua 256 karakter Kode Page 1252 (yaitu Latin1_General) telah diposting di PasteBin.com di:
T-SQL query dan hasil untuk memfilter jenis karakter
PEMBARUAN
Berikut ini disebutkan dalam diskusi terkait:
Anda telah membuat poin bagus tentang karakter beraksen, dengan mereka menjadi nama hotel dari seluruh dunia akan ada karakter beraksen dalam nama, untuk masalah saya, saya ingin mengklasifikasikan ini sebagai karakter alpha yang valid.
Pada kasus ini:
Ada 11 karakter non-Inggris yang termasuk dalam set karakter Latin1 / Halaman Kode yang tidak cocok dengan a-z
rentang. Mereka adalah: ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Ini perlu ditambahkan ke wildcard, dan sementara tidak perlu saat ini, tidak ada salahnya untuk menambahkan A-Z
sehingga pola bekerja dengan baik pada susunan case-sensitive. Hasil akhirnya adalah:
LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Mempertimbangkan bahwa data ini dapat memasukkan "nama hotel dari seluruh dunia", saya sangat merekomendasikan untuk mengubah tipe data kolom NVARCHAR
sehingga Anda dapat menyimpan semua karakter dari semua bahasa. Menjaga ini sebagai VARCHAR
menjalankan risiko yang sangat tinggi pada akhirnya kehilangan data karena Anda hanya dapat mewakili bahasa berbasis Latin, dan bahkan tidak sepenuhnya untuk mereka yang diberi enam kategori Unicode tambahan yang menyediakan karakter terkait Latin tambahan.