กรณี MySQL เลือกไม่สำคัญ


242

ใครสามารถบอกฉันว่าSELECTแบบสอบถามMySQL เป็นกรณี ๆ ไปหรือตามตัวพิมพ์เล็ก - ใหญ่โดยค่าเริ่มต้น? และถ้าไม่ฉันจะต้องส่งคำถามใดเพื่อให้ฉันสามารถทำสิ่งต่อไปนี้

SELECT * FROM `table` WHERE `Value` = "iaresavage"

คุณค่าที่แท้จริงของValueคือIAreSavageที่ไหน


44
ท้ายที่สุดมันขึ้นอยู่กับการเปรียบเทียบการยื่น - ถ้าเป็น '_ci' (case-insensitive) หรือ '_cs' (case-sensitive)
Jovan Perovic

15
นี่เป็นหนึ่งคำถามที่พูดไม่ดี;) คำตอบครึ่งหนึ่งแสดงให้คุณเห็นว่าจะต้องทำการเปรียบเทียบแบบไม่สนใจขนาดตัวพิมพ์หรือไม่ และมีเพียง 1 คนเท่านั้นที่บอกคุณว่าค่าเริ่มต้นนั้นแท้จริงแล้วไม่คำนึงถึงขนาดตัวพิมพ์ :) มันเป็นที่น่าสังเกตว่ากรณีไวไม่ทำงานแม้เมื่อคุณทำการเปรียบเทียบเช่น'value' in ('val1', 'val2', 'val3')
SaltyNuts

5
@SaltyNuts คนอ่านคำถามนี้ 7 ปีต่อมาและตระหนักถึง noob ที่ฉันอาย! ฉันสามารถอ่านเอกสารและคำตอบก็เหมือนประโยคแรกเกี่ยวกับคำสั่ง SELECT ...
NoodleOfDeath

หากต้องการเพิ่มสิ่งที่ @JovanPerovic กล่าวไว้ utf8_bin ยังทำให้เป็นกรณี ๆ ไป ไม่แน่ใจว่ามันมีอยู่จริงหรือไม่
Chiwda

คำตอบ:


494

พวกเขาเป็นกรณีตายถ้าคุณทำเปรียบเทียบไบนารี


3
ฉันเห็นด้วยกับความคิดเห็นของ Tim เป็นส่วนใหญ่ฉันไม่คิดว่าการทำ "ต่ำกว่า ()" ในคุณค่าของคุณทุกที่เป็นวิธีที่ดีที่สุดในการจัดการมัน แต่ฉันยอมรับมันในบางครั้งมันสมเหตุสมผลและง่ายขึ้น (โคลินไม่พูดถึงเรียงเป็นดีกว่า) เรามีข้อมูลประวัติย้ายลงในตาราง mysql ซึ่งทำลายตรรกะดั้งเดิมเนื่องจากค่าคอลัมน์บางอย่างมีกรณีตาย เราจำเป็นต้องรู้ถึงความแตกต่างระหว่าง "GE1234" และ "ge1234" พวกเขาจำเป็นต้องมีเอกลักษณ์และเข้าสู่ระบบด้วยวิธีดังกล่าว เราตั้งค่าคอลัมน์ของเราในการสร้างคำสั่งตารางด้วยวิธีนี้แทน: varchar (20) ชุดอักขระ UTF8 COLLATE utf8_bin
gregthegeek

19
ฉันไม่รู้ว่าทำไมคนจำนวนมากโหวตเรื่องนี้ มันระบุไว้อย่างชัดเจนที่นี่dev.mysql.com/doc/refman/5.0/en/case-sensitivity.htmlว่า "... นี่หมายความว่าสำหรับตัวอักษรที่เป็นตัวอักษรการเปรียบเทียบจะคำนึงถึงตัวพิมพ์เล็กและตัวอักษร" ดังนั้นถ้าฉันมองหา 'DickSavagewood' มันจะไม่ไปรับ 'dicksavagewood' ทำแบบเดียวกันกับ LOWER () จะหยิบมันขึ้นมา ดังนั้นคำตอบของฉันสำหรับคำถาม: ในกรณีของคุณโดยเฉพาะ SELECT เป็นแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก
Luftwaffle

