Hành vi mặc định của LIKE
và các toán tử so sánh khác, =
vv là phân biệt chữ hoa chữ thường.
Có thể làm cho họ không nhạy cảm trường hợp?
REGEXP_LIKE(username,'me','i')
thay vì THÍCH?
Hành vi mặc định của LIKE
và các toán tử so sánh khác, =
vv là phân biệt chữ hoa chữ thường.
Có thể làm cho họ không nhạy cảm trường hợp?
REGEXP_LIKE(username,'me','i')
thay vì THÍCH?
Câu trả lời:
Kể từ 10gR2, Oracle cho phép tinh chỉnh hành vi so sánh chuỗi bằng cách đặt tham số NLS_COMP
và NLS_SORT
phiên:
SQL> SET HEADING OFF
SQL> SELECT *
2 FROM NLS_SESSION_PARAMETERS
3 WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');
NLS_SORT
BINARY
NLS_COMP
BINARY
SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
2 FROM DUAL;
0
SQL>
SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;
Session altered.
SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;
Session altered.
SQL>
SQL> SELECT *
2 FROM NLS_SESSION_PARAMETERS
3 WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');
NLS_SORT
BINARY_CI
NLS_COMP
LINGUISTIC
SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
2 FROM DUAL;
1
Bạn cũng có thể tạo các chỉ mục không phân biệt chữ hoa chữ thường:
create index
nlsci1_gen_person
on
MY_PERSON
(NLSSORT
(PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
)
;
Thông tin này được lấy từ các trường hợp tìm kiếm không nhạy cảm của Oracle . Bài báo đề cập REGEXP_LIKE
nhưng nó dường như cũng làm việc với tốt cũ =
.
Trong các phiên bản cũ hơn 10gR2, điều đó thực sự không thể thực hiện được và cách tiếp cận thông thường, nếu bạn không cần tìm kiếm không có dấu , chỉ là UPPER()
cả cột và biểu thức tìm kiếm.
LIKE
biểu thức tùy ý (ví dụ WHERE foo LIKE '%abc%'
) đã đủ chậm nếu chúng không thể được lập chỉ mục, tôi không nghĩ nó liên quan cụ thể đến tính nhạy cảm của trường hợp.
DBD::Oracle
, bạn có thể viết $ENV{NLS_SORT} = 'BINARY_CI'; $ENV{NLS_COMP} = 'LINGUISTIC';
trước khi gọi `DBI-> connect`.
ALTER SESSION
chỉ thay đổi phiên bản địa phương của bạn về sửa lỗi và nó có nghĩa như phiên hiện tại của bạn tức là nếu tôi đóng và mở lại thì nó sẽ được đặt lại. Có cách nào để tôi có thể thấy các giá trị hiện tại là gì để nếu nó tồn tại ở mọi nơi tôi có thể thay đổi lại cài đặt gốc ...
Có 3 cách chính để thực hiện tìm kiếm không phân biệt chữ hoa chữ thường trong Oracle mà không cần sử dụng các chỉ mục toàn văn.
Cuối cùng, phương pháp bạn chọn phụ thuộc vào hoàn cảnh cá nhân của bạn; điều chính cần nhớ là để cải thiện hiệu suất, bạn phải lập chỉ mục chính xác cho tìm kiếm không phân biệt chữ hoa chữ thường.
Bạn có thể buộc tất cả dữ liệu của mình giống nhau bằng cách sử dụng UPPER()
hoặc LOWER()
:
select * from my_table where upper(column_1) = upper('my_string');
hoặc là
select * from my_table where lower(column_1) = lower('my_string');
Nếu column_1
không được lập chỉ mục trên upper(column_1)
hoặc lower(column_1)
, nếu phù hợp, điều này có thể buộc quét toàn bộ bảng. Để tránh điều này, bạn có thể tạo một chỉ mục dựa trên chức năng .
create index my_index on my_table ( lower(column_1) );
Nếu bạn đang sử dụng THÍCH thì bạn phải nối một %
chuỗi xung quanh chuỗi bạn đang tìm kiếm.
select * from my_table where lower(column_1) LIKE lower('my_string') || '%';
Fiddle SQL này cho thấy những gì xảy ra trong tất cả các truy vấn này. Lưu ý Kế hoạch Giải thích, cho biết khi nào một chỉ mục đang được sử dụng và khi nào thì không.
Từ Oracle 10g trở đi REGEXP_LIKE()
có sẵn. Bạn có thể chỉ định _match_parameter_ 'i'
, để thực hiện tìm kiếm không phân biệt chữ hoa chữ thường.
Để sử dụng điều này như một toán tử đẳng thức, bạn phải chỉ định điểm bắt đầu và kết thúc của chuỗi, được biểu thị bằng carat và ký hiệu đô la.
select * from my_table where regexp_like(column_1, '^my_string$', 'i');
Để thực hiện tương đương với THÍCH, chúng có thể được gỡ bỏ.
select * from my_table where regexp_like(column_1, 'my_string', 'i');
Hãy cẩn thận với điều này vì chuỗi của bạn có thể chứa các ký tự sẽ được diễn giải khác nhau bởi công cụ biểu thức chính quy.
Fiddle SQL này cho bạn thấy đầu ra ví dụ tương tự ngoại trừ sử dụng REGEXP_LIKE ().
Các NLS_SORT tham số điều chỉnh chuỗi collation cho đặt hàng và các toán tử so sánh khác nhau, bao gồm =
và LIKE. Bạn có thể chỉ định nhị phân, không phân biệt chữ hoa chữ thường, sắp xếp bằng cách thay đổi phiên. Điều này có nghĩa là mọi truy vấn được thực hiện trong phiên đó sẽ thực hiện các tham số không phân biệt chữ hoa chữ thường.
alter session set nls_sort=BINARY_CI
Có rất nhiều thông tin bổ sung xung quanh việc sắp xếp ngôn ngữ và tìm kiếm chuỗi nếu bạn muốn chỉ định một ngôn ngữ khác hoặc thực hiện tìm kiếm không nhạy cảm bằng cách sử dụng BINARY_AI.
Bạn cũng sẽ cần thay đổi tham số NLS_COMP ; để trích:
Các toán tử và mệnh đề truy vấn chính xác tuân theo tham số NLS_SORT phụ thuộc vào giá trị của tham số NLS_COMP. Nếu một toán tử hoặc mệnh đề không tuân theo giá trị NLS_SORT, như được xác định bởi NLS_COMP, thì đối chiếu được sử dụng là BINary.
Giá trị mặc định của NLS_COMP là BINary; nhưng, LINGUISTIC chỉ định rằng Oracle nên chú ý đến giá trị của NLS_SORT:
So sánh tất cả các hoạt động SQL trong mệnh đề WHERE và trong các khối PL / SQL nên sử dụng sắp xếp ngôn ngữ được chỉ định trong tham số NLS_SORT. Để cải thiện hiệu suất, bạn cũng có thể xác định một chỉ số ngôn ngữ trên cột mà bạn muốn so sánh ngôn ngữ.
Vì vậy, một lần nữa, bạn cần thay đổi phiên
alter session set nls_comp=LINGUISTIC
Như đã lưu ý trong tài liệu, bạn có thể muốn tạo một chỉ mục ngôn ngữ để cải thiện hiệu suất
create index my_linguistc_index on my_table
(NLSSORT(column_1, 'NLS_SORT = BINARY_CI'));
select * from my_table where lower(column_1) LIKE lower('my_string') || '%';
thay vì select * from my_table where lower(column_1) LIKE lower('my_string%');
? Liệu nó có mang lại lợi thế nào không?
regexp_like
, liệu có cách nào để thoát khỏi chuỗi đó không? Đưa ra một ví dụ, nếu chuỗi có $, đầu ra sẽ không như những gì chúng ta mong đợi. // cc @Ben và những người khác xin vui lòng chia sẻ.
`
là nhân vật thoát @bozzmob. Không có sự khác biệt về đầu ra nếu chuỗi biểu thức chính quy đang hoạt động có chứa a $
, điều này chỉ có thể gây ra sự cố cho bạn nếu bạn cần một $
chữ trong biểu thức chính quy. Nếu bạn có một vấn đề cụ thể, tôi sẽ hỏi một câu hỏi khác nếu nhận xét / câu trả lời này không có ích.
có lẽ bạn có thể thử sử dụng
SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'
WHERE upper(user_name) LIKE UPPER('%ME%')
sau đó? :)
UPPER
trên tham số đầu vào?
upper
chức năng bạn làm mất chỉ mục, bạn có biết làm thế nào để tìm kiếm bằng chỉ mục không?
Từ Oracle 12c R2 bạn có thể sử dụng COLLATE operator
:
Toán tử COLLATE xác định đối chiếu cho một biểu thức. Toán tử này cho phép bạn ghi đè lên đối chiếu mà cơ sở dữ liệu sẽ có được cho biểu thức bằng cách sử dụng các quy tắc dẫn xuất đối chiếu chuẩn.
Toán tử COLLATE lấy một đối số, collation_name, trong đó bạn có thể chỉ định đối chiếu có tên hoặc đối chiếu giả. Nếu tên đối chiếu chứa một khoảng trắng, thì bạn phải đặt tên đó trong dấu ngoặc kép.
Bản giới thiệu:
CREATE TABLE tab1(i INT PRIMARY KEY, name VARCHAR2(100));
INSERT INTO tab1(i, name) VALUES (1, 'John');
INSERT INTO tab1(i, name) VALUES (2, 'Joe');
INSERT INTO tab1(i, name) VALUES (3, 'Billy');
--========================================================================--
SELECT /*csv*/ *
FROM tab1
WHERE name = 'jOHN' ;
-- no rows selected
SELECT /*csv*/ *
FROM tab1
WHERE name COLLATE BINARY_CI = 'jOHN' ;
/*
"I","NAME"
1,"John"
*/
SELECT /*csv*/ *
FROM tab1
WHERE name LIKE 'j%';
-- no rows selected
SELECT /*csv*/ *
FROM tab1
WHERE name COLLATE BINARY_CI LIKE 'j%';
/*
"I","NAME"
1,"John"
2,"Joe"
*/
select user_name
from my_table
where nlssort(user_name, 'NLS_SORT = Latin_CI') = nlssort('%AbC%', 'NLS_SORT = Latin_CI')
%
's trong đối số đầu tiên thứ hai của bạn NLSSORT
đang không có nghĩa là ký tự đại diện, phải không? Họ nhầm lẫn.