Làm cách nào tôi có thể tìm thấy các ký tự không phải ASCII trong MySQL?


124

Tôi đang làm việc với cơ sở dữ liệu MySQL có một số dữ liệu được nhập từ Excel . Dữ liệu chứa các ký tự không phải ASCII (dấu gạch ngang, v.v.) cũng như trả về vận chuyển ẩn hoặc nguồn cấp dữ liệu dòng. Có cách nào để tìm những bản ghi này bằng MySQL không?


8
Ollie Jones có câu trả lời tốt hơn nhiều (kiểm tra phía dưới).
Jonathan Arkell

1
@JonathanArkell Không ở dưới đáy nữa :)
Brilliand

Sửa chữa .. kiểm tra giữa! ;)
Jonathan Arkell

Đây là câu trả lời @Jonathan đang nói về stackoverflow.com/a/11741314/792066
Braiam

Câu trả lời:


64

Nó phụ thuộc chính xác những gì bạn đang xác định là "ASCII", nhưng tôi khuyên bạn nên thử một biến thể của truy vấn như thế này:

SELECT * FROM tableName WHERE columnToCheck NOT REGEXP '[A-Za-z0-9]';

Truy vấn đó sẽ trả về tất cả các hàng trong đó cộtToCheck chứa bất kỳ ký tự không chữ và số nào. Nếu bạn có các ký tự khác được chấp nhận, hãy thêm chúng vào lớp ký tự trong biểu thức chính quy. Ví dụ: nếu dấu chấm, dấu phẩy và dấu gạch nối là OK, hãy thay đổi truy vấn thành:

SELECT * FROM tableName WHERE columnToCheck NOT REGEXP '[A-Za-z0-9.,-]';

Trang có liên quan nhất của tài liệu MySQL có lẽ là 12.5.2 Biểu thức chính quy .


3
Bạn không nên thoát khỏi dấu gạch nối và thời gian? .
Tooony

3
@Tooony Không, bên trong một tập hợp, một khoảng thời gian chỉ có nghĩa là chính nó và dấu gạch ngang chỉ có ý nghĩa đặc biệt giữa các nhân vật khác. Vào cuối tập hợp, nó chỉ có nghĩa là chính nó.
Michael Speer

10
Truy vấn này chỉ tìm thấy tất cả các dòng trong tên bảng không chứa ký tự chữ và số. Điều này không trả lời câu hỏi.
Rob Bailey

8
Đó là đối với các cột không có bất kỳ ký tự ascii nào, vì vậy nó sẽ bỏ lỡ các cột có kết hợp các ký tự ascii và không ascii. Câu trả lời dưới đây từ zende kiểm tra một hoặc nhiều ký tự không phải mã ascii. Điều này đã giúp tôi phần lớnSELECT * FROM tbl WHERE colname NOT REGEXP '^[A-Za-z0-9\.,@&\(\) \-]*$';
Frank Forte

1
Điều này chỉ hoạt động (đối với tôi dù thế nào) để tìm các chuỗi có chứa KHÔNG của các ký tự đó. Nó không tìm thấy các chuỗi chứa hỗn hợp các ký tự ASCII và không phải ASCII.
Ian

236

MySQL cung cấp quản lý bộ ký tự toàn diện có thể giúp giải quyết vấn đề này.

SELECT whatever
  FROM tableName 
 WHERE columnToCheck <> CONVERT(columnToCheck USING ASCII)

Các CONVERT(col USING charset)chức năng biến những nhân vật unconvertable vào nhân vật thay thế. Sau đó, văn bản được chuyển đổi và không chuyển đổi sẽ không đồng đều.

Xem điều này để thảo luận thêm. https://dev.mysql.com/doc/refman/8.0/en/charset-repertoire.html

Bạn có thể sử dụng bất kỳ tên bộ ký tự nào bạn muốn thay cho ASCII. Ví dụ: nếu bạn muốn tìm ra ký tự nào sẽ không hiển thị chính xác trong trang mã 1257 (tiếng Litva, tiếng Latvia, tiếng Estonia) sử dụngCONVERT(columnToCheck USING cp1257)


