Apakah ada persamaan T-SQL untuk tanda baca karena [0-9] untuk angka dan [az] untuk huruf?


8

Apakah ada T-SQL yang setara dengan [0-9]dan [a-z]pola yang akan membiarkan saya menarik nilai dari kolom yang berisi tanda baca?

Sebagai contoh:

Create Table #Test
(
Value   VarChar(10)
) 
Insert Into #Test
Values ('123a'), ('456b'), ('12ABC'),('AB!23'),('C?D789')

Select      *
From        #Test
Where       Value like '[0-9][0-9][0-9][a-z]'

Ini akan mengembalikan nilai di mana 3 karakter pertama adalah angka antara 0 dan 9 dan karakter terakhir akan menjadi huruf antara a dan z, jadi akan mengembalikan hal-hal seperti 123adan 456btetapi tidak akan mengembalikan nilai 12ABC.

Saya ingin tahu apakah ada yang setara dengan tanda baca seperti [0-9]untuk angka dan [a-z]untuk huruf sehingga akan kembali AB!23dan C?D789?

Jika saya bisa menggunakan ekspresi reguler, saya bisa menggunakan ekspresi ^[a-zA-Z0-9]*$untuk mencocokkan karakter alfanumerik dalam string.

Where       Value like '^[a-zA-Z0-9]*$'

Apakah ada persamaan SQL untuk ini?

Saya tahu hal semacam ini yang dapat dilakukan di RegEx tetapi saya membutuhkannya dalam T-SQL, saya tidak dapat memuat rakitan khusus ke server ini sehingga tidak dapat menggunakan ekspresi reguler.

Kolom sebenarnya adalah varchar (200) . Kolasi adalah Latin1_General_CI_AS. Saya menggunakan SQL Server 2012 Edisi Standar.


Jawaban:


12

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 VARCHARdata / 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 denganLatin1_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 LIKEklausa 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; _BINKolasi sudah tidak digunakan lagi jadi jangan menggunakannya jika Anda memiliki akses ke _BIN2versi) yang berarti saya juga perlu menambahkan A-Zrentang 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 SAFEAssemblies), 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:

  1. Ada 11 karakter non-Inggris yang termasuk dalam set karakter Latin1 / Halaman Kode yang tidak cocok dengan a-zrentang. Mereka adalah: ð Ð Þ þ œ Œ š Š ž Ž Ÿ. Ini perlu ditambahkan ke wildcard, dan sementara tidak perlu saat ini, tidak ada salahnya untuk menambahkan A-Zsehingga pola bekerja dengan baik pada susunan case-sensitive. Hasil akhirnya adalah:
    LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'

  2. Mempertimbangkan bahwa data ini dapat memasukkan "nama hotel dari seluruh dunia", saya sangat merekomendasikan untuk mengubah tipe data kolom NVARCHARsehingga Anda dapat menyimpan semua karakter dari semua bahasa. Menjaga ini sebagai VARCHARmenjalankan 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.


5

Saya mungkin terlalu menyederhanakan ini sedikit tetapi, jika kita mengatakan bahwa tanda baca adalah yang tersisa ketika nilai alfanumerik dihapus, maka berikut ini akan mencari string yang memiliki karakter non-alfanumerik di dalamnya.

Create Table #Test
(
Value   VarChar(10)
) 
Insert Into #Test
Values ('123a'), ('456b'), ('12ABC'),('AB!23'),('C?D789')

-- Original
Select      *
From        #Test
Where       Value like '[0-9][0-9][0-9][a-z]'

-- Non Alpha-numeric
SELECT * FROM #Test WHERE Value LIKE '%[^a-z0-9]%';

DROP TABLE #Test;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.