10
@ user1961753: อ่านอีกครั้ง: "สำหรับสตริงไบนารี (varbinary, blob) ... จะต้องตรงตามตัวพิมพ์ใหญ่ - เล็ก"
Marc B

1
@MarcB ลิงก์นี้เสียแล้ว คุณสามารถแก้ไขได้หรือไม่ :)
Phiter

5
ดังที่โจแวนกล่าวขึ้นอยู่กับการเปรียบเทียบดังนั้นคำตอบนี้ค่อนข้างผิด
phil294

117

คุณสามารถพิมพ์เล็กและค่าผ่านพารามิเตอร์:

SELECT * FROM `table` WHERE LOWER(`Value`) = LOWER("IAreSavage")

วิธีอื่น (ดีกว่า) คือใช้ตัวCOLLATEดำเนินการตามที่กล่าวไว้ในเอกสารประกอบ


21
SELECTข้อความนี้มีลักษณะอย่างไรเมื่อใช้COLLATEแล้ว?
ใช่ Barry

11
มันบอกว่าในหน้าเอกสารอ้างอิงที่อ้างถึงข้างต้นว่า "การเปรียบเทียบสตริงที่ไม่ใช่ไบนารีจะไม่ตรงตามตัวพิมพ์เล็กและใหญ่"
ต่อภารกิจ Aronsson

9
น่ากลัวแค่ไหนที่มีคนตอบคำถามนี้จำนวนมาก ดังที่ @Marc อธิบายไว้ข้างต้นการเปรียบเทียบจึงไม่คำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก คุณต้องเข้าใจการเรียงและดัชนีและกำหนดค่าอย่างเหมาะสม - การใช้การแปลงสตริงเช่นLOWER()หรือCOLLATEประโยคใด ๆสามารถข้ามดัชนีได้อย่างสมบูรณ์และเมื่อเวลาผ่านไปเมื่อตารางของคุณเติบโตขึ้น เป็นไปได้ไหมว่าชื่อผู้ใช้ที่คุณกำลังค้นหาอยู่ ใช้การเปรียบเทียบแบบ case-insensitive และเพิ่มดัชนีเฉพาะลงในคอลัมน์ ใช้EXPLAINเพื่อยืนยันว่าดัชนีกำลังถูกใช้
mindplay.dk

1
ฉันกำลังจะพูดเช่นเดียวกับ mindplay.dk ... upper () และ lower () ข้ามดัชนีและส่งผลโดยตรงต่อประสิทธิภาพการทำงานในตารางฐานข้อมูลขนาดใหญ่
GTodorov

ฉันเห็นด้วยทั้งความคิดเห็นของ mindplay.dk และ GTodorov ระมัดระวังการใช้วิธีการบางอย่างในคอลัมน์เป้าหมายที่ข้อ ดัชนีของคอลัมน์อาจไร้ประโยชน์ ใช้อธิบาย!
traeper

51

ใช้ไบนารี

นี่คือการเลือกที่ง่าย

SELECT * FROM myTable WHERE 'something' = 'Something'

= 1

นี่คือการเลือกด้วยไบนารี

SELECT * FROM myTable WHERE BINARY 'something' = 'Something'

หรือ

SELECT * FROM myTable WHERE 'something' = BINARY 'Something'

= 0


3
เมื่อใดจึงควรใช้ BINARY ที่ด้านใดด้านหนึ่งของ = (SELECT * จาก myTable WHERE BINARY 'some' = 'Something')
Jimmy

@Jimmy คุณหมายถึงอะไรกันแน่? รหัสใช้งานได้ เมื่อด้านหนึ่งในการเปรียบเทียบถูกส่งไปยังไบนารีการเปรียบเทียบจะถูกทำแบบไบนารี
Jori

@ โจริโอ้ฉันคิดว่าฉันเข้าใจผิด - ฉันคิดว่าหนึ่งในสองตัวอย่างนี้มี BINARY ทั้งสองด้านเท่ากัน
Jimmy

