Странное поведение UPPER при выборе

Я пытаюсь выполнить некоторые операции со строками в рамках выбора MySQL, и у меня, похоже, какое-то странное поведение из функции UPPER.

Я пытаюсь вернуть первую букву слова (разделенную пробелами) и преобразовать ее в верхний регистр. Однако, если я использую ПРОПИСНУЮ для одной возвращаемой буквы, я получаю пробел, а если я использую ПРОПИСНУЮ для всего слова до получения первой буквы из него, я получаю первую букву.

Сократив SQL до минимума, я придумал этот тестовый SQL: -

SELECT 
    'verbatim h', 
    SUBSTRING(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' ','verbatim h',' '), ' ', 2), ' ', -1), 1, 1),
    UPPER(SUBSTRING(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' ','verbatim h',' '), ' ', 2), ' ', -1), 1, 1)),
    SUBSTRING(UPPER(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' ','verbatim h',' '), ' ', 2), ' ', -1)), 1, 1)

Это берет строку «дословно h», объединяет пробелы с обоих концов, а затем получает строку между 1-м и 2-м пробелом (так что она будет дословно).

Первый столбец — это полная строка, 2-й столбец — это первая буква первого слова, 3-й столбец — это первая буква, преобразованная в верхний регистр первого слова, а 4-й столбец — это первая буква первого слова, преобразованная в верхний регистр. кейс.

Я думаю, что столбцы 3 и 4 должны иметь одинаковые значения (единственное отличие состоит в том, что один преобразует 1-е слово в верхний регистр перед захватом первой буквы, а другой захватывает 1-ю букву, а затем преобразует ее в верхний регистр), но вместо этого один содержит буква V, как я и ожидал, а другая содержит пробел.

Если я изменю приведенное выше, чтобы получить шестнадцатеричные значения результирующих символов, пустым будет строка из 1 символа с шестнадцатеричным значением 00, а V — шестнадцатеричное значение 56.

Какие-либо предложения? Я упускаю что-то очевидное?


person Kickstart    schedule 03.05.2013    source источник
comment
Для тех, кто обнаружит это в будущем, похоже, что это было исправлено для MySQL 5.6.   -  person Kickstart    schedule 07.03.2019


Ответы (1)


Строка становится двоичной строкой. И для них нельзя использовать LOWER и UPPER, как указано в справочный документ mysql

Итак, как решить?

Используйте функцию convert следующим образом:

SELECT 
    'verbatim h', 
    SUBSTRING(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' ','verbatim h',' '), ' ', 2), ' ', -1), 1, 1) AS c1,
    UPPER(CONVERT((SUBSTRING(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' ','verbatim h',' '), ' ', 2), ' ', -1), 1, 1)) USING latin1)) AS c1_upper;

вот sqlfiddle

person luksch    schedule 03.05.2013
comment
Интересно. Я думаю, что вы правы, но не уверен, почему MySQL решил рассматривать результат SUBSTRING для строки как двоичный. Тем более, что если вы используете пример SQL в качестве подзапроса, а затем выполняете UPPER во 2-м столбце, он дает правильный результат. - person Kickstart; 03.05.2013
comment
я немного странный, правда. Я не стал углубляться в логику строковых функций mysql и когда они возвращают бинарные строки. Я предполагаю, что это некоторая оптимизация, которая срабатывает для односимвольных строк. - person luksch; 03.05.2013
comment
Ммм, не так уверен, проведя небольшое расследование. Изменение ПОДСТРОЕК для получения первых двух символов с использованием ПРОПИСНОГО на первых символах возвращает V (в шестнадцатеричном формате 5600) — аналогичным образом, если вы измените его на первые 3 символа, первые 2 вернутся в верхний регистр с низким значением вместо 3-й. Похоже, он повреждает последний символ строки. - person Kickstart; 03.05.2013