เท่ากับ (=) กับ LIKE


282

เมื่อใช้ SQL จะมีประโยชน์ใด ๆ ของการใช้=ในWHEREประโยคแทนLIKE?

ไม่มีผู้ประกอบการพิเศษใด ๆLIKEและ=เหมือนกันใช่มั้ย


4
อาจต้องการระบุประเภท db ... mssql, mysql, oracle?
อัลเลนข้าว

1
คำถามของคุณมี5คะแนนอย่างน้อยสำหรับแท็กตัวดำเนินการเหมือนกัน ฉันขอความกรุณาให้คุณแนะนำsql-likeเป็นคำเหมือนได้ไหม
มิต

@ FreshPrinceOfSO ฉันจะทำเมื่อฉันได้รับชื่อเสียงเพียงพอ ขอบคุณ
เทรวิส

คำตอบ:


271

ผู้ประกอบการที่แตกต่างกัน

LIKEและ=เป็นผู้ประกอบการที่แตกต่างกัน คำตอบส่วนใหญ่ที่นี่มุ่งเน้นไปที่การสนับสนุนสัญลักษณ์ซึ่งไม่แตกต่างกันเพียงระหว่างผู้ประกอบการเหล่านี้!

=เป็นตัวดำเนินการเปรียบเทียบที่ทำงานกับตัวเลขและสตริง เมื่อเปรียบเทียบสตริงตัวดำเนินการเปรียบเทียบเปรียบเทียบสตริงทั้งหมด

LIKEเป็นผู้ประกอบการสตริงที่เปรียบเทียบทีละอักขระ

ในการทำให้เรื่องซับซ้อนผู้ประกอบการทั้งสองใช้การเปรียบเทียบซึ่งอาจมีผลกระทบที่สำคัญต่อผลลัพธ์ของการเปรียบเทียบ

ตัวอย่างการสร้างแรงจูงใจ

ก่อนอื่นเรามาระบุตัวอย่างที่ตัวดำเนินการเหล่านี้ให้ผลลัพธ์ที่ต่างกัน ให้ฉันอ้างอิงจากคู่มือ MySQL:

สำหรับมาตรฐาน SQL นั้น LIKE จะทำการจับคู่แบบตัวอักษรต่อตัวดังนั้นจึงสามารถสร้างผลลัพธ์ที่แตกต่างจากตัวดำเนินการ = การเปรียบเทียบ:

mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+

โปรดทราบว่าหน้านี้ของคู่มือ MySQL เรียกว่าฟังก์ชั่นการเปรียบเทียบสตริงและ=ไม่ได้กล่าวถึงซึ่งหมายความว่า=ไม่ฟังก์ชั่นการเปรียบเทียบสตริงอย่างเคร่งครัด

วิธีการที่ไม่=ทำงาน?

SQL มาตรฐาน§ 8.2อธิบายวิธี=เปรียบเทียบสตริง:

การเปรียบเทียบสตริงอักขระสองตัวถูกพิจารณาดังนี้:

a) หากความยาวเป็นอักขระของ X ไม่เท่ากับความยาวเป็นอักขระของ Y ดังนั้นสตริงที่สั้นกว่านั้นจะถูกแทนที่อย่างมีประสิทธิภาพเพื่อวัตถุประสงค์ในการเปรียบเทียบด้วยสำเนาของตัวเองที่ขยายไปจนถึงความยาวของสตริงที่ยาวกว่า โดยการเรียงต่อกันทางด้านขวาของอักขระแผ่นอย่างน้อยหนึ่งตัวซึ่งอักขระแผ่นถูกเลือกตาม CS หาก CS มีแอตทริบิวต์ NO PAD แสดงว่าตัวอักษรของ pad นั้นเป็นอักขระที่ขึ้นอยู่กับการนำไปใช้งานซึ่งแตกต่างจากอักขระใด ๆ ในชุดอักขระของ X และ Y ที่เรียงกันน้อยกว่าสตริงใด ๆ ภายใต้ CS มิฉะนั้นตัวละครแผ่นคือ

b) ผลลัพธ์ของการเปรียบเทียบ X และ Y นั้นได้รับจากการเรียงลำดับ CS

