พฤติกรรมเริ่มต้นของLIKE
และผู้ประกอบการเปรียบเทียบ=
อื่น ๆ เป็นกรณี ๆ ไป
เป็นไปได้หรือไม่ที่จะทำให้มันเป็นตัวพิมพ์เล็ก
REGEXP_LIKE(username,'me','i')
แทน LIKE หรือไม่?
พฤติกรรมเริ่มต้นของLIKE
และผู้ประกอบการเปรียบเทียบ=
อื่น ๆ เป็นกรณี ๆ ไป
เป็นไปได้หรือไม่ที่จะทำให้มันเป็นตัวพิมพ์เล็ก
REGEXP_LIKE(username,'me','i')
แทน LIKE หรือไม่?
คำตอบ:
ตั้งแต่ 10gR2, Oracle อนุญาตให้ปรับพฤติกรรมการเปรียบเทียบสตริงโดยการตั้งค่าNLS_COMP
และNLS_SORT
พารามิเตอร์เซสชั่น:
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
คุณยังสามารถสร้างดัชนีที่ไม่สนใจตัวพิมพ์เล็กและตัวพิมพ์ใหญ่:
create index
nlsci1_gen_person
on
MY_PERSON
(NLSSORT
(PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
)
;
ข้อมูลนี้จะถูกนำมาจากออราเคิลค้นหากรณีตาย บทความกล่าวถึงREGEXP_LIKE
แต่ดูเหมือนว่าจะทำงานกับเก่าดี=
เช่นกัน
ในรุ่นที่เก่ากว่า 10gR2 มันไม่สามารถทำได้จริง ๆ และวิธีการทั่วไปถ้าคุณไม่ต้องการการค้นหาที่เน้นเสียงไม่รู้สึกก็คือการใช้UPPER()
ทั้งคอลัมน์และนิพจน์การค้นหา
LIKE
การแสดงออกโดยพลการ (เช่นWHERE foo LIKE '%abc%'
) นั้นช้าพอหากไม่สามารถจัดทำดัชนีได้ฉันไม่คิดว่ามันเกี่ยวข้องกับความไวของ case โดยเฉพาะ
DBD::Oracle
คุณสามารถเขียน$ENV{NLS_SORT} = 'BINARY_CI'; $ENV{NLS_COMP} = 'LINGUISTIC';
ก่อนที่จะเรียก "DBI-> connect"
ALTER SESSION
แก้ไขอินสแตนซ์ในการแก้ไขเท่านั้นและมันหมายถึงเซสชั่นปัจจุบันของคุณคือถ้าฉันปิดและเปิดใหม่มันจะรีเซ็ต มีวิธีที่ฉันสามารถดูว่าค่าปัจจุบันคืออะไรเพื่อให้มันคงอยู่ทุกหนทุกแห่งฉันสามารถเปลี่ยนกลับเป็นการตั้งค่าดั้งเดิม ...
มี 3 วิธีหลักในการค้นหาแบบตรงตามตัวพิมพ์ใน Oracle โดยไม่ต้องใช้ดัชนีข้อความแบบเต็ม
ในที่สุดวิธีการที่คุณเลือกนั้นขึ้นอยู่กับสถานการณ์ของคุณ สิ่งสำคัญที่ต้องจำคือการปรับปรุงประสิทธิภาพคุณต้องจัดทำดัชนีอย่างถูกต้องสำหรับการค้นหาแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
คุณสามารถบังคับให้ข้อมูลทั้งหมดของคุณเป็นกรณีเดียวกันโดยใช้UPPER()
หรือLOWER()
:
select * from my_table where upper(column_1) = upper('my_string');
หรือ
select * from my_table where lower(column_1) = lower('my_string');
หากcolumn_1
ไม่ได้จัดทำดัชนีupper(column_1)
หรือlower(column_1)
ตามความเหมาะสมอาจเป็นการสแกนแบบเต็มตาราง เพื่อหลีกเลี่ยงการนี้คุณสามารถสร้างดัชนีฟังก์ชั่นที่ใช้
create index my_index on my_table ( lower(column_1) );
หากคุณใช้ LIKE คุณจะต้องเชื่อม%
สตริงที่คุณกำลังค้นหา
select * from my_table where lower(column_1) LIKE lower('my_string') || '%';
ซอ Fiddle นี้แสดงให้เห็นถึงสิ่งที่เกิดขึ้นในแบบสอบถามเหล่านี้ทั้งหมด หมายเหตุอธิบายแผนซึ่งระบุว่าจะใช้ดัชนีเมื่อใดและเมื่อใด
จาก Oracle 10g เป็นต้นไปREGEXP_LIKE()
สามารถใช้ได้ คุณสามารถระบุ _match_parameter_ 'i'
เพื่อทำการค้นหาแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก
ในการใช้สิ่งนี้เป็นตัวดำเนินการความเสมอภาคคุณต้องระบุจุดเริ่มต้นและจุดสิ้นสุดของสตริงซึ่งแสดงโดยกะรัตและเครื่องหมายดอลลาร์
select * from my_table where regexp_like(column_1, '^my_string$', 'i');
ในการดำเนินการเทียบเท่า LIKE สามารถลบออกได้
select * from my_table where regexp_like(column_1, 'my_string', 'i');
โปรดระวังสิ่งนี้เนื่องจากสตริงของคุณอาจมีอักขระที่จะตีความแตกต่างกันโดยเอ็นจินนิพจน์ทั่วไป
ซอ Fiddle นี้แสดงผลลัพธ์ตัวอย่างเดียวกันให้คุณยกเว้นการใช้ REGEXP_LIKE ()
NLS_SORTพารามิเตอร์ควบคุมลำดับการเปรียบเทียบสำหรับการสั่งซื้อและดำเนินการเปรียบเทียบต่างๆรวมถึง=
และไม่ชอบ คุณสามารถระบุไบนารีเป็นตัวพิมพ์เล็กและตัวพิมพ์ใหญ่การเรียงลำดับโดยการเปลี่ยนเซสชั่น ซึ่งหมายความว่าทุกแบบสอบถามที่ดำเนินการในเซสชันนั้นจะดำเนินการตามตัวพิมพ์เล็กและใหญ่
alter session set nls_sort=BINARY_CI
มีข้อมูลเพิ่มเติมมากมายเกี่ยวกับการเรียงลำดับภาษาศาสตร์และการค้นหาสตริงหากคุณต้องการระบุภาษาอื่นหรือทำการค้นหาแบบเน้นเสียงโดยใช้ BINARY_AI
คุณจะต้องเปลี่ยนพารามิเตอร์NLS_COMPด้วย อ้าง:
ตัวดำเนินการที่แน่นอนและส่วนคำสั่งที่ปฏิบัติตามพารามิเตอร์ NLS_SORT ขึ้นอยู่กับค่าของพารามิเตอร์ NLS_COMP หากโอเปอเรเตอร์หรือส่วนคำสั่งไม่เชื่อฟังค่า NLS_SORT ตามที่กำหนดโดย NLS_COMP การเปรียบเทียบที่ใช้คือ BINARY
ค่าเริ่มต้นของ NLS_COMP คือ BINARY แต่ LINGUISTIC ระบุว่า Oracle ควรใส่ใจกับค่าของ NLS_SORT:
การเปรียบเทียบสำหรับการดำเนินงาน SQL ทั้งหมดในส่วนคำสั่ง WHERE และบล็อก PL / SQL ควรใช้การเรียงลำดับภาษาศาสตร์ที่ระบุในพารามิเตอร์ NLS_SORT เพื่อปรับปรุงประสิทธิภาพคุณยังสามารถกำหนดดัชนีภาษาในคอลัมน์ที่คุณต้องการเปรียบเทียบภาษา
ดังนั้นอีกครั้งคุณจะต้องเปลี่ยนเซสชั่น
alter session set nls_comp=LINGUISTIC
ดังที่ระบุไว้ในเอกสารคุณอาจต้องการสร้างดัชนีภาษาเพื่อปรับปรุงประสิทธิภาพ
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') || '%';
แทน select * from my_table where lower(column_1) LIKE lower('my_string%');
? มันให้ประโยชน์ใด ๆ หรือไม่?
regexp_like
จะมีวิธีที่จะหลบหนีสตริงดังกล่าวหรือไม่ ให้ตัวอย่างถ้าสตริงมี $ ผลลัพธ์จะไม่เป็นอย่างที่เราคาดหวัง // cc @Ben และคนอื่น ๆ โปรดแชร์
`
เป็นตัวหนี @bozzmob ไม่ควรมีเอาต์พุตที่แตกต่างกันหากสตริงที่นิพจน์ทั่วไปทำงานอยู่มี a $
ซึ่งอาจทำให้คุณเกิดปัญหาหากคุณต้องการ$
ตัวอักษรในนิพจน์ปกติของคุณ หากคุณมีปัญหาที่เฉพาะเจาะจงฉันถามคำถามอื่นถ้าความคิดเห็น / คำตอบนี้ไม่ได้ช่วย
บางทีคุณสามารถลองใช้
SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'
WHERE upper(user_name) LIKE UPPER('%ME%')
บ้างไหม? :)
UPPER
พารามิเตอร์อินพุตด้วยล่ะ
upper
ฟังก์ชั่นที่คุณสูญเสียดัชนีคุณมีความคิดวิธีการค้นหาโดยใช้ดัชนีหรือไม่?
จาก Oracle 12c R2 คุณสามารถใช้COLLATE operator
:
COLLATE โอเปอเรเตอร์กำหนดการเรียงหน้าสำหรับนิพจน์ โอเปอเรเตอร์นี้ช่วยให้คุณสามารถแทนที่การเปรียบเทียบที่ฐานข้อมูลจะได้มาสำหรับนิพจน์โดยใช้กฎการได้มาซึ่งการเปรียบเทียบการจัดเรียงมาตรฐาน
ตัวดำเนินการ COLLATE ใช้เวลาหนึ่งอาร์กิวเมนต์ collation_name ซึ่งคุณสามารถระบุการเปรียบเทียบที่กำหนดชื่อหรือการตรวจสอบเทียมหลอก หากชื่อการเรียงมีช่องว่างคุณต้องใส่ชื่อในเครื่องหมายคำพูดคู่
การสาธิต:
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 ในอาร์กิวเมนต์แรกที่สองของคุณNLSSORT
จะไม่ได้หมายถึงการเป็นสัญลักษณ์แทนใช่มั้ย? พวกเขาค่อนข้างสับสน
คุณสามารถทำอะไรเช่นนั้น:
where regexp_like(name, 'string$', 'i');