Làm cách nào tôi có thể tìm kiếm (không phân biệt chữ hoa chữ thường) trong một cột bằng cách sử dụng ký tự đại diện THÍCH?


289

Tôi nhìn xung quanh một số và không tìm thấy những gì tôi đã sau khi ở đây đi.

SELECT * FROM trees WHERE trees.`title` LIKE  '%elm%'

Điều này hoạt động tốt, nhưng không phải nếu cây được đặt tên là Elm hoặc ELM, v.v ...

Làm cách nào để làm cho trường hợp SQL không nhạy cảm với tìm kiếm thẻ hoang dã này?

Tôi đang sử dụng MySQL 5 và Apache.


3
Nếu bạn tình cờ trên trang này nhưng thiết lập MySql của bạn DO làm việc trên truy vấn này cho Elm hoặc ELM và bạn muốn nó được trường hợp nhạy cảm, xem BINARYnhư đây: stackoverflow.com/questions/7857669/...
joshuahedlund

Nó không phụ thuộc vào đối chiếu trường / bảng sao? như 'ut8_general_CI'
Yousha Aleayoub

Làm thế nào để sử dụng nó tuần tự hóa truy vấn nút?
Ashh

likeTheo mặc định, MySQL không phân biệt chữ hoa chữ thường.
Marko Bonaci

Câu trả lời:


281
SELECT  *
FROM    trees
WHERE   trees.`title` COLLATE UTF8_GENERAL_CI LIKE '%elm%'

Trên thực tế, nếu bạn thêm COLLATE UTF8_GENERAL_CIvào định nghĩa của cột, bạn có thể bỏ qua tất cả các thủ thuật sau: nó sẽ hoạt động tự động.

ALTER TABLE trees 
 MODIFY COLUMN title VARCHAR(…) CHARACTER 
 SET UTF8 COLLATE UTF8_GENERAL_CI. 

Điều này cũng sẽ xây dựng lại bất kỳ chỉ mục nào trên cột này để chúng có thể được sử dụng cho các truy vấn mà không dẫn đến '%'


34
Trên thực tế, nếu bạn thêm COLLATE UTF8_GENERAL_CIvào định nghĩa của cột, bạn có thể bỏ qua tất cả các thủ thuật sau: nó sẽ hoạt động tự động. ALTER TABLE trees MODIFY COLUMN title VARCHAR(…) CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI. Điều này cũng sẽ xây dựng lại bất kỳ chỉ mục nào trên cột này để chúng có thể được sử dụng cho các truy vấn mà không dẫn '%'.
Quassnoi

1
ALTER TABLE cây MODIFY COLUMN title VARCHAR (Tập) đây có vẻ là cách tốt nhất, cảm ơn nhiều ... hãy để sql thực hiện công việc
David Morrow

10
Nhắc nhở thân thiện rằng đây là một câu trả lời mysql. Nếu bạn đang sử dụng PostgreSQL, ILike là giải pháp cho câu hỏi trên.
Steve

2
@RajanRawal: vui lòng gửi câu hỏi của bạn dưới dạng câu hỏi, không phải bình luận. Cảm ơn.
Quassnoi

1
Đây là câu trả lời đúng miễn là đối chiếu ban đầu của bạn là chung chứ không phải bin.
greenoldman

261

Tôi đã luôn giải quyết vấn đề này bằng cách sử dụng thấp hơn:

SELECT * FROM trees WHERE LOWER( trees.title ) LIKE  '%elm%'

47
và sử dụng chỉ số chiến lợi phẩm
Ý thức chung của bạn

3
MySQL 5 có toán tử ILIKE không?
Luke Maurer

27
mặc dù đối với tìm kiếm %% dù sao nó cũng không thành vấn đề :)
Ý thức chung của bạn vào

5
@Col. - Phải thừa nhận rằng, điều này ít hơn lý tưởng cho các cột được lập chỉ mục, nhưng nó sẽ hoạt động cho một cấu trúc đã có sẵn. Tôi cũng thấy rằng các tìm kiếm không phân biệt chữ hoa chữ thường xuất hiện trên các cột không được lập chỉ mục.
cwallenpoole