c) ขึ้นอยู่กับลำดับการเรียงสองสตริงอาจเปรียบเทียบเท่ากันแม้ว่าจะมีความยาวต่างกันหรือมีลำดับอักขระต่างกัน เมื่อการดำเนินการ MAX, MIN, DISTINCT, การอ้างอิงไปยังคอลัมน์การจัดกลุ่มและตัวดำเนินการ UNION, EXCEPT และ INTERSECT อ้างถึงสตริงอักขระค่าเฉพาะที่เลือกโดยการดำเนินการเหล่านี้จากชุดของค่าที่เท่ากันนั้นขึ้นอยู่กับการใช้งาน

(เพิ่มการเน้น)

สิ่งนี้หมายความว่า? หมายความว่าเมื่อเปรียบเทียบสตริงตัว=ดำเนินการเป็นเพียง wrapper บาง ๆ รอบการเปรียบเทียบปัจจุบัน การเปรียบเทียบคือไลบรารีที่มีกฎต่าง ๆ สำหรับการเปรียบเทียบสตริง นี่คือตัวอย่างของการเปรียบเทียบไบนารีจาก MySQL :

static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
                               const uchar *s, size_t slen,
                               const uchar *t, size_t tlen,
                               my_bool t_is_prefix)
{
  size_t len= MY_MIN(slen,tlen);
  int cmp= memcmp(s,t,len);
  return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}

การเปรียบเทียบแบบพิเศษนี้เกิดขึ้นเพื่อเปรียบเทียบไบต์ต่อไบต์ (ซึ่งเป็นสาเหตุที่เรียกว่า "ไบนารี่" - มันไม่ได้ให้ความหมายพิเศษกับสตริง) การเปรียบเทียบอื่น ๆ อาจให้การเปรียบเทียบขั้นสูงเพิ่มเติม

ตัวอย่างเช่นนี่คือการเปรียบเทียบ UTF-8ที่รองรับการเปรียบเทียบแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ รหัสนานเกินไปที่จะวางที่นี่ my_strnncollsp_utf8mb4()แต่ไปที่ลิงค์ที่และอ่านร่างของ การจัดเรียงนี้สามารถประมวลผลทีละหลายไบต์และสามารถใช้การแปลงต่าง ๆ (เช่นการเปรียบเทียบแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่) ตัว=ดำเนินการถูกแยกออกจากการเรียงของ

วิธีการที่ไม่LIKEทำงาน?

SQL มาตรฐาน§ 8.5อธิบายวิธีLIKEเปรียบเทียบสตริง:

<predicate>

M LIKE P

เป็นจริงถ้ามีการแบ่ง M ในการตั้งต้นเช่น:

i) สตริงย่อยของ M คือลำดับของ 0 หรือมากกว่าที่อยู่ติดกัน <การแสดงตัวอักษร> s ของ M และแต่ละ <การแสดงตัวอักษร> ของ M เป็นส่วนหนึ่งของสตริงย่อยที่แน่นอน

ii) หากตัวระบุสตริงย่อย i-th ของ P เป็นตัวระบุอักขระโดยพลการสตริงย่อย i-th ของ M คือ <การแสดงอักขระตัวเดียว> ใด ๆ

iii) หากตัวระบุสตริงย่อย i-th ของ P เป็นตัวระบุสตริงโดยพลการสตริงย่อย i-th ของ M คือลำดับใด ๆ ของ 0 หรือมากกว่า <การแสดงตัวอักษร> s

iv) หากตัวระบุสตริงย่อย i-th ของ P ไม่ใช่ตัวระบุอักขระตามอำเภอใจหรือตัวระบุสตริงแบบกำหนดเองดังนั้นสตริงย่อย i-th ของ M จะเท่ากับตัวระบุสตริงย่อยนั้นตามลำดับการเรียงลำดับของ <like predicate> โดยไม่มี การผนวกอักขระ <space> เข้ากับ M และมีความยาวเท่ากับตัวระบุสตริงย่อยนั้น

v) จำนวนสตริงย่อยของ M เท่ากับจำนวนตัวระบุสตริงย่อยของ P

(เพิ่มการเน้น)

นี่มันช่างพูดงั้นงั้นมาทำลายมันกัน รายการ ii และ iii อ้างถึง wildcard _และ%ตามลำดับ หากPไม่มีไวลด์การ์ดอยู่จะใช้ไอเท็ม iv เท่านั้น นี่เป็นกรณีที่ดอกเบี้ยเกิดขึ้นโดย OP