20
Đây là một giải pháp tuyệt vời cho vấn đề này và mạnh mẽ hơn nhiều.
CraigDoumund

5
điều này cũng hữu ích để tìm các ký tự có dấu (á ä v.v.) hoặc ký tự không thuộc về mã hóa
Graffitinost

3
tốt hơn nhiều so với việc sử dụng REGEXP (dường như không hiệu quả đối với tôi trong việc tìm kiếm điểm nhấn) và cũng cung cấp một cơ chế đơn giản để làm mọi thứ trở lại ...
Dirk Conrad Coetsee

1
Câu trả lời này hoạt động tuyệt vời và sẽ đưa ra các chuỗi có chứa bất kỳ ký tự không phải ASCII nào thay vì chỉ các chuỗi chỉ chứa các ký tự không phải ASCII. Cảm ơn bạn!
Ian

2
Giải pháp nổi bật!
Chó điên Tannen

93

Bạn có thể định nghĩa ASCII là tất cả các ký tự có giá trị thập phân là 0 - 127 (0x00 - 0x7F) và tìm các cột có các ký tự không phải ASCII bằng truy vấn sau

SELECT * FROM TABLE WHERE NOT HEX(COLUMN) REGEXP '^([0-7][0-9A-F])*$';

Đây là truy vấn toàn diện nhất mà tôi có thể đưa ra.


3
Câu trả lời hay nhất cho đến nay, nhưng thậm chí còn dễ hơn như thế này:SELECT * FROM table WHERE LENGTH( column ) != CHAR_LENGTH( column )
SuN

15
-1 Điều này có thể mang lại kết quả sai lầm. Ví dụ, giả sử rằng người ta có cột UTF-16 chứa 'ā'(được mã hóa bởi chuỗi byte 0x0101) - nó sẽ được coi là "ASCII" khi sử dụng thử nghiệm này: âm tính giả ; thật vậy, một số bộ ký tự không mã hóa các ký tự ASCII trong đó 0x00cho đến 0x7fkhi giải pháp này mang lại kết quả dương tính giả. KHÔNG LIÊN QUAN ĐẾN TRẢ LỜI NÀY!
eggyal

2
@sun: Điều đó không giúp ích gì cả - nhiều bộ ký tự có độ dài cố định và do đó LENGTH(column)sẽ là bội số không đổi CHAR_LENGTH(column)bất kể giá trị.
eggyal

49

Đây có lẽ là những gì bạn đang tìm kiếm:

select * from TABLE where COLUMN regexp '[^ -~]';

Nó sẽ trả về tất cả các hàng trong đó COLUMN chứa các ký tự không phải ASCII (hoặc các ký tự ASCII không in được như dòng mới).


7
Làm việc tuyệt vời cho tôi. "regrec '[^ - ~]'" có nghĩa là có một ký tự đứng trước dấu cách "" hoặc sau "~" hoặc ASCII 32 - 126. Tất cả các chữ cái, số và ký hiệu, nhưng không có những thứ không thể in được.
Josh

Bạn thậm chí có thể lấy nó làm áo phông;) catonmat.net/blog/my-favorite-regex
Samoody

1
Lưu ý cảnh báo trong tài liệu : " Các toán tử REGEXPRLIKEtoán tử hoạt động theo kiểu byte khôn ngoan, vì vậy chúng không an toàn nhiều byte và có thể tạo ra kết quả không mong muốn với các bộ ký tự nhiều byte. Ngoài ra, các toán tử này so sánh các ký tự theo các giá trị byte của chúng và các ký tự có dấu có thể không so sánh như nhau ngay cả khi một đối chiếu nhất định coi chúng là bằng nhau. "
eggyal

1
cảm ơn vì điều đó. điều tôi băn khoăn là làm thế nào để thay thế một nhân vật thay thế - ví dụ:
mars-o

1
@ mars-o - viên kim cương đen biểu thị ký tự utf8 không hợp lệ. Thảo luận thêm ở đây
Rick James

