SET @test = 'test';
SELECT COERCIBILITY(@test), COERCIBILITY('test');
--- ---
2 4
Из документации :
COERCIBILITY(str)
Возвращаемые значения имеют значения, указанные в следующей таблице. Более низкие значения имеют более высокий приоритет.
Coercibility Meaning Example
0 Explicit collation Value with COLLATE clause
1 No collation Concatenation of strings with different collations
2 Implicit collation Column value
3 System constant USER() return value
4 Coercible Literal string
5 Ignorable NULL or an expression derived from NULL
Принудительность определяет, что будет преобразовано в что в случае конфликта сопоставления.
Выражение с большей принудительностью будет преобразовано в сопоставление выражения с более низкой принудительностью.
Эта функция полезна для устранения проблем с сопоставлением. Например, эти два запроса возвращают результаты в разном порядке.
Вот этот:
SELECT col
FROM (
SELECT DATABASE() AS col
UNION ALL
SELECT 'X'
) q
ORDER BY
col;
----
'test'
'X'
А вот этот:
SET @t := 'X' COLLATE UTF8_BIN;
SELECT col
FROM (
SELECT DATABASE() AS col
UNION ALL
SELECT @t
) q
ORDER BY
col;
----
'X'
'test'
Почему так?
DATABASE()
- это системная функция, возвращаемые значения которой имеют совокупность 3
и сопоставление базы данных по умолчанию UTF8_GENERAL_CI
.
'X' в первом запросе является строковым литералом с принудительным значением 4
.
Результат UNION
всегда будет иметь наименьшую степень принуждения из всех значений (то есть 3
) и сопоставление выражения с наименьшей степенью сопоставимости:
SELECT col, COERCIBILITY(col), COLLATION(col)
FROM (
SELECT DATABASE() AS col
UNION ALL
SELECT 'X'
) q
ORDER BY
col;
--------
'test', 3, 'utf8_general_ci'
'X', 3, 'utf8_general_ci'
Во втором запросе @t
- это переменная, которая содержит строковое значение с сопоставлением UTF8_BIN
. Поскольку его принудительность ниже, чем у системной функции, в результирующем наборе используется сопоставление переменной.
Соотношение переменных равно 2
, поэтому результат равен как переменным, так и параметрам сортировки:
SET @t := 'X' COLLATE UTF8_BIN;
SELECT col, COERCIBILITY(col), COLLATION(col)
FROM (
SELECT DATABASE() AS col
UNION ALL
SELECT @t
) q
ORDER BY
col;
--------
'X', 2, 'utf8_bin'
'test', 2, 'utf8_bin'