ในกรณีนี้มันจะเปรียบเทียบแต่ละ "สตริงย่อย" (อักขระแต่ละตัว) Mเทียบกับแต่ละสตริงย่อยในการPใช้การเปรียบเทียบปัจจุบัน

สรุปผลการวิจัย

บรรทัดล่างคือเมื่อเปรียบเทียบสตริงให้=เปรียบเทียบสตริงทั้งหมดในขณะที่LIKEเปรียบเทียบอักขระหนึ่งตัวในแต่ละครั้ง การเปรียบเทียบทั้งสองใช้การเปรียบเทียบปัจจุบัน ความแตกต่างนี้นำไปสู่ผลลัพธ์ที่แตกต่างกันในบางกรณีตามที่ปรากฏในตัวอย่างแรกในโพสต์นี้

คุณควรใช้อันไหน ไม่มีใครสามารถบอกคุณได้ว่า - คุณต้องใช้สิ่งที่ถูกต้องสำหรับกรณีการใช้งานของคุณ อย่าปรับให้เหมาะสมก่อนกำหนดโดยการสลับโอเปอเรเตอร์การเปรียบเทียบ


4
"EQUALS เปรียบเทียบข้อมูลสองไบต์ต่อไบต์": oversimplified และบ่อยเกินไปไม่เป็นความจริงเพราะพฤติกรรม EQUALS (=) สามารถแก้ไขได้ด้วย COLLATE ทำให้คลาสของอักขระถูกเปรียบเทียบแทนอักขระ เช่นดูdev.mysql.com/doc/refman/5.0/en/charset-collate.html (MySQL) หรือsqlmag.com/blog/forcing-collation-where-clause-22-jun-2011 (SQL Server)
Peter B

11
นี่คือคำตอบที่ถูกต้อง เรารู้ว่าสิ่งที่LIKEไม่ แต่คำตอบนี้ awesomely อธิบายว่าการใช้LIKEโดยไม่ต้อง%หรือ_ปัจจุบันไม่ได้เลย=เช่นเดียวกับการใช้ คำตอบของคุณอาจได้รับหนึ่งพัน upvotes
rinogo

1
@ mehase นี้ไม่เป็นความจริง ถ้าเขตข้อมูล varchar ของฉันมีค่า'AbCdEfG'และฉันทำWHERE MyCol = 'abcdefg'ฉันยังคงได้รับแถวนั้นกลับแม้ว่าพวกเขาจะไม่ชัดเจนเทียบเท่าไบต์ต่อไบต์
Kip

1
PeterB และ @Kip ต่างก็ให้คะแนนดี ฉันได้ปรับปรุงคำตอบของฉันเพื่อพยายามอธิบายว่าการเปรียบเทียบมีผลกับตัวดำเนินการเหล่านี้อย่างไร
Mark E. Haase

2
สิ่งนี้ไม่เป็นความจริงอีกต่อไป: set charset latin1; SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;ให้ 0 และSELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;ให้ 0 ด้วย
joanq

170

ตัวดำเนินการเท่ากับ (=) คือ "ตัวดำเนินการเปรียบเทียบเปรียบเทียบสองค่าเพื่อความเท่าเทียมกัน" กล่าวอีกนัยหนึ่งในคำสั่ง SQL จะไม่คืนค่าจริงเว้นแต่ว่าทั้งสองด้านของสมการจะเท่ากัน ตัวอย่างเช่น:

SELECT * FROM Store WHERE Quantity = 200;

ตัวดำเนินการ LIKE "ใช้รูปแบบการเปรียบเทียบการจับคู่" ที่พยายามจับคู่ "ค่าสตริงกับสตริงรูปแบบที่มีอักขระ wild-card" ตัวอย่างเช่น:

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

LIKE โดยทั่วไปใช้เฉพาะกับสตริงและเท่ากับ (ฉันเชื่อว่า) เร็วกว่า ตัวดำเนินการเท่ากับจะถือว่าอักขระ wild-card เป็นอักขระตัวอักษร ความแตกต่างในผลลัพธ์ที่ส่งคืนมีดังนี้:

SELECT * FROM Employees WHERE Name = 'Chris';

และ

SELECT * FROM Employees WHERE Name LIKE 'Chris';