ฉันเพิ่งโหวตสิ่งนี้เพราะนี่คือคำตอบที่ถูกต้อง ตามเอกสารที่เว็บไซต์ MySQL พวกเขาบอกว่ามันเป็นการดีกว่าที่จะใช้คำสั่ง BINARY มากกว่าที่จะพยายามพิมพ์คำ / คำขอของคุณเป็นภาษาเฉพาะเพราะคำสั่ง BINARY บอกว่าจะปล่อยทุกอย่างเหมือนที่มันเป็นและใช้อย่างถูกต้อง มันถูกนำเสนอ ดังนั้นเมื่อฉันมาหาคำตอบ - ทั้งสองคำตอบที่นี่ทำให้ฉันไปที่เว็บไซต์ MySQL และดูเอกสารของพวกเขา ใช้ BINARY ดีกว่า การแปลอาจทำให้เกิดปัญหาอื่น ๆ
Mark Manning

43

การเปรียบเทียบเป็นกรณีตายเมื่อคอลัมน์ใช้เปรียบเทียบซึ่งจบลงด้วย_ci(เช่นเริ่มต้น latin1_general_ciการเปรียบเทียบ) และพวกเขามีกรณีที่สำคัญเมื่อคอลัมน์ใช้การเปรียบเทียบที่ปลายด้วย_csหรือ_bin(เช่นutf8_unicode_csและutf8_bin collations)

ตรวจสอบการเรียง

คุณสามารถตรวจสอบของเซิร์ฟเวอร์ , ฐานข้อมูลและการเชื่อมต่อเรียงโดยใช้:

mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

และคุณสามารถตรวจสอบการเรียงตารางของคุณโดยใช้:

mysql> SELECT table_schema, table_name, table_collation 
       FROM information_schema.tables WHERE table_name = `mytable`;
+----------------------+------------+-------------------+
| table_schema         | table_name | table_collation   |
+----------------------+------------+-------------------+
| myschema             | mytable    | latin1_swedish_ci |

เปลี่ยนการเรียงหน้า

คุณสามารถเปลี่ยนการเรียงฐานข้อมูลตารางหรือคอลัมน์เป็นแบบตรงตามตัวพิมพ์ใหญ่ - เล็กได้ดังนี้:

-- Change database collation
ALTER DATABASE `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;

-- or change table collation
ALTER TABLE `table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- or change column collation
ALTER TABLE `table` CHANGE `Value` 
    `Value` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;

การเปรียบเทียบของคุณควรเป็นแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก


25

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

WHERE `colname` = 'keyword'

หรือ

WHERE `colname` = 'KeyWord'

และคุณจะได้รับผลลัพธ์เดียวกันผลเดียวกันนั่นคือพฤติกรรมเริ่มต้นของ MySQL

หากคุณต้องการเปรียบเทียบให้ตรงตามตัวพิมพ์ใหญ่และตัวพิมพ์เล็กคุณสามารถเพิ่มCOLLATEเช่นนี้:

WHERE `colname` COLLATE latin1_general_cs = 'KeyWord'

SQL นั้นจะให้ผลลัพธ์ที่แตกต่างกับอันนี้: WHERE colname COLLATE latin1_general_cs = 'keyword'

latin1_general_cs เป็นเรื่องปกติหรือการเปรียบเทียบค่าเริ่มต้นในฐานข้อมูลส่วนใหญ่



9

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

สคริปต์ด้านล่างสร้างตาราง สังเกตลงที่ด้านล่างว่า "COLLATE latin1_general_cs" cs นั้นในตอนท้ายหมายถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ หากคุณต้องการให้ตารางของคุณมีความรู้สึกตัวพิมพ์เล็กและตัวพิมพ์ใหญ่คุณอาจจะปล่อยส่วนนั้นออกหรือใช้ "COLLATE latin1_general_ci"

   CREATE Table PEOPLE (

       USER_ID  INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

       FIRST_NAME  VARCHAR(50) NOT NULL,
       LAST_NAME  VARCHAR(50) NOT NULL,

       PRIMARY KEY (USER_ID)

   )

   ENGINE=MyISAM DEFAULT CHARACTER SET latin1
    COLLATE latin1_general_cs AUTO_INCREMENT=0;

หากโครงการของคุณเป็นเช่นนั้นคุณสามารถสร้างตารางของคุณเองมันก็เป็นเรื่องเหมาะสมที่จะระบุการตั้งค่าความไวกรณีและปัญหาของคุณเมื่อคุณสร้างตาราง