14

Một ký tự bị thiếu trong các ví dụ của mọi người ở trên là ký tự kết thúc (\ 0). Điều này là vô hình đối với đầu ra của bảng điều khiển MySQL và không thể tìm thấy bởi bất kỳ truy vấn nào được đề cập ở đây. Truy vấn để tìm nó chỉ đơn giản là:

select * from TABLE where COLUMN like '%\0%';

4

Dựa trên câu trả lời đúng, nhưng cũng tính đến các ký tự điều khiển ASCII, giải pháp hiệu quả với tôi là:

SELECT * FROM `table` WHERE NOT `field` REGEXP  "[\\x00-\\xFF]|^$";

Nó cũng làm điều tương tự: tìm kiếm các vi phạm phạm vi ASCII trong một cột, nhưng cũng cho phép bạn tìm kiếm các ký tự điều khiển, vì nó sử dụng ký hiệu thập lục phân cho các điểm mã. Vì không có so sánh hoặc chuyển đổi (không giống như câu trả lời của @ Ollie), nên điều này cũng nhanh hơn đáng kể. (Đặc biệt là nếu MySQL không kết thúc sớm trên truy vấn regex, điều này chắc chắn nên.)

Nó cũng tránh các trường trả về có độ dài bằng không. Nếu bạn muốn một phiên bản dài hơn một chút có thể hoạt động tốt hơn, bạn có thể sử dụng phiên bản này thay thế:

SELECT * FROM `table` WHERE `field` <> "" AND NOT `field` REGEXP  "[\\x00-\\xFF]";

Nó thực hiện một kiểm tra riêng về độ dài để tránh kết quả có độ dài bằng không, mà không xem xét chúng cho vượt qua regex. Tùy thuộc vào số lượng mục nhập có độ dài bằng không bạn có, mục này có thể nhanh hơn đáng kể.

Lưu ý rằng nếu bộ ký tự mặc định của bạn là thứ gì đó kỳ quái trong đó 0x00-0xFF không ánh xạ tới các giá trị giống như ASCII (có một bộ ký tự như vậy tồn tại ở bất cứ đâu không?), Điều này sẽ trả về kết quả dương tính giả. Nếu không, hãy tận hưởng!


1
00-FF bao gồm tất cả các giá trị 8 bit có thể, đó là những gì REGEXPđang kiểm tra. Do đó nó được đảm bảo để luôn luôn phù hợp. Cũng ^$có thể không phải là những gì bạn muốn.
Rick James

Chắc chắn là giải pháp REGEXP tốt nhất để tìm tất cả các ký tự 8 bit nhưng không tốt bằng giải pháp CONVERT (col USING charset) cũng sẽ cho phép điều khiển các ký tự trong khi giới hạn các ký tự hiển thị trong một bảng mã cụ thể.
Ian

1

Thử sử dụng truy vấn này để tìm kiếm các bản ghi ký tự đặc biệt

SELECT *
FROM tableName
WHERE fieldName REGEXP '[^a-zA-Z0-9@:. \'\-`,\&]'

0

Câu trả lời của @ zende là câu duy nhất bao gồm các cột có sự pha trộn của các ký tự ascii và non ascii, nhưng nó cũng có điều hex có vấn đề. Tôi đã sử dụng điều này:

SELECT * FROM `table` WHERE NOT `column` REGEXP '^[ -~]+$' AND `column` !=''

0

Trong Oracle chúng ta có thể sử dụng dưới đây.

SELECT * FROM TABLE_A WHERE ASCIISTR(COLUMN_A) <> COLUMN_A;

-2

Đối với câu hỏi này, chúng tôi cũng có thể sử dụng phương pháp này:

Câu hỏi từ sở thú sql:
Tìm tất cả các chi tiết về giải thưởng giành được bởi PETER GRÜNBERG

Các ký tự không phải ASCII

ans: chọn * từ nobel nơi người chiến thắng như'P% GR% _% berg ';


1
Đâu là mối liên hệ với câu hỏi?
Nico Haase
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.