จะส่งกลับผลลัพธ์เดียวกันแม้ว่าการใช้ LIKE โดยทั่วไปจะใช้เวลานานกว่าเนื่องจากรูปแบบตรงกัน อย่างไรก็ตาม

SELECT * FROM Employees WHERE Name = 'Chris%';

และ

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

จะให้ผลลัพธ์ที่แตกต่างกันโดยที่การใช้ "=" ให้ผลลัพธ์เฉพาะผลลัพธ์เมื่อมีการส่งคืน "Chris%" และตัวดำเนินการ LIKE จะส่งคืนสิ่งที่เริ่มต้นด้วย "Chris"

หวังว่าจะช่วย บางข้อมูลที่ดีสามารถพบได้ที่นี่


108
ฉันอยู่ภายใต้ความประทับใจที่ OP รู้ว่าจะใช้ LIKE เมื่อใดและเมื่อใดที่จะใช้ = เขาแค่สงสัยว่ามีความแตกต่างด้านประสิทธิภาพหรือไม่เมื่อไม่มี wildcard อยู่ คำตอบนี้สัมผัสสั้น ๆ แต่ฉันรู้สึกว่า 95% ของคำตอบนี้ไม่เกี่ยวข้องจริงๆ
Outlaw Programmer

1
จริงแท้แน่นอน. ฉันไม่แน่ใจว่าคำถามนั้นเหมือนกันหรือไม่เมื่อฉันตอบคำถาม ถ้าเป็นเช่นนั้นฉันคิดถึงส่วนที่ถามเกี่ยวกับการแสดง ขอบคุณสำหรับการสังเกต
achinda99

9
คำตอบนี้แย่มาก LIKE และ '=' เป็นตัวดำเนินการที่แตกต่างกันโดยสิ้นเชิง แต่เกิดขึ้นกับพฤติกรรมในทำนองเดียวกันในบางกรณี เพื่อประโยชน์ของลูกหลานโปรดอ่านคำตอบที่เหลือที่นี่หรืออย่างน้อย google สำหรับ "mysql like" ก่อนที่คุณจะยอมรับสิ่งนี้กับหน่วยความจำ
Mark E. Haase

3
ในทางกลับกันคำตอบนี้ตอบคำถามที่ฉันมีและ googled สำหรับ บางครั้งมันก็ดีถ้าคำตอบตอบชื่อของคำถามเช่นเดียวกับเนื้อหา
CorayThan

ความคิดที่ดีที่ต้องจดจำคือเมื่อคุณใช้ถ่านและ varchar2 ถ้าคุณเปรียบเทียบถ่านกับถ่าน ก่อนที่จะทำการเปรียบเทียบฐานข้อมูลก่อนอื่นให้ทำการแปลงความยาวของ 'ตัวแปร' ตัวแรกให้เป็นเท่าเดิม หากคุณเปรียบเทียบ char และ varchar2 ฐานข้อมูลจะไม่ทำอะไรเลย docs.oracle.com/cd/A64702_01/doc/server.805/a58236/c_char.htm
xild

18

นี่คือสำเนา / วางของคำตอบของฉันสำหรับคำถามSQL 'like' vs '=' ประสิทธิภาพ :

ตัวอย่างส่วนตัวที่ใช้ mysql 5.5: ฉันมีการรวมภายในระหว่าง 2 ตารางหนึ่งใน 3 ล้านแถวและหนึ่งใน 10,000 แถว

เมื่อใช้สิ่งที่ชอบในดัชนีด้านล่าง (ไม่มีสัญลักษณ์เสริม) จะใช้เวลาประมาณ 30 วินาที:

where login like '12345678'

ใช้ 'อธิบาย' ฉันได้รับ:

ป้อนคำอธิบายรูปภาพที่นี่

เมื่อใช้ '=' กับข้อความค้นหาเดียวกันจะใช้เวลาประมาณ 0.1 วินาที:

where login ='12345678'

ใช้ 'อธิบาย' ฉันได้รับ:

ป้อนคำอธิบายรูปภาพที่นี่

อย่างที่คุณเห็นการlikeยกเลิกการค้นหาดัชนีอย่างสมบูรณ์ดังนั้นการสืบค้นจึงใช้เวลามากขึ้น 300 เท่า


17

