Có một T-SQL tương đương với dấu chấm câu vì [0-9] dành cho số và [az] dành cho chữ cái không?


8

Có một T-SQL tương đương với các mẫu [0-9][a-z]sẽ cho phép tôi kéo các giá trị từ một cột có dấu chấm câu không?

Ví dụ:

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]'

Điều này sẽ trả về các giá trị trong đó 3 ký tự đầu tiên là các số từ 0 đến 9 và ký tự cuối cùng sẽ là một chữ cái giữa a và z, do đó sẽ trả về những thứ như 123a456bsẽ không trả về giá trị 12ABC.

Tôi muốn biết nếu có một dấu chấm tương đương như [0-9]là cho các số và [a-z]là cho các chữ cái để nó trở lại AB!23C?D789?

Nếu tôi có thể sử dụng biểu thức chính quy, tôi có thể sử dụng biểu thức ^[a-zA-Z0-9]*$để khớp các ký tự chữ và số trong một chuỗi.

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

Có một SQL tương đương cho điều này?

Tôi biết loại điều này có thể được thực hiện trong RegEx nhưng tôi cần nó trong T-SQL, tôi không thể tải bất kỳ tập hợp tùy chỉnh nào lên máy chủ này vì vậy không thể sử dụng các biểu thức thông thường.

Cột thực là varchar (200) . Đối chiếu là Latin1_General_CI_AS. Tôi đang sử dụng SQL Server 2012 Standard Edition.


Câu trả lời:


12

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ề VARCHARdữ 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ếtLatin1_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ư ©?
  • 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ị LIKEmệ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; _BINCá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 _BIN2phiên bản), điều đó có nghĩa là tôi cũng cần thêm vào A-Zphạ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ợ SAFEAssemblies), 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:

  1. 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-zphạ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ðÐÞþœŒšŠžŽŸ]%'

  2. 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à VARCHARcó 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.


5

Tôi có thể đơn giản hóa điều này một chút nhưng, nếu chúng ta nói rằng dấu câu là tất cả những gì còn lại khi loại bỏ các giá trị chữ và số, thì phần sau đây sẽ tìm kiếm các chuỗi có các ký tự không phải là chữ và số.

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.