3

SQL Select ไม่คำนึงถึงขนาดตัวพิมพ์

ลิงก์นี้สามารถแสดงวิธีการใช้ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่: http://web.archive.org/web/20080811231016/http://sqlserver2000.databases.aspfaq.com:80/how-can-i-make-my- SQL แบบสอบถามกรณี-sensitive.html


4
ขึ้นอยู่กับฐานข้อมูลของคุณตามที่ระบุไว้ที่อื่นที่นี่พวกเขาสามารถใช้ mysql
vickirk


2

ยังทราบว่าชื่อตารางเป็นกรณีที่สำคัญบน Linux เว้นแต่คุณจะตั้งค่าlower_case_table_nameคำสั่งการตั้งค่าไป1 นี่เป็นเพราะตารางถูกแสดงด้วยไฟล์ที่คำนึงถึงขนาดตัวพิมพ์ใน Linux

โดยเฉพาะอย่างยิ่งระวังการพัฒนาบน Windows ซึ่งไม่คำนึงถึงขนาดตัวพิมพ์และปรับใช้กับการผลิต ตัวอย่างเช่น:

"SELECT * from mytable" 

เทียบกับตาราง myTable จะประสบความสำเร็จใน Windows แต่ล้มเหลวใน Linux อีกครั้งเว้นแต่ว่ามีการตั้งค่าคำสั่งข้างต้น

การอ้างอิงที่นี่: http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html


1
1 - สถานการณ์ของการเขียนคำสั่งกรณีตายแล้วล้มเหลวใน Linuxes ที่เกิดขึ้นมากในโครงการของเรา
วิก

@Vic ฉันมีปัญหาเดียวกันกับโครงการของฉัน คุณช่วยกรุณาบอกฉันว่าคุณแก้ไขได้อย่างไร
Kamran Ahmed

@KamranAhmed, คุณจำเป็นต้องใช้ปลอกของชื่อตารางตรงตามที่ปรากฏในสคริปต์สร้าง
วิก

@Vic ที่เป็นทางเลือกสุดท้ายเนื่องจากฉันต้องแก้ไขข้อความค้นหามากมาย ฉันสงสัยว่าถ้ามีวิธีง่าย ๆ ที่จะทำ ขอบคุณนะ!
Kamran Ahmed

@KamranAhmed พยายามที่จะเปลี่ยนlower_case_table_nameตามที่ระบุไว้ในคำตอบที่เรากำลังแสดงความคิดเห็นภายใต้
วิก

1

โซลูชันที่ยอมรับในปัจจุบันส่วนใหญ่ถูกต้อง

หากคุณใช้สตริงที่ไม่ใช่ไบนารี (CHAR, VARCHAR, TEXT) การเปรียบเทียบจะไม่คำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็กและเล็กตามการจัดเรียงเริ่มต้น

หากคุณใช้สตริงไบนารี (BINARY, VARBINARY, BLOB) การเปรียบเทียบจะคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ดังนั้นคุณต้องใช้ LOWERตามที่อธิบายไว้ในคำตอบอื่น ๆ

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

ที่มา: https://dev.mysql.com/doc/refman/8.0/en/case-sensitivity.html อ่านอย่างใกล้ชิด บางคนเข้าใจผิดว่าเป็นการเปรียบเทียบว่าต้องคำนึงถึงตัวพิมพ์เล็กหรือตัวพิมพ์ใหญ่ กรณีนี้ไม่ได้.


0

คุณสามารถลอง หวังว่ามันจะมีประโยชน์

SELECT * FROM `table` WHERE `Value` COLLATE latin1_general_cs = "IAreSavage"

0

ฟิลด์สตริงที่มีชุดแฟล็กไบนารีจะคำนึงถึงขนาดตัวพิมพ์เสมอ หากคุณต้องการค้นหาตัวพิมพ์เล็กและใหญ่สำหรับฟิลด์ข้อความไบนารีที่ไม่ใช่ให้ใช้ตัวเลือกนี้: เลือก 'ทดสอบ' REGEXP BINARY 'ทดสอบ' เป็นผลลัพธ์

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