LIKEและ=มีความแตกต่าง LIKEคือสิ่งที่คุณจะใช้ในการค้นหา นอกจากนี้ยังอนุญาตให้ใช้ wildcard เช่น_( wildcard อักขระแบบง่าย) และ%(wildcard แบบหลายตัวอักษร)

= ควรใช้ถ้าคุณต้องการการแข่งขันที่แน่นอนและมันจะเร็วขึ้น

เว็บไซต์นี้อธิบาย LIKE


11

ข้อแตกต่างประการหนึ่ง - นอกเหนือจากความเป็นไปได้ที่จะใช้อักขระตัวแทนที่มี LIKE - อยู่ในช่องว่างต่อท้าย: ตัวดำเนินการ = ละเว้นพื้นที่ต่อท้าย แต่ LIKE ไม่ได้


4
แม้ว่าสิ่งนี้จะเป็นจริงสำหรับ MySQL และ MS SQL แต่สิ่งนี้ไม่ได้มีไว้สำหรับ PostgreSQL
บรูโน่

10

ขึ้นอยู่กับระบบฐานข้อมูล

โดยทั่วไปที่ไม่มีตัวอักษรพิเศษใช่ = และเหมือนกัน

อย่างไรก็ตามระบบฐานข้อมูลบางระบบอาจทำการตั้งค่าการจัดเรียงที่แตกต่างกับตัวดำเนินการที่แตกต่างกัน

ตัวอย่างเช่นในการเปรียบเทียบ MySQL กับ = on สตริงจะคำนึงถึงขนาดตัวพิมพ์เสมอโดยค่าเริ่มต้นดังนั้น LIKE ที่ไม่มีอักขระพิเศษจะเหมือนกัน ใน LIKE ของ RDBMS อื่นนั้นไม่คำนึงถึงขนาดตัวพิมพ์ขณะที่ = ไม่ใช่


มีบางอย่างที่เหมือนภาพรวมของสิ่งแปลกประหลาดนี้หรือไม่?
Gumbo

9

สำหรับตัวอย่างนี้เรารับค่าที่ varcharcol ไม่มี''และไม่มีเซลล์ว่างเทียบกับคอลัมน์นี้

select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''

ผลลัพธ์แรกจะแสดงผลลัพธ์เป็น 0 แถวในขณะที่รายการที่สองแสดงรายการทั้งหมด = เป็นกรณีที่จับคู่อย่างเคร่งครัดขณะที่ทำหน้าที่เหมือนตัวกรอง หากตัวกรองไม่มีเกณฑ์ข้อมูลทุกอย่างจะถูกต้อง

เช่น - โดยจุดประสงค์ของมันทำงานได้ช้าลงเล็กน้อยและมีไว้สำหรับใช้กับ varchar และข้อมูลที่คล้ายกัน


6

หากคุณค้นหาคู่ที่ตรงกันคุณสามารถใช้ทั้งคู่ = และ LIKE

การใช้ "=" จะเร็วขึ้นเล็กน้อยในกรณีนี้ (ค้นหาการจับคู่ที่ตรงกัน) - คุณสามารถตรวจสอบด้วยตัวเองโดยใช้แบบสอบถามเดียวกันสองครั้งใน SQL Server Management Studio เมื่อใช้ "=" เมื่อใช้ "LIKE" และ จากนั้นใช้ "Query" / "รวมแผนการดำเนินการจริง"

ดำเนินการแบบสอบถามทั้งสองและคุณควรเห็นผลลัพธ์ของคุณสองครั้งรวมทั้งแผนปฏิบัติจริงสองแผน ในกรณีของฉันพวกเขาถูกแบ่ง 50% เทียบกับ 50% แต่แผนการดำเนินการ "=" มีค่าใช้จ่าย "ทรีย่อยโดยประมาณ" ที่เล็กกว่า (แสดงเมื่อคุณวางเมาส์เหนือช่อง "เลือก" ซ้ายสุด) - แต่อีกครั้ง ไม่แตกต่างกันมาก

แต่เมื่อคุณเริ่มค้นหาด้วย wildcard ในนิพจน์ LIKE ของคุณประสิทธิภาพการค้นหาจะลดลง การค้นหา "LIKE Mill%" ยังคงค่อนข้างเร็ว - SQL Server สามารถใช้ดัชนีในคอลัมน์นั้นได้หากมีอยู่ การค้นหา "LIKE% expression%" นั้นช้ามากเนื่องจากวิธีเดียวที่ SQL Server สามารถตอบสนองการค้นหานี้ได้คือทำการสแกนตารางแบบเต็ม ดังนั้นระวังด้วย LIKE ของคุณ!

