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.