Spec-Zone.ru › MySQL 5.7

10.8.4 Принудимость сортировки в выражениях

В подавляющем большинстве операторов очевидно, какую сортировку MySQL использует для разрешения операции сравнения. Например, в следующих случаях должно быть ясно, что сортировка — это сортировка столбца x:

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

Однако при использовании нескольких операндов может возникнуть неоднозначность. Например, данное оператор выполняет сравнение столбца x со строковым литералом 'Y':

SELECT x FROM T WHERE x = 'Y';

Если у x и 'Y' одинаковая сортировка, то нет неоднозначности относительно сортировки, которую следует использовать для сравнения. Но если у них разные сортировки, какая сортировка должна использоваться для сравнения: сортировка x или сортировка 'Y'? Обе x и 'Y' имеют сортировку, так какая сортировка имеет приоритет?

Смешение сортировок может также возникать и в контекстах, отличных от сравнения. Например, операция конкатенации с несколькими аргументами, такая как CONCAT(x,'Y'), объединяет свои аргументы в одну строку. Какой сортировкой должна обладать результат?

Для разрешения подобных вопросов MySQL проверяет, может ли сортировка одного элемента быть принудительно преобразована в сортировку другого элемента. MySQL присваивает значения принудительности следующим образом:

  • Оператор явного COLLATE имеет принудительность 0 (не подлежит принудительному преобразованию).

  • Конкатенация двух строк с разными сортировками имеет принудительность 1.

  • Сортировка столбца или параметра хранимой процедуры или локальной переменной имеет принудительность 2.

  • “Системная константа” (строка, возвращаемая функциями, такими как USER() или VERSION()) имеет принудительность 3.

  • Сортировка литерала имеет принудительность 4.

  • Сортировка числового или временного значения имеет принудительность 5.

  • NULL или выражение, полученное из NULL, имеет принудительность 6.

MySQL использует значения принудительности по следующим правилам для разрешения неоднозначностей:

  • Используйте сортировку с наименьшим значением принудительности.

  • Если обе стороны имеют одинаковую принудительность, то:

    • Если обе стороны Unicode или обе стороны не Unicode, это ошибка.

    • Если у одной из сторон есть настроенный набор символов Unicode, а у другой — не Unicode, сторона с настроенным набором символов Unicode выигрывает, и выполняется автоматическое преобразование набора символов для стороны без Unicode. Например, следующее оператор не возвращает ошибку:

      SELECT CONCAT(utf8_column, latin1_column) FROM t1;
      

      Он возвращает результат, имеющий набор символов utf8 и ту же сортировку, что и utf8_column. Значения latin1_column автоматически преобразуются в utf8 перед конкатенацией.

    • Для операции с операндами из одного набора символов, но со смешанными сортировками _bin и _ci или _cs, используется сортировка _bin. Это аналогично тому, как операции, смешивающие небинарные и бинарные строки, оценивают операнды как бинарные строки, применённые к сортировкам, а не к типам данных.

Хотя автоматическое преобразование не является частью стандарта SQL, в стандарте говорится, что каждый набор символов (с точки зрения поддерживаемых символов) является «подмножеством» Unicode. Поскольку хорошо известно, что «то, что относится к надмножеству, может относиться и к подмножеству», мы считаем, что сортировка для Unicode может применяться для сравнений с не-Unicode строками. В более общем плане MySQL использует понятие репертуара наборов символов, который иногда может использоваться для определения отношений подмножества между наборами символов и для обеспечения преобразования операндов в операциях, которые в противном случае могли бы привести к ошибке. См. Раздел 10.2.1, «Репертуар наборов символов».

Следующая таблица иллюстрирует некоторые применения вышеупомянутых правил.

Сравнение Используемая сортировка
column1 = 'A' Используется сортировка column1
column1 = 'A' COLLATE x Используется сортировка 'A' COLLATE x
column1 COLLATE x = 'A' COLLATE y Ошибка

Чтобы определить принудительность строкового выражения, используйте функцию COERCIBILITY() (см. Раздел 12.15, «Функции информации»):

mysql> SELECT COERCIBILITY(_utf8'A' COLLATE utf8_bin);
        -> 0
mysql> SELECT COERCIBILITY(VERSION());
        -> 3
mysql> SELECT COERCIBILITY('A');
        -> 4
mysql> SELECT COERCIBILITY(1000);
        -> 5
mysql> SELECT COERCIBILITY(NULL);
        -> 6

Для неявного преобразования числового или временного значения в строку, например, для аргумента 1 в выражении CONCAT(1, 'abc'), результатом является строка символов (не бинарная), которая имеет набор символов и сортировку, определённые системными переменными character_set_connection и collation_connection. См. Раздел 12.3, «Преобразование типов в процессе вычисления выражений».

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/charset-collation-coercibility.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API