มาร์ค


-1 ไม่ไม่มันเร็วกว่านี้สักหน่อย หากคอลัมน์นั้นได้รับการจัดทำดัชนีโดยใช้% mystring% จะมีลำดับของขนาดที่ช้ากว่า แน่นอนว่ามาตรฐานรหัสใด ๆ ที่ควรค่าแก่เกลือของพวกเขาจะมีแนวทางที่เข้มงวดเกี่ยวกับเวลาและเวลาที่จะไม่ใช้เช่นบนฐานข้อมูลที่ใหญ่กว่าของ micky mouse
Cruachan

1
ฉันไม่เคยบอกว่ามันจะช้าลงเล็กน้อยสำหรับทุกกรณี - ฉันบอกว่ามันจะช้าลงเล็กน้อยถ้าคุณค้นหาคู่ที่ตรงกัน แน่นอนว่าการค้นหาด้วย LIKE และใช้ wildcard โดยเฉพาะที่จุดเริ่มต้นและจุดสิ้นสุดของรายการค้นหาของคุณนั้นช้ากว่ามากไม่ต้องสงสัยเลยว่า
marc_s

และใช่ฉันเห็นด้วย - เราควรมีแนวทางที่ชัดเจนว่าควรใช้ LIKE เมื่อใด (เฉพาะเมื่อคุณต้องการค้นหาด้วย wildcard) แต่แล้วอีกครั้ง - ในทางทฤษฎีไม่มีความแตกต่างระหว่างทฤษฎีและการปฏิบัติ แต่ในทางปฏิบัติ .......
marc_s

6

การใช้ = หลีกเลี่ยงสัญลักษณ์แทนและอักขระพิเศษขัดแย้งกันในสตริงเมื่อคุณสร้างแบบสอบถามในขณะใช้งาน

สิ่งนี้ทำให้ชีวิตของโปรแกรมเมอร์ง่ายขึ้นโดยไม่ต้องหลีกเลี่ยงอักขระพิเศษทั้งหมดที่อาจหลุดใน LIKE clause และไม่สร้างผลลัพธ์ที่ต้องการ ท้ายที่สุด = เป็นสถานการณ์กรณีการใช้งาน 99% มันจะเป็นความเจ็บปวดที่ต้องหลบหนีพวกเขาทุกครั้ง

ตาที่ '90s

ฉันยังสงสัยว่ามันช้าลงเล็กน้อย แต่ฉันสงสัยว่ามันสำคัญถ้าไม่มี wildcard ในรูปแบบ


6

ไปยังที่อยู่ที่คำถามเดิมเกี่ยวกับประสิทธิภาพมันลงมาเพื่อการใช้ดัชนี เมื่อตารางการสแกนง่าย ๆ เกิดขึ้น "LIKE" และ "=" มีเหมือนกัน เมื่อมีส่วนร่วมของดัชนีมันขึ้นอยู่กับว่าประโยค LIKE เกิดขึ้นอย่างไร โดยเฉพาะอย่างยิ่งสถานที่ของตัวแทนคืออะไร?


พิจารณาสิ่งต่อไปนี้:

CREATE TABLE test(
    txt_col  varchar(10) NOT NULL
)
go

insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
  from master..spt_values a, master..spt_values b
go

CREATE INDEX IX_test_data 
    ON test (txt_col);
go 

--Turn on Show Execution Plan
set statistics io on

--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost

--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure

--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO

--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO


DROP TABLE test

อาจมีความแตกต่างเล็กน้อยในการสร้างแผนแบบสอบถามเมื่อใช้ "=" vs "LIKE"


4

นอกเหนือจาก wildcard ความแตกต่างระหว่าง=AND LIKEจะขึ้นอยู่กับชนิดของเซิร์ฟเวอร์ SQL และชนิดคอลัมน์

นำตัวอย่างนี้:

CREATE TABLE testtable (
  varchar_name VARCHAR(10),
  char_name CHAR(10),
  val INTEGER
);

INSERT INTO testtable(varchar_name, char_name, val)
    VALUES ('A', 'A', 10), ('B', 'B', 20);

