Hi các bạn ^^ Chả là chiều nay, đang lướt Facebook thì mình có đọc được một câu hỏi của một cậu em, đại khái là cậu ấy có issue sau: "Có một bảng lưu trữ dữ liệu là Tiếng việt có dấu, bây giờ muốn khi truy vấn thì dù viết có dấu hay không dấu đều trả ra kết quả" Một câu hỏi khi nhìn qua thì ta thấy rất đơn giản, mình cũng nghĩ vậy, nhưng đọc các câu trả lời thì bắt đầu mình thấy phức tạp
Đề xuất 1: Khi truy vấn thì chuyển có dấu sang không dâu !
Bạn này chưa hiểu câu hỏi, bản chất vấn đề là phải lưu dữ liệu có dấu, nên nếu làm như bạn này nói thì truy vấn ko bao giờ match cả !
Đề xuất 2: Sử dụng UnicodeSharpCore
Đây là 1 thư viện, cụ thể hơn là 1 extensions của String giúp loại bỏ unicode khỏi string.Nó cũng ko giải quyết được vấn đề, nó cũng tương tự cách bạn kia là truy vấn không dấu
Đề xuất 3: Tạo một cột mới lưu tiếng việt không dấu bên cạnh có dấu, dạng url slug
Cái này khả thi hơn, nhưng nó lại nảy sinh 1 vấn đề mới. Đó là nếu dữ liệu quá lớn, ví dụ lưu cả gần 1000 chương Cẩm Y Vệ vào (tất nhiên ko ai lưu 1000 chương vào 1 chỗ, nhưng ta phải giải quyết thắc mắc này) thì sao ? Nếu làm thêm 1 cột clone data và lọc dấu đi thì vừa tốn lưu trữ, vừa tốn công tiền xử lý data (bỏ dấu)
Solution: Thiết kế lại bảng
Các cách trên đều chưa ổn, mình đề xuất 1 cách sau. Giả sử bảng của chúng ta có 3 cột như sau
Trong đó
ID: Cột định danh khóa chính
Word: Cột lưu trữ dữ liệu
Offset: Cái này ko quan trọng, ignore nó đi, giả sử cuốn sách nằm ở vị trí kệ 500 thì lưu ở đây
Giờ, ta sẽ tạo bảng với query sau
CREATE TABLE DocumentIndex (id INT PRIMARY KEY,
word NVARCHAR(MAX) COLLATE Vietnamese_CI_AI,
document_offset INT);
Ở đây, ta định nghĩa cột 'Word' sử dụng collate 'Vietnamese', sơ qua về Collate
Trong SQL, collation là một thiết lập quy định cách so sánh và sắp xếp dữ liệu chuỗi trong cơ sở dữ liệu. Collation ảnh hưởng đến cách các ký tự được xử lý và so sánh trong các truy vấn SQL, đặc biệt là khi sắp xếp chuỗi. Collation trong SQL có thể được áp dụng cho toàn bộ cơ sở dữ liệu, bảng hoặc cột cụ thể. Đối với ngôn ngữ Vietnamese, việc chọn collation là quan trọng để đảm bảo sự đồng nhất trong quá trình so sánh và sắp xếp các ký tự có dấu. Ta bổ sung thêm "CI" và "AI", chúng có nghĩa là gì? CI: Case Insensitive => Không phân biệt hoa, thường
AI: Accent Insensitive => Không phân biệt dấu
Như vậy, dữ liệu được lưu trên cột này sẽ đáp ứng được yêu cầu trên, mà ta không phải tạo thêm 1 cột khác nữa
Để tối ưu, ta đánh index cho cột WORD, bởi vì tìm kiếm chỉ xảy ra ở cột này
CREATE NONCLUSTERED INDEX IX_Word ON DocumentIndex (word);
Kiểm tra thử kết quả, mình đang đọc báo vụ Báo Người Lao Động khô máu với hiệp sĩ CNTT Nguyễn Tử Quảng nên mượn luôn nội dung bài báo Ta có 2 rows Giờ sẽ tìm chữ "oách nhỉ" bằng Tiếng việt có dấu Như mong muốn, ta đã tìm được Vậy, giờ dùng chữ "oach nhi" không dấu xem sao Kết quả tương tự, vậy đáp ứng được yêu cầu của bạn rồi
Tóm lại, để giải quyết việc tìm kiếm dữ liệu không dấu (non-unicode) trên dữ liệu có dấu (unicode) cụ thể là Tiếng Việt, ta sẽ sử dụng collate Vietnamese do SQL đã cung cấp Một số kết hợp của collation Vietnamese
Vietnamese_CI_AS (Case-Insensitive, Accent-Sensitive): Đây là collation phổ biến cho tiếng Việt. Nó là không phân biệt chữ hoa chữ thường nhưng phân biệt dấu.
Vietnamese_CS_AS (Case-Sensitive, Accent-Sensitive): Đây là collation không phân biệt chữ hoa chữ thường và phân biệt dấu. Các ký tự được coi là khác nhau nếu chúng có chữ hoa/chữ thường khác nhau hoặc dấu khác nhau.
Vietnamese_CI_AI (Case-Insensitive, Accent-Insensitive): Collation này không phân biệt chữ hoa chữ thường và không phân biệt dấu.
Vietnamese_CS_AI (Case-Sensitive, Accent-Insensitive): Collation này phân biệt chữ hoa chữ thường, nhưng không phân biệt dấu.
Kết bài, cảm ơn các bạn đã theo dõi ạ ^^