Вибір регістру MySQL нечутливий


242

Чи може хто-небудь сказати мені, чи SELECTзапит MySQL чутливий до регістру чи малочутливий до регістру? А якщо ні, то який запит я мав би відправити, щоб я міг зробити щось на кшталт:

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

Де в дійсності, реальна цінність Valueє IAreSavage.


44
Зрештою, це залежить від поданих посилань - якщо це "_ci" (нечутливий до регістру) або "_cs" (залежно від регістру)
Jovan Perovic

15
Це одне погано сформульоване питання;). Половина відповідей показує вам, як зробити порівняння з урахуванням регістру, половина націлена на залежність від регістру. І лише 1 говорить про те, що за замовчуванням насправді справа нечутлива. :) Варто відзначити, що нечутливість випадку працює навіть тоді, коли ви робите порівняння на кшталт'value' in ('val1', 'val2', 'val3')
SaltyNuts

5
Чоловік @SaltyNuts, прочитавши це запитання через 7 років і зрозумівши, скільки я нобу, це бентежить! Я міг щойно прочитати документацію, і відповідь, як у першому реченні про твердження SELECT ...
NoodleOfDeath

Щоб додати те, що сказав @JovanPerovic, utf8_bin також робить його чутливим до регістру. Не впевнений, чи це тоді існувало
Chiwda

Відповіді:


494

Вони нечутливі до регістру , якщо ви не зробите бінарне порівняння .


3
Я в основному погоджуюся з коментарем Тіма, я не думаю, що найкращий спосіб впоратися з вашими цінностями скрізь - схоже на вирішення проблеми. Але я визнаю, це часом має сенс і простіше. (Колін все ж згадував кращі результати) У нас були історичні дані, переміщені в таблицю mysql, яка порушила застарілу логіку через певні значення стовпців, що мають нечутливий регістр. Нам потрібно було знати різницю між "GE1234" та "ge1234", вони повинні бути унікальними і таким чином залишатися в журналі. Ми встановимо наш стовпець для створення оператора таблиці таким чином: varchar (20) CHARACTER SET utf8 COLLATE utf8_bin
gregthegeek

19
Я не знаю, чому стільки людей проголосували за це. Тут чітко зазначено dev.mysql.com/doc/refman/5.0/en/case-sensibility.html, що "... це означає, що для алфавітних символів порівняння залежать від регістру". Тож якщо я шукаю "DickSavagewood", він НЕ підбере "dicksavagewood". Зробимо те ж саме з МИСЛОМ () БУДЕ забрати. Тож моя відповідь на питання: у вашому конкретному випадку ВИБІР дійсно відрізняється від регістру.
Luftwaffle

10
@ user1961753: Прочитайте ще раз: "Для двійкових рядків (varbinary, blob) ... буде залежно від регістру".
Марк Б

1
@MarcB це посилання зараз розірвано. Ви могли б це виправити? :)
Фітер

5
Як сказав Йован, це залежить від співставлення, тому ця відповідь є в значній мірі неправильною.
phil294

117

Ви можете зменшити малі значення та переданий параметр:

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

Ще одним (кращим) способом було б використання COLLATEоператора, як сказано в документації


21
Як би SELECTвиглядало це твердження, використовуючи COLLATEтоді?
Так, Баррі

11
На згадуваній сторінці документації вище, йдеться про те, що "порівняння бінарних рядків за замовчуванням нечутливі до регістру".
Запитаний Аронсон

9
Жахливо, як багато людей схвалили цю відповідь. Як пояснює @Marc вище, порівняння не залежать від регістру. Вам потрібно зрозуміти складання та індекси та правильно їх налаштувати - використання рядкових перетворень на кшталт LOWER()або довільного COLLATEзастереження може повністю обійти індекс, і з часом, у міру зростання вашої таблиці, це може мати різкі наслідки для продуктивності. Ймовірно, це імена користувачів, які ви шукаєте? Використовуйте порівняння з урахуванням регістру та додайте унікальний індекс до стовпця. Використовуйте EXPLAINдля підтвердження того, що індекс використовується.
mindplay.dk