SELECT 'VarChar Eq Without Space', val FROM testtable WHERE varchar_name='A'
UNION ALL
SELECT 'VarChar Eq With Space', val FROM testtable WHERE varchar_name='A '
UNION ALL
SELECT 'VarChar Like Without Space', val FROM testtable WHERE varchar_name LIKE 'A'
UNION ALL
SELECT 'VarChar Like Space', val FROM testtable WHERE varchar_name LIKE 'A '
UNION ALL
SELECT 'Char Eq Without Space', val FROM testtable WHERE char_name='A'
UNION ALL
SELECT 'Char Eq With Space', val FROM testtable WHERE char_name='A '
UNION ALL
SELECT 'Char Like Without Space', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'Char Like With Space', val FROM testtable WHERE char_name LIKE 'A '
  • การใช้MS SQL Server 2012ช่องว่างต่อท้ายจะถูกละเว้นในการเปรียบเทียบยกเว้นเมื่อชนิดคอลัมน์LIKEVARCHAR

  • ใช้MySQL 5.5 , ช่องว่างต่อท้ายจะถูกละเว้นสำหรับ=แต่ไม่ได้LIKEทั้งที่มีและCHARVARCHAR

  • การใช้PostgreSQL 9.1ช่องว่างมีความสำคัญทั้งกับ=และLIKEใช้VARCHARแต่ไม่ใช่กับCHAR(ดูเอกสารประกอบ )

    ลักษณะการทำงานที่มีความแตกต่างยังมีLIKECHAR

    การใช้ข้อมูลเดียวกันข้างต้นการใช้CASTชื่อคอลัมน์อย่างชัดเจนก็สร้างความแตกต่างได้เช่นกัน :

    SELECT 'CAST none', val FROM testtable WHERE char_name LIKE 'A'
    UNION ALL
    SELECT 'CAST both', val FROM testtable WHERE
        CAST(char_name AS CHAR) LIKE CAST('A' AS CHAR)
    UNION ALL
    SELECT 'CAST col', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE 'A'
    UNION ALL
    SELECT 'CAST value', val FROM testtable WHERE char_name LIKE CAST('A' AS CHAR)

    นี่จะส่งคืนแถวสำหรับ "CAST ทั้งสอง" และ "CAST col" เท่านั้น


2

คำหลัก LIKE ไม่ต้องสงสัยเลยว่ามาพร้อมกับ "แท็กราคาตามประสิทธิภาพ" ที่แนบมา ที่กล่าวว่าหากคุณมีช่องป้อนข้อมูลที่อาจรวมอักขระไวด์การ์ดที่จะใช้ในการค้นหาของคุณฉันขอแนะนำให้ใช้ LIKE เฉพาะเมื่ออินพุตมีหนึ่งในไวลด์การ์ด มิฉะนั้นให้ใช้มาตรฐานเท่ากับการเปรียบเทียบ

ขอแสดงความนับถืออย่างสูง...


1

จริง ๆ แล้วมันลงมากับสิ่งที่คุณต้องการให้แบบสอบถามทำ หากคุณหมายถึงการจับคู่ที่ตรงกันให้ใช้ = หากคุณหมายถึงการจับคู่ที่คลุมเครือให้ใช้ LIKE การพูดในสิ่งที่คุณหมายถึงมักเป็นนโยบายที่ดีพร้อมรหัส


1

ใน Oracle เครื่องหมาย 'like' ที่ไม่มี wildcard จะส่งคืนผลลัพธ์เหมือนกับ 'เท่ากับ' แต่อาจต้องการการประมวลผลเพิ่มเติม Tom Kyteระบุว่า Oracle จะปฏิบัติต่อ 'like' โดยไม่มี wildcards เป็น 'equals' เมื่อใช้ตัวอักษร แต่ไม่ใช่เมื่อใช้ตัวแปรที่ผูกไว้


0

=และLIKEไม่เหมือนกัน

  1. = ตรงกับสตริงที่แน่นอน
  2. LIKE ตรงกับสตริงที่อาจมีอักขระตัวแทน (%)

2
คำตอบไม่เพียงพอ

มันสามารถใช้งานได้โดยไม่มีสัญลักษณ์แทนคำถามที่ถามถึงความแตกต่างในกรณีเดียวกัน
M-Razavi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.