1
Đối chiếu mặc định đã là CI. Vì vậy, vấn đề thực sự không có trong câu hỏi cụ thể này. Nhưng đó vẫn là câu trả lời kiểu SO hoàn hảo.
Ý thức chung của bạn

48

Độ nhạy trường hợp được xác định trong cài đặt đối chiếu cột / bảng / cơ sở dữ liệu. Bạn có thể thực hiện truy vấn theo đối chiếu cụ thể theo cách sau:

SELECT *
FROM trees
WHERE trees.`title` LIKE '%elm%' COLLATE utf8_general_ci

ví dụ.

(Thay thế utf8_general_cibằng bất kỳ đối chiếu nào bạn thấy hữu ích). Các _cichữ viết tắt của trường hợp không nhạy cảm .


1
Trong MySQL 5.6 tôi nhận được ERROR 1273 (HY000): Đối chiếu không xác định: 'utf_general_ci' . Tôi đoán phần đối chiếu này đã bị xóa khỏi MySQL? utf8_general_cihoạt động tốt, mặc dù.
Đánh dấu Amery

1
Có cùng một vấn đề. Bạn phải sửa COLLATEhoặc thực hiện một mẹo đơn giản như thế này ( LOWER()cả hai chuỗi của bạn trước khi so sánh)
Menelaos Kotsollaris

Trong MySQL 5.6+ hoặc MariaDB 10+, bạn chỉ cần cung cấp hướng dẫn THU THẬP trước điều kiện của mình. Vì vậy, điều này hoạt động:SELECT * FROM products WHERE name COLLATE utf8_general_ci LIKE 'AB47TU';
stamster

41

Đây là ví dụ về một truy vấn THÍCH đơn giản:

SELECT * FROM <table> WHERE <key> LIKE '%<searchpattern>%'

Bây giờ, không phân biệt chữ hoa chữ thường bằng cách sử dụng LOWER () func:

SELECT * FROM <table> WHERE LOWER(<key>) LIKE LOWER('%<searchpattern>%')

3
Trên thực tế đây là một giải pháp khá hay, đặc biệt là khi bạn phải đối mặt với COLLATEcác vấn đề về định dạng
Menelaos Kotsollaris

27

Đơn giản chỉ cần sử dụng:

"SELECT * FROM `trees` WHERE LOWER(trees.`title`) LIKE  '%elm%'";

Hoặc dùng

"SELECT * FROM `trees` WHERE LCASE(trees.`title`) LIKE  '%elm%'";

Cả hai chức năng hoạt động như nhau


15

Tôi đang làm một cái gì đó như thế.