1
Я збирався сказати те саме, що mindplay.dk ... верхній () і нижній () обходять індекс і безпосередньо впливають на продуктивність у великих таблицях бази даних.
Гтодоров

Я згоден як mindplay.dk, так і думки GTodorov. Будьте обережні, використовуючи якийсь метод на цільовому стовпчику, де пункт. Покажчик стовпця може бути марним. Використовуйте ПОЯСНЕННЯ!
трапер

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 * FROM myTable WHERE BINARY 'something' = 'Something')?
Джиммі

@Jimmy Що саме ти маєш на увазі? Код працює. Коли одна зі сторін у порівнянні приведена до двійкового, порівняння робиться двійковим.
Джорі

@Jori О, я думаю, що я неправильно прочитав - я подумав, що один із двох прикладів має BINARY з обох сторін рівних.
Джиммі

Я просто проголосував за це, тому що це справді правильна відповідь. Згідно з документацією на веб-сайті MySQL, вони кажуть, що краще використовувати команду BINARY, ніж намагатися набрати свої слова / запит певною мовою, оскільки команда BINARY говорить залишити все як є, і використовувати саме так, як вона представлена. Тож, коли я прийшов шукати відповідь - дві відповіді тут привели мене до веб-сайту MySQL і подивитися на їх документальну документацію. Використовувати BINARY краще. Переклад може спричинити інші проблеми.
Марк Меннінг

43

Порівняння чутливі до регістру , якщо стовпець використовує параметри сортування , який закінчується _ci(наприклад, по замовчуванням latin1_general_ci параметри сортування) , і вони чутливі до регістру , якщо стовпець використовує параметри сортування , яка закінчується _csабо _bin(таких , як utf8_unicode_csі utf8_binсортування).

Перевірте порівняння

Ви можете перевірити свій сервер , базу даних і підключення сортування з допомогою:

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 colnameCOLLATE latin1_general_cs = 'ключове слово'

latin1_general_cs є загальним чи стандартним порівнянням у більшості баз даних.



9

За замовчуванням не враховує регістр, але наступне найважливіше, на що слід звернути увагу, - це, як створена таблиця в першу чергу, тому що ви можете вказати чутливість регістру під час створення таблиці.

Сценарій нижче створює таблицю. Зверніть увагу, що внизу написано "COLLATE latin1_general_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-запити-регістр.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-sensibility.html


1
+1 - Сценарій написання нечутливих запитів про регістри, а потім виходу з ладу на Linuxes трапився багато в нашому проекті
Вік

@Vic У мене те саме питання зі своїм проектом. Скажіть, будь ласка, як ви це виправили?
Камран Ахмед

@KamranAhmed, вам потрібно використовувати обкладинки назв таблиць саме так, як вони відображаються в сценаріях створення
Vic

@Vic це було б в останню чергу, тому що я повинен був би змінити буквально багато запитів. Мені було цікаво, чи знайдеться якийсь простий спосіб зробити це. Дякую, хоча!
Камран Ахмед

@KamranAhmed, спробуйте змінити, lower_case_table_nameяк зазначено у відповіді, яку ми коментуємо,
Вік

1

В даний час прийняте рішення є переважно правильним.

Якщо ви використовуєте небінарний рядок (CHAR, VARCHAR, TEXT), порівняння не залежать від регістру відповідно до замовчуванням.

Якщо ви використовуєте двійковий рядок (BINARY, VARBINARY, BLOB), порівняння залежать від регістру, тому вам потрібно буде використовувати, LOWERяк описано в інших відповідях.

Якщо ви не використовуєте порівняння за замовчуванням і використовуєте небінарний рядок, чутливість регістру визначається обраним порівнянням.

Джерело: https://dev.mysql.com/doc/refman/8.0/en/case-sensibility.html . Читайте уважно. Деякі інші помиляються, кажучи, що порівняння обов'язково залежать від регістру або не чутливі. Це не так.


0

Можна спробувати. сподіваюся, що це стане в нагоді.

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

0

Поля рядків з набором двійкового прапора завжди залежать від регістру. Якщо вам потрібен регістр пошуку небінарного текстового поля, використовуйте це: SELECT 'test' REGEXP BINARY 'TEST' КАК РЕЗУЛЬТАТ;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.