MariaDB: Почему LOCATE использует сравнение с учетом регистра? - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть база данных со следующими данными в столбце «Имя»:

enter image description here

Однако выполнение следующего запроса возвращает неверные результаты:

SELECT `e`.`Id`, `e`.`Name`
      FROM `Regions` AS `e`
      WHERE (LOCATE('s', `e`.`Name`) > 0)

Возвращает:

Calgary Northeast
Test Location
Calgary West

Однако, это не возвращение "Южного Британской Колумбии", который имеет s в начале. Согласно документам MariaDB, функция LOCATE не учитывает регистр (см .: https://mariadb.com/kb/en/library/locate/),, поэтому я ожидаю, что "Southern BC" и "Calgary South" будут отображаться в результатах. Ясно, что мой запрос выполняет сравнение с учетом регистра, но я не знаю почему. Все мои параметры сортировки установлены на utf8mb4_general_ci везде, где я проверял.

SELECT TABLE_SCHEMA
    , TABLE_NAME
    , TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME ='Regions';

возвращает utf8mb4_general_ci

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

возврат

collation_connection    utf8mb4_general_ci
collation_database  utf8mb4_general_ci
collation_server    utf8mb4_general_ci

Я бегу 10.3.10-MariaDB-1:10.3.10+maria~bionic-log

Есть идеи об этом поведении?

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Я не могу воспроизвести проблему:

MariaDB [_]> SELECT VERSION();
+-----------------+
| VERSION()       |
+-----------------+
| 10.3.10-MariaDB |
+-----------------+
1 row in set (0.000 sec)

MariaDB [_]> SHOW VARIABLES LIKE 'character_set%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.002 sec)

MariaDB [_]> SHOW VARIABLES LIKE 'collation%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_general_ci |
| collation_database   | utf8mb4_general_ci |
| collation_server     | utf8mb4_general_ci |
+----------------------+--------------------+
3 rows in set (0.001 sec)

MariaDB [_]> DROP TABLE IF EXISTS `Regions`;
Query OK, 0 rows affected (0.005 sec)

MariaDB [_]> CREATE TABLE IF NOT EXISTS `Regions` (
    ->   `Name` VARCHAR(255)
    -> );
Query OK, 0 rows affected (0.010 sec)

MariaDB [_]> INSERT INTO `Regions`
    -> VALUES
    ->   ('Calgary South'),
    ->   ('Calgary Northeast'),
    ->   ('Calgary Location'),
    ->   ('Location'),
    ->   ('Calgary West'),
    ->   ('Calgary BC'),
    ->   ('Southern BC');
Query OK, 7 rows affected (0.004 sec)
Records: 7  Duplicates: 0  Warnings: 0

MariaDB [_]> SELECT `Name`
    -> FROM `Regions`;
+-------------------+
| Name              |
+-------------------+
| Calgary South     |
| Calgary Northeast |
| Calgary Location  |
| Location          |
| Calgary West      |
| Calgary BC        |
| Southern BC       |
+-------------------+
7 rows in set (0.000 sec)

MariaDB [_]> SELECT `Name`
    -> FROM `Regions`
    -> WHERE LOCATE('s', `Name`) > 0;
+-------------------+
| Name              |
+-------------------+
| Calgary South     |
| Calgary Northeast |
| Calgary West      |
| Southern BC       |
+-------------------+
4 rows in set (0.001 sec)
0 голосов
/ 14 ноября 2018

Пожалуйста, укажите SHOW CREATE TABLE. Сличение name является значительным.

Если вы используете параметры сортировки по умолчанию или другие ..._ci параметры сортировки, тогда это подходит:

WHERE e.name LIKE '%s%'

чтобы поймать прописные и строчные буквы s.

LIKE и REGEXP подходят для проверки подстрок. LOCATE подходит для поиска позиции чего-либо в строке.

0 голосов
/ 14 ноября 2018

Вы можете сделать либо

SELECT `e`.`Id`, `e`.`Name`
      FROM `Regions` AS `e`
      WHERE (LOCATE('s', `e`.`Name`) > 0) OR (LOCATE('S', `e`.`Name`) > 0)

ИЛИ

SELECT `e`.`Id`, `e`.`Name`
          FROM `Regions` AS `e`
          WHERE e.name like '%S%' or e.name like '%s%'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...