Lấy các giá trị bằng chữ thường và MySQL làm phần còn lại

    $string = $_GET['string'];
    mysqli_query($con,"SELECT *
                       FROM table_name
                       WHERE LOWER(column_name)
                       LIKE LOWER('%$string%')");

Và đối với thay thế PDO của MySQL:

        $string = $_GET['string'];
        $q = "SELECT *
              FROM table_name
              WHERE LOWER(column_name)
              LIKE LOWER(?);";
        $query = $dbConnection->prepare($q);
        $query->bindValue(1, "%$string%", PDO::PARAM_STR);
        $query->execute();

6

Tôi nghĩ rằng truy vấn này sẽ thực hiện một tìm kiếm không nhạy cảm trường hợp:

SELECT * FROM trees WHERE trees.`title` ILIKE '%elm%';

1
Tôi gặp lỗi cú pháp trên mysql 5.5 trong khi sử dụng ILIKE trong các truy vấn của mình
Steel Brain

18
Điều này chỉ hoạt động cho PostgreSQL; không phải MySQL. postgresql.org/docs/civerse/static/fifts-matching.html
Martin Tournoij

Như đã lưu ý, câu hỏi là về MySQL và câu trả lời là về PostgreSQL và chắc chắn rằng địa ngục không hoạt động với MySQL. Tôi không bỏ phiếu nhưng không thể tự hỏi số phiếu tăng đến từ đâu ...
silverdr

5

sử dụng ILIKE

SELECT * FROM trees WHERE trees.`title` ILIKE '%elm%';

nó làm việc cho tôi !!


9
MySQL không hỗ trợ ILIKE.
ttarchala

3
Điều đó làm việc cho PostgreSQL, câu hỏi liên quan đến MySQL.
Telmo Trooper

4

Bạn không cần đến ALTERbất kỳ bảng nào. Chỉ cần sử dụng các truy vấn sau, trước SELECTtruy vấn thực tế mà bạn muốn sử dụng ký tự đại diện:

    set names `utf8`;
    SET COLLATION_CONNECTION=utf8_general_ci;
    SET CHARACTER_SET_CLIENT=utf8;
    SET CHARACTER_SET_RESULTS=utf8;

2
Đây là một nhận xét rất bị đánh giá thấp. Nó giải quyết câu hỏi nói chung nhất. Tôi nghĩ rằng cú pháp bảng thay đổi cũng quan trọng, vì câu hỏi có thể muốn so sánh chỉ giới hạn trong một cột đó.
Brian Chrisman

1

tốt trong mysql 5.5, giống như toán tử không nhạy cảm ... vì vậy nếu vale của bạn là elm hoặc ELM hoặc Elm hoặc eLM hoặc bất kỳ loại nào khác, và bạn sử dụng như '% elm%', nó sẽ liệt kê tất cả các giá trị khớp.

Tôi không thể nói về các phiên bản trước của mysql.

Nếu bạn vào Oracle, thích làm việc theo phân biệt chữ hoa chữ thường, vì vậy nếu bạn gõ như '% elm%', nó sẽ chỉ dành cho việc này và bỏ qua chữ hoa ..

Lạ thật, nhưng đây là như thế :)


Điều này không hoàn toàn đúng. Nó hoạt động theo cách đó chỉ khi đối chiếu được đặt thành *_ci, viết tắt của "trường hợp không nhạy cảm". Vì điều này xảy ra là mặc định cho tất cả các bộ ký tự được hỗ trợ (vấn đề show character set;cần kiểm tra điều này) - câu trả lời là đúng một phần :-) Chỉ có lý do là không chính xác. Nó không phải là toán tử không phân biệt chữ hoa chữ thường, nó là đối chiếu mặc định.
silverdr

vâng tôi đồng ý với bạn Nó phụ thuộc vào ký tự và nếu bạn đang sản xuất với ký tự * _ci thì chỉ có tùy chọn là sử dụng nhị phân trước mệnh đề
where


0

Bạn phải thiết lập mã hóa và đối chiếu thích hợp cho các bảng của mình.

Bảng mã phải phản ánh mã hóa dữ liệu thực tế. Mã hóa dữ liệu của bạn là gì?

Để xem bảng mã, bạn có thể chạy truy vấn SHOW CREATE TABLE tablename


0

Khi tôi muốn phát triển các tìm kiếm trường hợp không nhạy cảm, tôi luôn chuyển đổi mọi chuỗi thành chữ thường trước khi so sánh


0

Bạn có thể sử dụng phương pháp sau

 private function generateStringCondition($value = '',$field = '', $operator = '', $regex = '', $wildcardStart = '', $wildcardEnd = ''){
        if($value != ''){
            $where = " $field $regex '$wildcardStart".strtolower($value)."$wildcardEnd' ";

            $searchArray = explode(' ', $value);

            if(sizeof($searchArray) > 1){

                foreach ($searchArray as $key=>$value){
                    $where .="$operator $field $regex '$wildcardStart".strtolower($value)."$wildcardEnd'";
                }

            }

        }else{
            $where = '';
        }
        return $where;
    }

sử dụng phương pháp này như dưới đây

   $where =  $this->generateStringCondition($yourSearchString,  'LOWER(columnName)','or', 'like',  '%', '%');
  $sql = "select * from table $where";

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.