Khó khăn lớn nhất trong việc đưa ra một giải pháp chính xác là trong việc xác định chính xác các ký tự được đưa vào (hoặc loại trừ, hướng nào có ý nghĩa hơn cho hoạt động). Ý nghĩa:
- Chúng ta đang nói về
VARCHAR
dữ liệu / ASCII hoặc NVARCHAR
/ dữ liệu Unicode? Danh sách các ký tự dấu chấm câu cho dữ liệu ASCII phụ thuộc vào Trang mã, lần lượt phụ thuộc vào Đối chiếu. ( trong Câu hỏi này, chúng tôi đang xử lý dữ liệu ASCII ).
- Chúng ta đang đối phó với các tìm kiếm phân biệt chữ hoa chữ thường hay chữ hoa chữ thường?
- Cột đối chiếu là gì? Collation sẽ cho chúng ta biết cả Trang mã và phân biệt chữ hoa chữ thường. ( trong câu hỏi này chúng tôi đang giải quyết
Latin1_General_CI_AS
)
- là một thuật ngữ "dấu chấm câu" có nghĩa là chỉ ký tự dấu chuẩn (ví dụ như
.
, ,
, ;
, :
, vv) hoặc dùng nó có nghĩa là các ký tự không tự chữ và số?
- Là các ký tự khoảng trắng được bao gồm?
- Có bao gồm các ký tự điều khiển không?
- Những gì về ký hiệu tiền tệ như
¢
, £
, ¥
, vv?
- Còn những biểu tượng như
©
và ™
?
- Những nhân vật được coi là "alpha"? Được ký tự không phải tiếng Anh như
Â
, É
, Ñ
, ß
, Þ
bao gồm?
- Vì Câu hỏi này liên quan đến bàn phím của Vương quốc Anh (xem phần thảo luận cho Câu hỏi này), còn ký tự
Æ
/ æ
thì sao?
Để giúp tạo điều kiện rõ ràng về hành vi dự kiến, truy vấn sau đây sẽ hiển thị tất cả 256 ký tự của bộ ký tự Latin1 (ví dụ Mã trang 1252) và cách hai biến thể của giải pháp đề xuất của @ Shaneis hoạt động. Trường đầu tiên (được gắn nhãn là Latin1_General_CI_AS
) hiển thị LIKE
mệnh đề như được đề xuất bởi @Shaneis (khi viết bài này) và trường thứ hai (được gắn nhãn Latin1_General_100_BIN2
) hiển thị một sửa đổi trong đó tôi áp dụng Collation để chỉ định một nhị phân (ví dụ: Collation kết thúc bằng _BIN2
; _BIN
Các bộ sưu tập không được dùng nữa vì vậy đừng sử dụng chúng nếu bạn có quyền truy cập vào các _BIN2
phiên bản), điều đó có nghĩa là tôi cũng cần thêm vào A-Z
phạm vi để lọc các chữ cái viết hoa vì Collation hiện tại không phân biệt chữ hoa chữ thường:
;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;
CẬP NHẬT
Cần phải đề cập rằng NẾU người ta thực sự muốn tìm các ký tự được phân loại là "dấu chấm câu" (và không phải là "ký hiệu tiền tệ", "ký hiệu toán học", v.v.) và NẾU không bị cấm sử dụng SQLCLR / tải một tùy chỉnh hội (SQLCLR đã được giới thiệu với SQL server 2005, và tôi vẫn chưa đi qua một tốt lý do để không cho phép nó, đặc biệt là kể từ khi Azure SQL Database V12 hỗ trợ SAFE
Assemblies), sau đó bạn có thể sử dụng Regular Expressions, nhưng không phải vì lý do đó hầu hết mọi người sẽ đoán.
Thay vì sử dụng Biểu thức chính quy để xây dựng phạm vi ký tự chức năng nhiều hơn hoặc thậm chí thay vì sử dụng một từ như \w
(nghĩa là bất kỳ ký tự "từ" nào), bạn có thể chỉ định Danh mục Unicode của các ký tự bạn muốn lọc và có một số danh mục được xác định :
https: //www.THER-expressions.info/unicode.html#carget
Thậm chí, bạn có thể chỉ định Khối Unicode để lọc, chẳng hạn như "InBengali" hoặc "InDingbats" hoặc "InOptical_Character_Recognition", v.v.
https://www.THER-expressions.info/unicode.html#block
Có rất nhiều ví dụ về việc tạo các hàm RegEx cho SQL Server (mặc dù hầu hết các ví dụ không tuân theo các thực tiễn tốt nhất về SQLCLR) hoặc bạn có thể tải xuống phiên bản miễn phí của thư viện SQL # (mà tôi đã tạo) và sử dụng hàm RegEx_IsMatch vô hướng như sau :
SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)
Các \p{P}
phương tiện biểu hiện \p
= Unicode Thể loại, và {P}
= tất cả các dấu chấm câu (như trái ngược với một loại hình cụ thể của dấu chấm câu, chẳng hạn như "Trình kết nối Punctuation"). VÀ, danh mục "Dấu câu" bao gồm tất cả các dấu câu trên tất cả các ngôn ngữ! Bạn có thể xem danh sách đầy đủ trên trang Unicode.org thông qua liên kết sau (hiện có 717 Điểm Mã trong danh mục đó):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Carget%3DPuncinating%3A%5D
Một phiên bản cập nhật của truy vấn kiểm tra được hiển thị ở trên, bao gồm một trường khác sử dụng SQL # .RegEx_IsMatch với \p{P}
, và kết quả của cả 3 bài kiểm tra trên tất cả 256 ký tự của Mã 1252 (tức là Latin1_General) đã được đăng trên PasteBin.com tại:
Truy vấn và kết quả T-SQL để lọc các loại ký tự
CẬP NHẬT
Sau đây đã được đề cập trong các cuộc thảo luận liên quan:
Bạn đã nói rõ về các ký tự có dấu, với chúng là tên khách sạn từ khắp nơi trên thế giới, sẽ có các ký tự có dấu trong tên, vì vấn đề của tôi, tôi muốn xếp chúng thành các ký tự alpha hợp lệ.
Trong trường hợp này:
Có 11 ký tự không phải tiếng Anh được bao gồm trong bộ ký tự / Trang mã Latin1 không khớp với a-z
phạm vi. Họ là : ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Những thứ này cần phải được thêm vào ký tự đại diện, và mặc dù không cần thiết vào lúc này, nhưng sẽ không hại khi thêm vào A-Z
để mô hình hoạt động tốt như trên đối chiếu phân biệt chữ hoa chữ thường. Kết quả cuối cùng là:
LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Xét rằng dữ liệu này có thể bao gồm "tên khách sạn trên khắp thế giới", tôi sẽ đánh giá cao đề nghị thay đổi kiểu dữ liệu của cột là NVARCHAR
để bạn có thể lưu trữ tất cả các nhân vật từ mọi ngôn ngữ. Giữ điều này là VARCHAR
có nguy cơ mất dữ liệu rất cao vì bạn chỉ có thể đại diện cho các ngôn ngữ gốc Latinh và thậm chí không hoàn toàn cho những ngôn ngữ được cung cấp trong sáu loại Unicode bổ sung cung cấp thêm các ký tự liên quan đến tiếng Latin.