Làm cách nào để đặt Sqlite3 không phân biệt chữ hoa chữ thường khi so sánh chuỗi?


305

Tôi muốn chọn các bản ghi từ cơ sở dữ liệu sqlite3 bằng cách khớp chuỗi. Nhưng nếu tôi sử dụng '=' trong mệnh đề where, tôi thấy rằng sqlite3 phân biệt chữ hoa chữ thường. Bất cứ ai có thể cho tôi biết làm thế nào để sử dụng chuỗi so sánh không phân biệt chữ hoa chữ thường?

Câu trả lời:


493

Bạn có thể dùng COLLATE NOCASE trong SELECTtruy vấn của mình :

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

Ngoài ra, trong SQLite, bạn có thể chỉ ra rằng một cột không phân biệt chữ hoa chữ thường khi bạn tạo bảng bằng cách chỉ định collate nocasetrong định nghĩa cột (các tùy chọn khác là binary(mặc định) vàrtrim ; xem tại đây ). Bạn có thể chỉ địnhcollate nocase khi bạn tạo một chỉ mục là tốt. Ví dụ:

tạo bảng thử nghiệm
(
  Text_Value văn bản đối chiếu nocase
);

chèn vào các giá trị Kiểm tra ('A');
chèn vào các giá trị thử nghiệm ('b');
chèn vào các giá trị thử nghiệm ('C');

tạo chỉ mục Test_Text_Value_Index
  trong bài kiểm tra (Text_Value collate nocase);

Biểu hiện liên quan Test.Text_Valuenên bây giờ không nhạy cảm trường hợp. Ví dụ:

sqlite> chọn Text_Value từ Kiểm tra trong đó Text_Value = 'B';
Text_Value      
----------------
b               

sqlite> chọn Text_Value từ Thứ tự kiểm tra của Text_Value;
Text_Value      
----------------
Một               
b               
C    

sqlite> chọn Text_Value từ Thứ tự kiểm tra của Text_Value desc;
Text_Value      
----------------
C               
b               
Một               

Trình tối ưu hóa cũng có khả năng sử dụng chỉ mục cho tìm kiếm và kết hợp không phân biệt chữ hoa chữ thường trên cột. Bạn có thể kiểm tra điều này bằng explainlệnh SQL, vd:

sqlite> giải thích chọn Text_Value từ Test trong đó Text_Value = 'b';
addr opcode p1 p2 p3                               
---------------- -------------- ---------- ---------- ---------------------------------
0 đi 0 16                                           
1 số nguyên 0 0                                            
2 OpenRead 1 3 keyinfo (1, NOCASE)                
3 SetNumColumn 1 2                                            
4 Chuỗi8 0 0 b                                
5 Không có -1 -1                                           
6 MakeRecord 1 0 a                                
7 MemStore 0 0                                            
8 Di chuyểnGe 1 14                                           
9 Tải 0 0                                            
10 IdxGE 1 14 +                                
11 Cột 1 0                                            
12 Gọi lại 1 0                                            
13 Tiếp theo 1 9                                            
14 Đóng 1 0                                            
15 Dừng 0 0                                            
16 Giao dịch 0 0                                            
17 ConfirmCookie 0 4                                            
18 Goto 0 1                                            
19 giờ 0 0                                            

20
Sau khi (lại) tạo bảng với 'đối chiếu NOCASE', tôi nhận thấy đó là nhiều nhanh hơn so với truy vấn WHERE name = 'ai đó' đối chiếu NOCASE. NHIỀU nhanh hơn (sáu đến 10 lần, khoảng?)
DefenestrationDay

10
Theo tài liệu, COLLATE NOCASEkhông cần thêm vào chỉ mục nếu trường đã có đối chiếu này được xác định: " Trình tự đối chiếu mặc định là trình tự đối chiếu được xác định cho cột đó trong câu lệnh CREATE TABLE. "
Heinzi

29
COLLATE NOCASEsẽ chỉ hoạt động với văn bản ASCII. Khi bạn có "FIANCÉ" hoặc "voilà" trong các giá trị cột của mình, nó sẽ không khớp với "vị hôn phu" hoặc "VOILA". Sau khi kích hoạt tiện ích mở rộng ICU, LIKEtrở nên không phân biệt chữ hoa chữ thường , như vậy 'FIANCÉ' LIKE 'fiancé'là đúng, nhưng 'VOILA' LIKE 'voilà'vẫn là sai. Và ICU + THÍCH có nhược điểm là không sử dụng chỉ mục, do đó, nó có thể bị chậm trên các bảng lớn.

chọn div, trường hợp khi div = 'fail' rồi 'FAIL' khác 'PASSED' kết thúc, * từ các dấu đối chiếu nocase ở trên không làm việc tôi có làm gì sai không?
Sấm

7
Một điều cần lưu ý rằng đã làm tôi vấp ngã: select * from tbl where firstname='john' and lastname='doe' COLLATE NOCASEsẽ không nhạy cảm lastname. Để được trường hợp không nhạy cảm firstname, viết này : select * from tbl where firstname='john' COLLATE NOCASE and lastname='doe'. Nó cụ thể cho một cột đó, không phải toàn bộ wheremệnh đề.
James Toomey

