2013-02-24 36 views
5

Tôi muốn so sánh hai chuỗi trong một DB SQLite mà không cần quan tâm đến dấu trọng âm và trường hợp. Tôi có nghĩa là "Événement" nên bằng "evenèment".COLLATE được bản địa hoá trên so sánh chuỗi SQLite

Trên Debian Wheezy, gói SQLite không cung cấp ICU. Vì vậy, tôi đã biên soạn gói SQLite chính thức (phiên bản 3.7.15.2 2013-01-09 11:53:05) với một mô-đun ICU. Bây giờ, tôi có hỗ trợ Unicode tốt hơn (bản gốc lower() chỉ áp dụng cho các ký tự ASCII, giờ nó hoạt động trên các chữ cái khác). Nhưng tôi không thể quản lý để áp dụng một đối chiếu để so sánh.

SELECT icu_load_collation('fr_FR', 'FRENCH'); 
SELECT 'événement' COLLATE FRENCH = 'evenement'; 
-- 0 (should be 1) 
SELECT 'Événement' COLLATE FRENCH = 'événement'; 
-- 0 (should be 1 if collation was case-insensitive) 
SELECT lower('Événement') = 'événement'; 
-- 1 (at least lower() works as expected with Unicode strings) 

SQLite documentation xác nhận rằng đây là cách phù hợp để áp dụng đối chiếu. Tôi nghĩ rằng documentation of this ICU extension là một chút ánh sáng (vài ví dụ, không có gì về trường hợp nhạy cảm đối với collations).

Tôi không hiểu tại sao toán tử COLLATE không có tác dụng trong ví dụ trên của tôi. Hãy giúp tôi.

Trả lời

5

Tôi đã dành cho tôi nhiều giờ để hiểu tình hình ... Cách mà các collation ICU được định nghĩa trong SQLite có (hầu như) không có tỷ lệ so sánh. Một ngoại lệ là, theo ICU, văn bản tiếng Do Thái với các dấu hiệu ợ hơi. Đây là hành vi mặc định của collation của thư viện ICU. Với SQLite, LIKE trở nên không phân biệt chữ hoa chữ thường khi ICU được tải, nhưng không thể đạt được bình thường hóa các chữ cái nổi bật theo cách này.

cuối cùng tôi đã hiểu rằng những gì tôi cần là để thiết lập strength của collation cho primary level thay cho bậc đại học mặc định.

Tôi không tìm thấy cách nào để đặt điều này thông qua ngôn ngữ (ví dụ: một số biến thể của SELECT icu_load_collation('fr_FR,strength=0', 'french') là vô dụng). Vì vậy, giải pháp duy nhất là vá mã của SQLite. Thật dễ dàng nhờ hàm ucol_setStrength() trong số ICU API.

Thay đổi tối thiểu là bản vá một dòng: thêm dòng ucol_setStrength(pUCollator, 0); sau pUCollator = ucol_open(zLocale, &status); trong hàm icuLoadCollation(). Để thay đổi tương thích ngược, tôi đã thêm tham số thứ ba tùy chọn vào icu_load_collation() đặt độ mạnh: 0 theo mặc định, 1 cho giá trị chính, v.v ... lên đến 4-bậc bốn. Xem diff.

Cuối cùng tôi có những gì tôi muốn:

SELECT icu_load_collation('fr_FR', 'french_ci', 1); -- collation with strength=primary 
SELECT 'Événement' COLLATE french_ci = 'evenèment'; 
-- 1 
Các vấn đề liên quan