148
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

5
Nếu bạn giống tôi và muốn có thêm tài liệu về Collating, bạn có thể tìm thấy nó ở đây trên trang này: sqlite.org/datatype3.html Chỉ cần cuộn xuống # 6.0
Will

47

Bạn có thể làm như thế này:

SELECT * FROM ... WHERE name LIKE 'someone'

(Đây không phải giải pháp, nhưng trong một số trường hợp rất thuận tiện)

" Toán tử THÍCH thực hiện so sánh khớp mẫu. Toán hạng bên phải chứa mẫu, toán hạng bên trái chứa chuỗi khớp với mẫu. Biểu tượng phần trăm ("% ") trong mẫu khớp với bất kỳ chuỗi nào từ 0 trở lên . ký tự trong chuỗi Một dấu gạch dưới ( "_") trong mô hình phù hợp với bất kỳ ký tự đơn trong chuỗi. Bất kỳ nhân vật khác phù hợp với bản thân hoặc thấp hơn / chữ hoa tương đương (tức là case-insensitive khớp) (Một lỗi:. SQLite chỉ hiểu chữ hoa / chữ thường cho các ký tự ASCII. Toán tử THÍCH phân biệt chữ hoa chữ thường đối với các ký tự unicode nằm ngoài phạm vi ASCII. Ví dụ: biểu thức 'a' THÍCH 'A' là TRUE nhưng 'æ' THÍCH ''là sai.)."


@ MM-BB có, trừ khi chúng tôi thực hiện THÍCH trên một cột được khai báo (hoặc được lập chỉ mục) là THU THẬP NỀN TẢNG, nó sẽ thực hiện quét toàn bộ các hàng.
Nick Dandoulakis

1
Nó không phải là một lỗi, nó là một giới hạn tài liệu. Cùng một trang được trích dẫn trong câu trả lời đề cập đến phần mở rộng ICU quản lý các ký tự unicode. (Có lẽ đó không phải là trường hợp trong năm 2009)
stenci

40

Điều này không cụ thể đối với sqlite nhưng bạn chỉ có thể làm

SELECT * FROM ... WHERE UPPER(name) = UPPER('someone')

Phần khác của mối quan tâm về hiệu suất là tìm các hàng khớp trong bảng. SQLite3 có hỗ trợ các chỉ mục dựa trên chức năng không? Lập chỉ mục cột tìm kiếm hoặc biểu thức (ví dụ: "LÊN (tên)") trong tình huống như thế này thường là một ý tưởng tốt.
cheduardo

13
Xem ra với điều này, như cheduardo gợi ý, SQLite không thể sử dụng một chỉ mục trên 'name' khi chạy truy vấn này. Công cụ db sẽ cần quét toàn bộ tất cả các hàng, chuyển đổi tất cả các trường 'tên' thành chữ hoa và chạy so sánh.
Mathew Waters

1
@quantity, vâng, rất nhiều.
Berga

4

Một lựa chọn khác là tạo đối chiếu tùy chỉnh của riêng bạn. Sau đó, bạn có thể đặt đối chiếu đó trên cột hoặc thêm nó vào các mệnh đề đã chọn. Nó sẽ được sử dụng để đặt hàng và so sánh.

Điều này có thể được sử dụng để tạo ra 'VOILA' THÍCH 'voilà'.

http://www.sqlite.org/capi3ref.html#sqlite3_create_collation

Hàm đối chiếu phải trả về một số nguyên âm, bằng 0 hoặc dương nếu chuỗi thứ nhất nhỏ hơn, bằng hoặc lớn hơn chuỗi thứ hai, tương ứng.


2

Một tùy chọn khác có thể có hoặc không có ý nghĩa trong trường hợp của bạn, là thực sự có một cột riêng với các giá trị được hạ thấp trước của cột hiện tại của bạn. Điều này có thể được xác định bằng cách sử dụng hàm SQLite LOWER()và sau đó bạn có thể thực hiện khớp trên cột này.

Rõ ràng, nó thêm sự dư thừa và tiềm năng cho sự không nhất quán, nhưng nếu dữ liệu của bạn là tĩnh, nó có thể là một lựa chọn phù hợp.


2

Đơn giản, bạn có thể sử dụng THU THẬP NOCASE trong truy vấn CHỌN của bạn:

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

1

Nếu cột là loại charthì bạn cần nối thêm giá trị bạn đang truy vấn bằng dấu cách, vui lòng tham khảo câu hỏi này tại đây . Điều này ngoài việc sử dụng COLLATE NOCASEhoặc một trong các giải pháp khác (trên (), v.v.).


0

bạn có thể sử dụng truy vấn tương tự để so sánh chuỗi tương ứng với các giá trị bảng.

chọn tên cột từ tên_bảng trong đó tên cột như 'giá trị so sánh tương ứng';


Điều này không thêm bất cứ điều gì vào stackoverflow.com/a/973665/2462516 đã được đăng vào năm 2009
umasudhan

0

Nó làm việc cho tôi hoàn hảo. SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

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.