Глава 13. Функции и операторы

Выражения могут использоваться в запросах SQL, таких как ORDER BY или HAVING в SELECT, в предложении WHERE запросов SELECT, DELETE или UPDATE или в операторе SET. Выражения могут быть написаны, используя литеральные значения, значения столбцов, NULL, встроенные функции, сохраненные функции, определяемые пользователем функции и операторы. Эта глава описывает функции и операторы, которые разрешены для того, чтобы написать выражения в MySQL. Инструкции для того, чтобы написать сохраненные функции и определяемые пользователем функции даны в разделах 21.2 и 26.4. См. раздел 10.2.4 для правил, описывающих, как сервер интерпретирует ссылки на различные виды функций.

Выражение, которое содержит NULL всегда производит NULL, если иное не обозначено в документации для особой функции или оператора.

По умолчанию, не должно быть никакого пробела между именем функции и круглой скобкой после этого. Это помогает анализатору MySQL различить вызовы функции и ссылки на таблицы или столбцы, у которых, оказывается, есть то же самое имя, как у функции. Однако, пробелы вокруг функциональных параметров разрешены.

Вы можете сказать серверу MySQL принимать пробелы после имен функций, запуская его с опцией --sql-mode=IGNORE_SPACE. См. раздел 6.1.8. Отдельные программы клиента могут просить это поведение при использовании опции CLIENT_IGNORE_SPACE для mysql_real_connect() . В этом случае все имена функций становятся зарезервированными словами.

Ради краткости большинство примеров в этой главе выводит на экран вывод из программы mysql в сокращенной форме. Вместо того, чтобы показывать примеры в этом формате:

mysql> SELECT MOD(29,9);
+-----------+
| mod(29,9) |
+-----------+
|   2       |
+-----------+
1 rows in set (0.00 sec)

Этот формат используется:

mysql> SELECT MOD(29,9);
    -> 2

13.1. Обзор функций и операторов

Таблица 13.1. Функции и операторы

ИмяОписание
ABS() Возвращает абсолютное значение
ACOS() Возвращает арккосинус
ADDDATE() Добавляет интервал времени к значению даты
ADDTIME() Добавляет время
AES_DECRYPT()Дешифрует с использованием AES
AES_ENCRYPT()Шифрует с использованием AES
AND, &&Логический AND
ANY_VALUE()Подавить отклонение значения ONLY_FULL_GROUP_BY
ASCII() Возвращает числовое значение крайнего левого символа
ASIN() Арксинус
= Назначает значение (как часть SET)
:= Назначает значение
ASYMMETRIC_DECRYPT() Дешифрует зашифрованный текст, используя частный или открытый ключ
ASYMMETRIC_DERIVE() Получить симметричный ключ из асимметричных ключей
ASYMMETRIC_ENCRYPT() Шифрует открытый текст, используя частный или открытый ключ
ASYMMETRIC_SIGN() Генерирует сигнатуру
ASYMMETRIC_VERIFY() Проверяет соответствие сигнатуры
ATAN() Арктангенс
ATAN2(), ATAN()Арктангенс двух параметров
AVG() Среднее значение
BENCHMARK() Неоднократно выполняет выражение
BETWEEN ... AND ...Проверяет, находится ли значение в пределах диапазона значений
BIN() Строка, содержащая двоичное представление числа
BIN_TO_UUID()Конвертирует двоичный UUID в строку
BINARY Преобразует обычную строку в двоичную
BIT_AND() Битовое AND
BIT_COUNT() Возвратить число битов, которые установлены
BIT_LENGTH()Длина параметра в битах
BIT_OR() Битовое OR
BIT_XOR() Битовое XOR
& Битовое AND
~Битовая инверсия
| Битовое OR
^ Битовое XOR
CASE Оператор Case
CAST() Приводит значение к определенному типу
CEIL() Возвратить самое маленькое целочисленное значение не меньше, чем параметр
CEILING() Возвратить самое маленькое целочисленное значение не меньше, чем параметр
CHAR() Возвратить символ для каждого целого числа
CHAR_LENGTH()Число символов в параметре
CHARACTER_LENGTH()Синоним CHAR_LENGTH()
CHARSET() Набор символов параметра
COALESCE() Первый не-NULL параметр
COERCIBILITY()Сопоставление значения строкового параметра
COLLATION() Сопоставление значения строкового параметра
COMPRESS() Возвращает результат как двоичную строку
CONCAT() Конкатенация строк
CONCAT_WS() Конкатенация строк с сепаратором
CONNECTION_ID()ID соединения (ID потока)
CONV() Преобразует числа между системами счисления
CONVERT() Возвращает значение в качестве определенного типа
CONVERT_TZ()Преобразует временные зоны
COS() Косинус
COT() Котангенс
COUNT() Число строк
COUNT(DISTINCT)Число различных значений
CRC32() Значение циклического контроля по избыточности
CREATE_ASYMMETRIC_PRIV_KEY() Создает приватный ключ
CREATE_ASYMMETRIC_PUB_KEY() Создает публичный ключ
CREATE_DH_PARAMETERS() Генерирует разделяемый DH
CREATE_DIGEST() Генерирует дайджест строки
CURDATE() Текущяя дата
CURRENT_DATE(), CURRENT_DATE Синонимы для CURDATE()
CURRENT_ROLE()Текущяя активная роль
CURRENT_TIME(), CURRENT_TIME Синонимы для CURTIME()
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP Синонимы для NOW()
CURRENT_USER(), CURRENT_USER Имя пользователя и имя хоста
CURTIME() Текущее время
DATABASE() Имя базы данных по умолчанию
DATE() Извлекает часть даты из date или datetime
DATE_ADD() Добавляет интервал к дате
DATE_FORMAT()Форматирует дату как надо
DATE_SUB() Вычитает интервал из даты
DATEDIFF() Вычитает две даты
DAY() Синоним для DAYOFMONTH()
DAYNAME() Название дня
DAYOFMONTH()День месяца (0-31)
DAYOFWEEK() День недели (индекс)
DAYOFYEAR() День года (1-366)
DECODE() Декодирует строку из ENCODE()
DEFAULT() Значение по умолчанию для столбца таблицы
DEGREES() Конвертирует радианы в degrees
DES_DECRYPT()Дешифрует строку
DES_ENCRYPT()Шифрует строку
DIV Целочисленное деление
/ Оператор деления
ELT() Строка как номер в индексе
ENCODE() Шифрует строку
ENCRYPT() Шифрует строку
= Оператор равенства
<=> Оператор равенства, защищенный от NULL
EXP() Возведение в степень
EXPORT_SET()Возвращает строку таким образом, что для каждого установленного бита Вы получаете строку on, а для каждого неустановленного бита строку off
EXTRACT() Извлекает часть даты
ExtractValue()Извлекает значение из строки XML, используя нотацию XPath
FIELD() Индекс (позиция) первого параметра в последующих параметрах
FIND_IN_SET()Номер позиции первого параметра в пределах второго параметра
FLOOR() Самое большое целочисленное значение, не больше, чем параметр
FORMAT() Число, отформатированное к конкретному количеству десятичных разрядов
FOUND_ROWS()Для SELECT с предложением LIMIT число строк, которые были бы возвращены, если бы там не было LIMIT
FROM_BASE64()Декодирует строку base-64
FROM_DAYS() Конвертирует число дней в дату
FROM_UNIXTIME()Форматирует Unix timestamp в дату
GeometryCollection() Создает набор геометрии из конфигураций
GET_FORMAT()Дата, сформатированная в строку
GET_LOCK() Получить названную блокировку
> Оператор "больше чем"
>=Оператор "больше чем или равно"
GREATEST() Самый большой параметр
GROUP_CONCAT()Конкатенация строк
GTID_SUBSET()Возвратит истину, если все GTID в подмножестве установлены, иначе ложь
GTID_SUBTRACT()Возвратит все GTID в наборе, которые не находятся в подмножестве.
HEX() Возвратит шестнадцатеричное представление десятичного числа или строки
HOUR() Извлекает час
IF() Конструкция If/else
IFNULL() Конструкция Null If/else
IN() Находится ли значение в пределах ряда значений
INET_ATON() Числовое значение IP-адреса
INET_NTOA() IP-адрес из числового значения
INET6_ATON()Числовое значение IPv6-адреса
INET6_NTOA()IPv6-адрес из числового значения
INSERT() Вставить подстроку в указанной позиции
INSTR() Индекс первого возникновения подстроки
INTERVAL() Индекс параметра, который меньше, чем первый параметр
IS Проверка аргумента на двоичность
IS_FREE_LOCK()Свободна ли названная блокировка
IS_IPV4() Является ли параметр адресом IPv4
IS_IPV4_COMPAT()Является ли параметр IPv4-совместимым адресом
IS_IPV4_MAPPED()Является ли параметр IPv4-отображенным адресом
IS_IPV6() Является ли параметр адресом IPv6
IS NOT Проверка аргумента на двоичность
IS NOT NULLПроверка NOT NULL
IS NULL Проверка на NULL
IS_USED_LOCK()Используется ли названная блокировка, возвратит идентификатор соединения, если да
IS_UUID() Является ли параметр допустимым UUID
ISNULL() Является ли параметр NULL
JSON_ARRAY()Создает массив JSON
JSON_ARRAY_APPEND() Добавляет данные в документ JSON
JSON_ARRAY_INSERT()Вставляет в массив JSON
JSON_ARRAYAGG()Возвратит набор результатов как единственный массив JSON
-> Возвращаемое значение столбца JSON после оценки пути, эквивалент JSON_EXTRACT().
JSON_CONTAINS()Содержит ли документ JSON указанный объект
JSON_CONTAINS_PATH()Содержит ли документ JSON какие-либо данные в пути
JSON_DEPTH()Максимальная глубина документа JSON
JSON_EXTRACT()Данные из документа JSON
->>Возвращаемое значение столбца JSON после оценки пути и закрытия кавычки результат, эквивалент JSON_UNQUOTE(JSON_EXTRACT())
JSON_INSERT()Вставляет данные в документ JSON
JSON_KEYS() Массив ключей из документа JSON
JSON_LENGTH()Число элементов в документе
JSON_MERGE()Объединение документов JSON
JSON_OBJECT()Создать объект JSON
JSON_OBJECTAGG()Возвратит набор результатов как единственный объект JSON
JSON_QUOTE()Цитировать документ JSON
JSON_REMOVE()Удалить данные из документа JSON
JSON_REPLACE()Заменить значения в документе JSON
JSON_SEARCH()Путь в пределах документа JSON
JSON_SET() Вставить данные в документ JSON
JSON_TYPE() Тип значения JSON
JSON_UNQUOTE()Отменить цитирование значения JSON
JSON_VALID()Допустимо ли значение JSON
LAST_DAY Последний день месяца для параметра
LAST_INSERT_ID()Значение столбца AUTOINCREMENT для последнего INSERT
LCASE() Синоним для LOWER()
LEAST() Самый маленький параметр
LEFT() Крайнее левое число символов как определено
<< Сдвиг влево
LENGTH() Возвратит длину строки в байтах
< Оператор "меньше чем"
<=Оператор "меньше чем или равно"
LIKE Простое соответствие образцу
LineString()Создает LineString из значений Point
LN() Натуральный логарифм
LOAD_FILE() Загрузить названный файл
LOCALTIME() , LOCALTIMEСиноним для NOW()
LOCALTIMESTAMP, LOCALTIMESTAMP() Синоним для NOW()
LOCATE() Возвратит позицию первого вхождения подстроки
LOG() Натуральный логарифм первого параметра
LOG10() Десятичный логарифм
LOG2() Двоичный логарифм
LOWER() Возвратит параметр в нижнем регистре
LPAD() Возвратит строковый параметр, дополненный слева указанной строкой
LTRIM() Удалить ведущие пробелы
MAKE_SET() Вернет ряд отделенных запятыми строк, у которых есть соответствующий бит в наборе битов
MAKEDATE() Создает дату из года и дня года
MAKETIME() Создает время из часа, минуты и секунды
MASTER_POS_WAIT()Блокировка, пока ведомое устройство считает и применит все обновления до указанной позиции
MATCH Полнотекстовый поиск
MAX() Максимальное значение
MBRContains()Содержит ли MBR одной геометрии MBR другой
MBRCoveredBy()Покрыт ли один MBR другим
MBRCovers() Покрывает ли один MBR другого
MBRDisjoint()Являются ли MBR двух конфигураций несвязными
MBREquals() Равны ли MBR двух конфигураций
MBRIntersects()Пересекаются ли MBR двух конфигураций
MBROverlaps()Есть ли перекрытие у двух MBR
MBRTouches()Есть ли касание у двух MBR
MBRWithin() Находится ли MBR одной геометрии в пределах MBR другой
MD5() Вычисляет хэш MD5
MICROSECOND()Возвратит микросекунды из параметра
MID() Возвратит подстроку, начиная с указанной позиции
MIN() Минимальное значение
- Оператор "-"
MINUTE() Минута из параметра
MOD() Остаток
%, MODМодуль
MONTH() Месяц из значения даты
MONTHNAME() Имя месяца
MultiLineString()Собирает MultiLineString из LineString
MultiPoint()Собирает MultiPoint из Point
MultiPolygon()Собирает MultiPolygon из Polygon
NAME_CONST()Присваивает имя столбцу
NOT, !Отрицает значение
NOT BETWEEN ... AND ...Проверяет, не находится ли значение в пределах диапазона значений
!=, <>Оператор "не равно"
NOT IN() Проверяет, не находится ли значение в пределах ряда значений
NOT LIKE Отрицание простого соответствия образца
NOT REGEXP Отрицание REGEXP
NOW() Возвратит текущую дату и время
NULLIF() Вернет NULL, если expr1 = expr2
OCT() Возвратит строку, содержащую октальное представление числа
OCTET_LENGTH()Синоним для LENGTH()
||, ORЛогический OR
ORD() Символьный код для крайнего левого символа параметра
PASSWORD() Вычислит и возвратит строку пароля
PERIOD_ADD()Добавляет период к году и месяцу
PERIOD_DIFF()Возвратит число месяцев между периодами
PI() Значение числа pi
+ Оператор "+"
Point() Собирает Point из координат
Polygon() Собирает Polygon из LineString
POSITION() Синоним для LOCATE()
POW() Возводит в указанную степень
POWER() Возводит в указанную степень
PROCEDURE ANALYSE()Анализирует результаты запроса
QUARTER() Квартал из значения date
QUOTE() Экранирует параметр для использования в запросе SQL
RADIANS() Конвертирует в радианы
RAND() Возвратит случайное значение с плавающей запятой
RANDOM_BYTES()Возвратит случайный вектор байта
REGEXP Соответствие образца, используя регулярные выражения
RELEASE_ALL_LOCKS() Освобождает все текущие именованные блокировки
RELEASE_LOCK()Освобождает именованную блокировку
REPEAT() Повторит строку конкретное количество раз
REPLACE() Заменяет указанную строку
REVERSE() Перевернуть строку
RIGHT() Самый правый символ
>> Сдвиг вправо
RLIKE Синоним для REGEXP
ROLES_GRAPHML()Возвращает документ GraphML, представляющий ролевые подграфы памяти
ROUND() Округлит параметр
ROW_COUNT() Сколько строк обновлено
RPAD() Добавляет строку конкретное количество раз
RTRIM() Удалит конечные пробелы
SCHEMA() Синоним для DATABASE()
SEC_TO_TIME()Конвертирует секунды в формат 'HH:MM:SS'
SECOND() Возвратит секунды (0-59)
SESSION_USER()Синоним для USER()
SHA1(), SHA()SHA-1 160-bit хэш
SHA2() Хэш SHA-2
SIGN() Знак аргумента
SIN() Синус
SLEEP() Сон в течение указанного числа секунд
SOUNDEX() Строка soundex
SOUNDS LIKEСравнивает звуки
SPACE() Возвратит строку из конкретного количества пробелов
SQRT() Квадратный корень параметра
ST_Area() Вернет область Polygon или MultiPolygon
ST_AsBinary(), ST_AsWKB() Переходит от внутренней геометрии к WKB
ST_AsGeoJSON()Генерирует объект GeoJSON
ST_AsText() , ST_AsWKT()Переходит от внутренней геометрии к WKT
ST_Buffer() Возвратит геометрию точек в пределах данного расстояния от геометрии
ST_Buffer_Strategy()Произведет опцию стратегии для ST_Buffer()
ST_Centroid()Вернет центр как точку
ST_Contains()Содержит ли одна геометрия другую
ST_ConvexHull()Возвратит выпуклый корпус геометрии
ST_Crosses()Пересекает ли одна геометрия другую
ST_Difference()Возвратит различие в наборе точек двух конфигураций
ST_Dimension()Измерение геометрии
ST_Disjoint()Является ли одна геометрия несвязной с другой
ST_Distance()Расстояние одной геометрии от другой
ST_Distance_Sphere()Минимальное расстояние на земле между двумя конфигурациями
ST_EndPoint()Конечный Point LineString
ST_Envelope()MBR геометрии
ST_Equals() Равна ли одна геометрия другой
ST_ExteriorRing()Возвратит внешнее кольцо Polygon
ST_GeoHash()Произведит значение geohash
ST_GeomCollFromText(), ST_GeometryCollectionFromText(), ST_GeomCollFromTxt()Набор геометрии из WKT
ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB() Набор геометрии из WKB
ST_GeometryN()Возвратит N-ую геометрию из набора геометрий
ST_GeometryType()Возвратит название типа геометрии
ST_GeomFromGeoJSON()Произведет геометрию из объекта GeoJSON
ST_GeomFromText(), ST_GeometryFromText() Набор геометрии из WKT
ST_GeomFromWKB(), ST_GeometryFromWKB() Набор геометрии из WKB
ST_InteriorRingN()Вернет N-ое внутреннее кольцо Polygon
ST_Intersection() Пересечение набора точек двух конфигураций
ST_Intersects()Пересекает ли одна геометрия другую
ST_IsClosed()Закрыта ли геометрия и проста
ST_IsEmpty()Функция заполнителя
ST_IsSimple()Проста ли геометрия
ST_IsValid()Допустима ли геометрия
ST_LatFromGeoHash()Возвратит широту из значения geohash
ST_Length() Возвратит длину LineString
ST_LineFromText(), ST_LineStringFromText() Собирает LineString из WKT
ST_LineFromWKB(), ST_LineStringFromWKB() Собирает LineString из WKB
ST_LongFromGeoHash()Возвратит долготу из значения geohash
ST_MakeEnvelope()Прямоугольник вокруг двух точек
ST_MLineFromText(), ST_MultiLineStringFromText() Собирает MultiLineString из WKT
ST_MLineFromWKB(), ST_MultiLineStringFromWKB() Собирает MultiLineString из WKB
ST_MPointFromText(), ST_MultiPointFromText() Собирает MultiPoint из WKT
ST_MPointFromWKB(), ST_MultiPointFromWKB() Собирает MultiPoint из WKB
ST_MPolyFromText(), ST_MultiPolygonFromText() Собирает MultiPolygon из WKT
ST_MPolyFromWKB(), ST_MultiPolygonFromWKB() Собирает MultiPolygon из WKB
ST_NumGeometries()Число конфигураций в наборе геометрии
ST_NumInteriorRing(), ST_NumInteriorRings() Число углов в Polygon
ST_NumPoints()Число точек в LineString
ST_Overlaps()Перекрывает ли одна геометрия другую
ST_PointFromGeoHash() Конвертирует geohash в POINT
ST_PointFromText()Собирает Point из WKT
ST_PointFromWKB()Собирает Point из WKB
ST_PointN() Возвратит N-ую точку LineString
ST_PolyFromText(), ST_PolygonFromText() Собирает Polygon из WKT
ST_PolyFromWKB(), ST_PolygonFromWKB() Собирает Polygon из WKB
ST_Simplify()Возвратит упрощенную геометрию
ST_SRID() Возвратит пространственный ссылочный системный ID для геометрии
ST_StartPoint()Стартовая Point LineString
ST_SymDifference()Возвратит набор точек симметрического различия двух конфигураций
ST_Touches()Касается ли одна геометрия другой
ST_Union() Возвратит набор общих точек двух конфигураций
ST_Validate()Возвратит утвержденную геометрию
ST_Within() Является ли одна геометрия в пределах другой
ST_X() Координата X Point
ST_Y() Координата Y Point
STD() Возвратит стандартное отклонение
STDDEV() Возвратит стандартное отклонение
STDDEV_POP()Возвратит стандартное отклонение
STDDEV_SAMP()Возвратит типовое стандартное отклонение
STR_TO_DATE()Конвертирует строку в дату
STRCMP() Сравнивает две строки
SUBDATE() Синоним для DATE_SUB(), когда вызвана с тремя параметрами
SUBSTR() Вернет подстроку как определено
SUBSTRING() Вернет подстроку как определено
SUBSTRING_INDEX()Вернет подстроку из строки перед конкретным количеством разделителей
SUBTIME() Вычитает время
SUM() Вернет сумму
SYSDATE() Время выполнения функции
SYSTEM_USER()Синоним для USER()
TAN() Тангенс
TIME() Извлекает часть времени из выражения
TIME_FORMAT()Форматирует время
TIME_TO_SEC() Возвратит параметр, преобразованный в секунды
TIMEDIFF() Вычитает время
* Умножение
TIMESTAMP() С единственным параметром эта функция возвращает дату или выражение datetime, с двумя параметрами, их сумму
TIMESTAMPADD()Добавляет интервал к datetime
TIMESTAMPDIFF()Вычитает интервал из datetime
TO_BASE64() Конвертирует параметр в строку base-64
TO_DAYS() Возвратит параметр даты, преобразованный в дни
TO_SECONDS()Возвратит параметр даты или datetime, преобразованный в секунды с года 0
TRIM() Удаляет начальные и конечные пробелы
TRUNCATE() Урезает к конкретному количеству десятичных разрядов
UCASE() Синоним для UPPER()
- Меняет знак аргумента
UNCOMPRESS()Распаковывает сжатую строку
UNCOMPRESSED_LENGTH()Возвратит длину строки перед сжатием
UNHEX() Строка с hex-представлением числа
UNIX_TIMESTAMP()Unix timestamp
UpdateXML() Возвратит замененный фрагмент XML
UPPER() Конвертирует в верхний регистр
USER() Имя пользователя и имя хоста клиента
UTC_DATE() Текущая дата в UTC
UTC_TIME() Текущее время в UTC
UTC_TIMESTAMP()Текущие дата и время в UTC
UUID() Universal Unique Identifier (UUID)
UUID_SHORT()Числовое значение UUID
UUID_TO_BIN()Конвертирует UUID в двоичную строку
VALIDATE_PASSWORD_STRENGTH() Определяет силу пароля
VALUES() Определяет значения, которые будут использоваться в INSERT
VAR_POP() Возвратит различие стандарта
VAR_SAMP() Возвратит типовое различие
VARIANCE() Возвратит стандартное отклонение
VERSION() Строка версии сервера MySQL
WAIT_FOR_EXECUTED_GTID_SET()Ждать, пока данные GTID не выполнятся на ведомом устройстве
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()Ждать, пока данные GTID не выполнятся на ведомом устройстве
WEEK() Номер недели
WEEKDAY() Индекс дня недели
WEEKOFYEAR()Календарная неделя для даты (1-53)
WEIGHT_STRING()Возвратит строку веса для строки
XOR Логический XOR
YEAR() Год
YEARWEEK() Год и неделя

13.2. Преобразование типов в выражениях

Когда оператор используется с операндами различных типов, происходит преобразование, чтобы сделать операнды совместимыми. Некоторые преобразования происходят неявно. Например, MySQL автоматически преобразовывает числа в строки по мере необходимости, и наоборот.

mysql> SELECT 1+'1';
    -> 2
mysql> SELECT CONCAT(2,' test');
    -> '2 test'

Также возможно преобразовать число в строку, явно используя функцию CAST(). Преобразование происходит неявно с функцией CONCAT(), потому что это ожидает строковые параметры.

mysql> SELECT 38.8, CAST(38.8 AS CHAR);
    -> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
    -> 38.8, '38.8'

См. ниже в этом разделе информацию о наборе символов неявных преобразований числа в строку и измененные правила, которые относятся к CREATE TABLE ... SELECT.

Следующие правила описывают, как преобразование происходит для операций сравнения:

Сравнение значений JSON имеет место на двух уровнях. Первый уровень сравнения основан на типах значений JSON. Если типы отличаются, результат сравнения определен тем, у какого типа есть более высокий приоритет. Если два значения имеют тот же самый тип JSON, второй уровень сравнения происходит, используя определенные для типа правила. Для сравнения JSON с не-JSON значение не-JSON преобразовано в JSON и значения сравниваются значения JSON.

Следующие примеры иллюстрируют преобразование строк к числам для операций сравнения:

mysql> SELECT 1 > '6x';
    -> 0
mysql> SELECT 7 > '6x';
    -> 1
mysql> SELECT 0 > 'x6';
    -> 0
mysql> SELECT 0 = 'x6';
    -> 1

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

SELECT * FROM tbl_name WHERE str_col=1;

Причина этого состоит в том, что есть много различных строк, которые можно преобразовать в значение 1, например, '1', ' 1' или '1a'.

Сравнения, которые используют числа с плавающей запятой (или значения, которые преобразованы в числа с плавающей запятой) приблизительны, потому что такие числа неточны. Это может бы привести к результатам, которые кажутся непоследовательными:

mysql> SELECT '18015376320243458' = 18015376320243458;
    -> 1
mysql> SELECT '18015376320243459' = 18015376320243459;
    -> 0

Такие результаты могут произойти, потому что значения преобразованы в числа с плавающей запятой, которые имеют только 53 бита точности и подвергаются округлению:

mysql> SELECT '18015376320243459'+0.0;
    -> 1.8015376320243e+16

Кроме того, преобразование строки в число с плавающей запятой и из целого числа в число с плавающей запятой не обязательно проходит тот же самый путь. Целое число может быть преобразовано в число с плавающей запятой центральным процессором, тогда как строка преобразована посимвольно, что вовлекает умножение с плавающей запятой.

Показанные результаты изменятся на различных системах, и могут быть затронуты факторами, такими как архитектура ЭВМ, версия компилятора или уровень оптимизации. Один способ избежать таких проблем состоит в том, чтобы использовать CAST() так, чтобы значение не было преобразовано неявно:

mysql> SELECT CAST('18015376320243459' AS UNSIGNED) = 18015376320243459;
    -> 1

Сервер включает dtoa, конверсионную библиотеку, которая обеспечивает улучшенное преобразование строк или значений DECIMAL в значения FLOAT/ DOUBLE:

Поскольку преобразования, произведенные этой библиотекой, отличаются в некоторых случаях от неdtoa, существует потенциал для несовместимостей в приложениях, которые полагаются на предыдущие результаты. Например, приложениям, которые зависят от определенного точного результата предыдущих преобразований, возможно, понадобилась бы корректировка, чтобы приспособить дополнительную точность.

Библиотека dtoa предоставляет преобразованиям следующие свойства. D представляет значение DECIMAL или строковое представление, F представляет число с плавающей запятой в двоичном формате (IEEE).

Эти свойства подразумевают, что F -> D -> F преобразования без потерь, если F -inf, +inf или NaN. Последние значения не поддержаны, потому что стандарт SQL определяет их как недопустимые значения для FLOAT или DOUBLE.

Для D -> F -> D преобразования, достаточное условие для работы без потерь это то, что D использует 15 или меньше цифр точности, -inf, +inf или NaN. В некоторых случаях преобразование без потерь возможно, даже если D имеет больше, чем 15 цифр точности, но это не всегда.

Неявное преобразование числового или временного значения, чтобы представить в виде строки производит значение, у которого есть набор символов и сопоставление, определенное системными переменными character_set_connection и collation_connection . Эти переменные обычно устанавливаются SET NAMES.

Это означает, что такое преобразование приводит к символьной строке (CHAR, VARCHAR или LONGTEXT), кроме случая, в котором установлен набор символов соединения binary. В этом случае конверсионный результат двоичная строка (BINARY, VARBINARY или LONGBLOB).

Для выражений целого числа предыдущие замечания об оценке выражения применяются несколько по-другому для назначения выражения: например, в запросе

CREATE TABLE t SELECT integer_expr;

В этом случае у таблицы в столбце, следующем из выражения, есть тип INT или BIGINT, в зависимости от длины выражения целого числа. Если максимальная длина выражения не вписывается в INT, вместо него будет использован BIGINT . Длина взята из значения max_length метаданных набора результатов SELECT (см. раздел 25.8.5). Это означает, что Вы можете вызвать BIGINT вместо INT при помощи достаточно длинного выражения:

CREATE TABLE t SELECT 000000000000000000000;

13.3. Операторы

Таблица 13.2. Операторы

ИмяОписание
AND, &&Логический AND
= Назначает значение (как часть SET)
:= Назначает значение
BETWEEN ... AND ...Проверяет, является ли значение в пределах диапазона значений
BINARY Преобразует строку в двоичную
& Битовое AND
~ Битовая инверсия
| Битовое OR
^ Битовое XOR
CASE Оператор Case
DIV Целочисленное деление
/ Деление
= Равенство
<=> NULL-безопасный оператор равенства
> Больше чем
>=Больше чем или равно
IS Проверка на boolean
IS NOT Проверка на boolean
IS NOT NULLПроверка на NOT NULL
IS NULL Проверка на NULL
-> Возвращаемое значение столбца JSON после оценки пути, эквивалент JSON_EXTRACT()
->>Возвращаемое значение столбца JSON после оценки пути и закрытия кавычки, аналог JSON_UNQUOTE(JSON_EXTRACT()).
<< Сдвиг влево
< Меньше чем
<=Меньше чем или равно
LIKE Простое соответствие образца
- Минус
%, MODМодуль числа
NOT, !Отрицание
NOT BETWEEN ... AND ...Проверяет, не является ли значение в пределах диапазона значений
!=, <>Не равно
NOT LIKE Отрицание простого соответствия образца
NOT REGEXP Отрицание REGEXP
||, ORЛогический OR
+ Сложение
REGEXP Соответствие образца, используя регулярные выражения
>> Сдвиг вправо
RLIKE Синоним для REGEXP
SOUNDS LIKEСравнение звуков
* Умножение
- Смена знака параметра
XOR Логический XOR

13.3.1. Приоритет операторов

Приоритет операторов показан в следующем списке, от самого высокого приоритета до самого низкого. У операторов, которые показаны вместе на строке, тот же самый приоритет.

INTERVAL
BINARY, COLLATE
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
<<, >>
&
|
= (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
AND, &&
XOR
OR, ||
= (assignment), :=

Приоритет = зависит от того, используется ли это в качестве оператора сравнения (=) или как оператор назначения ( =). Когда использующийся в качестве оператора сравнения, есть тот же самый приоритет, что и у <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP и IN. Когда используется в качестве оператора назначения, у него есть тот же самый приоритет, что и у := . Разделы 14.7.4.1 и 10.4 объясняют, как MySQL определяет, какая интерпретация = должна применяться.

Для операторов, которые на том же самом уровне приоритета в пределах выражения, оценка происходит слева направо, за исключением того, что присвоение происходит справа налево.

Значение некоторых операторов зависит от режима SQL:

Приоритет операторов определяет порядок оценки выражения. Чтобы переопределить этот порядок и группировать члены явно, используйте круглые скобки. Например:

mysql> SELECT 1+2*3;
    -> 7
mysql> SELECT (1+2)*3;
    -> 9

13.3.2. Функции сравнения и операторы

Таблица 13.3. Операторы сравнения

ИмяОписание
BETWEEN ... AND ...Проверяет, является ли значение в пределах диапазона значений
COALESCE() Вернет первый аргумент не-NULL
= Равенство
<=> NULL-безопасное равенство
> Больше чем
>=Больше чем или равно
GREATEST() Самый большой параметр
IN() Проверяет, является ли значение в пределах ряда значений
INTERVAL() Индекс параметра, который меньше, чем первый параметр
IS Проверка на boolean
IS NOT Проверка на boolean
IS NOT NULLПроверка на NOT NULL
IS NULL Проверка на NULL
ISNULL() Является ли параметром NULL
LEAST() Самый маленький параметр
< Меньше чем
<=Меньше чем или равно
LIKE Простое соответствие образца
NOT BETWEEN ... AND ...Проверяет, не является ли значение в пределах диапазона значений
!=, <>Не равно
NOT IN() Проверяет, не является ли значение в пределах ряда значений
NOT LIKE Отрицание простого соответствия образца
STRCMP() Сравнить две строки

Операции сравнения приводят к значению 1 (TRUE), 0 (FALSE) или NULL. Эти операции работают и на числах, и на строках. Строки автоматически преобразованы в числа, а числа в строки по мере необходимости.

Следующие относительные операторы сравнения могут использоваться, чтобы сравнить не только скалярные операнды, но и операнды строки:

=  >  <  >=  <=  <>  !=

Описания для тех операторов позже в этом разделе детализируют, как они работают с операндами строки. Для дополнительных примеров сравнений строки в контексте подзапросов строки, см. раздел 14.2.10.5.

Некоторые из функций в этом разделе возвращают значения кроме 1 (TRUE), 0 (FALSE) или NULL. Например, LEAST() и GREATEST(). Однако, значение, которое они возвращают, основано на операциях сравнения, выполненных согласно правилам, описанным в разделе 13.2.

Чтобы преобразовать значение в определенный тип в целях сравнения, Вы можете использовать CAST(). Строковые значения могут быть преобразованы в различное использование набора символов с помощью CONVERT() .

По умолчанию, строковые сравнения не являются чувствительными к регистру и используют текущий набор символов. Значение по умолчанию latin1 (cp1252 West European), которое также работает хорошо на английском языке.

13.3.3. Логические операторы

Таблица 13.4. Логические операторы

ИмяОписание
AND, &&Логический AND
NOT, !Отрицание
||, ORЛогический OR
XOR Логический XOR

В SQL все логические операторы оценивают как TRUE, FALSE или NULL (UNKNOWN). В MySQL они осуществлены как 1 (TRUE), 0 (FALSE) и NULL. Большая часть из этого характерна для различных серверов базы данных SQL, хотя некоторые серверы могут возвратить любое ненулевое значение для TRUE.

MySQL оценивает любое отличное от нуля, не-NULL значение как TRUE. Например, все следующие запросы оцениваются как TRUE:

mysql> SELECT 10 IS TRUE;
    -> 1
mysql> SELECT -10 IS TRUE;
    -> 1
mysql> SELECT 'string' IS NOT NULL;
    -> 1

13.3.4. Операторы присваивания

Таблица 13.5. Операторы присваивания

ИмяОписание
= Назначает значение (как часть SET)
:= Назначает значение

13.4. Функции управления потоком

Таблица 13.6. Операторы управления потоком

ИмяОписание
CASE Case
IF() If/else
IFNULL() Null if/else
NULLIF() NULL, если expr1 = expr2

13.5. Строковые функции

Таблица 13.7. Строковые функции

ИмяОписание
ASCII() Возвращает числовое значение крайнего левого символа
BIN() Строка, содержащая двоичное представление числа
BIT_LENGTH()Длина параметра в битах
CHAR() Возвратить символ для каждого целого числа
CHAR_LENGTH()Число символов в параметре
CHARACTER_LENGTH()Синоним для CHAR_LENGTH()
CONCAT() Конкатенация строк
CONCAT_WS() Конкатенация строк с сепаратором
ELT() Строка как номер в индексе
EXPORT_SET()Возвращает строку таким образом, что для каждого установленного бита Вы получаете строку on, а для каждого неустановленного бита строку off
FIELD() Индекс (позиция) первого параметра в последующих параметрах
FIND_IN_SET()Номер позиции первого параметра в пределах второго параметра
FORMAT() Число, отформатированное к конкретному количеству десятичных разрядов
FROM_BASE64()Декодирует строку base-64
HEX() Возвратит шестнадцатеричное представление десятичного числа или строки
INSERT() Вставить подстроку в указанной позиции
INSTR() Индекс первого возникновения подстроки
LCASE() Синоним для LOWER()
LEFT() Крайнее левое число символов как определено
LENGTH() Возвратит длину строки в байтах
LIKE Простое соответствие образцу
LOAD_FILE() Загрузить названный файл
LOCATE() Возвратит позицию первого вхождения подстроки
LOWER() Возвратит параметр в нижнем регистре
LPAD() Возвратит строковый параметр, дополненный слева указанной строкой
LTRIM() Удалить ведущие пробелы
MAKE_SET() Вернет ряд отделенных запятыми строк, у которых есть соответствующий бит в наборе битов
MATCH Полнотекстовый поиск
MID() Возвратит подстроку, начиная с указанной позиции
NOT LIKE Отрицание простого соответствия образца
NOT REGEXP Отрицание REGEXP
OCT() Возвратит строку, содержащую октальное представление числа
OCTET_LENGTH()Синоним для LENGTH()
ORD() Символьный код для крайнего левого символа параметра
POSITION() Синоним для LOCATE()
QUOTE() Экранирует параметр для использования в запросе SQL
REGEXP Соответствие образца, используя регулярные выражения
REPEAT() Повторит строку конкретное количество раз
REPLACE() Заменяет указанную строку
REVERSE() Перевернуть строку
RIGHT() Самый правый символ
RLIKE Синоним для REGEXP
RPAD() Добавляет строку конкретное количество раз
RTRIM() Удалит конечные пробелы
SOUNDEX() Строка soundex
SOUNDS LIKEСравнивает звуки
SPACE() Возвратит строку из конкретного количества пробелов
STRCMP() Сравнивает две строки
SUBSTR() Вернет подстроку как определено
SUBSTRING() Вернет подстроку как определено
SUBSTRING_INDEX()Вернет подстроку из строки перед конкретным количеством разделителей
TO_BASE64() Конвертирует параметр в строку base-64
TRIM() Удаляет начальные и конечные пробелы
UCASE() Синоним для UPPER()
UNHEX() Строка с hex-представлением числа
UPPER() Конвертирует в верхний регистр
WEIGHT_STRING()Возвратит строку веса для строки

Функции, возвращающие строки, вернут NULL, если длина результата больше, чем значение системной переменной max_allowed_packet . См. раздел 6.1.1.

Для функций, которые воздействуют на строковые позиции, первая позиция 1.

Для функций, которые берут параметры длины, параметры нецелого числа округлены к самому близкому целому числу.

13.5.1. Функции сравнения строк

Таблица 13.8. Функции сравнения строк

ИмяОписание
LIKE Простое соответствие образцу
NOT LIKE Отрицание простого соответствия образца
STRCMP() Сравнивает две строки

Если строковой функции дают двоичную строку как параметр, получающаяся строка также двоичная. Число, преобразованное в строку, обработано как двоичная строка. Это затрагивает только сравнения.

Обычно если какое-либо выражение в строковом сравнении является чувствительным к регистру, сравнение выполнено чувствительным к регистру способом.

13.5.2. Регулярные выражения

Таблица 13.9. Строки регулярных выражений

ИмяОписание
NOT REGEXPОтрицание REGEXP
REGEXP Соответствие образца, используя регулярные выражения
RLIKE Синоним для REGEXP

Регулярное выражение сильный способ определить образец для сложного поиска.

MySQL применяет реализацию регулярных выражений от Henry Spencer, которая нацелена на соответствие POSIX 1003.2. MySQL использует расширенную версию, чтобы поддержать соответствующие образцы, выполненные оператором REGEXP в запросах SQL.

Этот раздел подводит итог, с примерами, специальными символами и конструкциями, которые могут использоваться в MySQL для REGEXP. Это не содержит все детали, которые могут быть найдены в Henry Spencer's regex(7) manual page. Эта документация есть в дистрибутиве исходных текстов MySQL в файле regex.7 каталога regex. Также изучите раздел 4.3.4.7.

Операторы регулярных выражений

Синтаксис регулярных выражений

Регулярное выражение описывает ряд строк. Самое простое регулярное выражение то, у которого нет никаких специальных символов в нем. Например, регулярное выражение hello соответствует только hello и ничему больше.

Нетривиальные регулярные выражения используют определенные специальные конструкции так, чтобы они могли соответствовать больше, чем одной строке. Например, регулярное выражение hello|word соответствует любой строке hello или word.

Как более сложный пример, регулярное выражение B[an]*s соответствует любой из строк Bananas, Baaaaas, Bs и любой другой строке, начинающейся с B, заканчивающейся на s и включающей любое число символов a или n между ними.

Регулярное выражение для REGEXP может использовать любой из следующих специальных символов и конструкций:

Чтобы использовать буквальный случай специального символа в регулярном выражении, предварите его двумя наклонными чертами влево (\\). Анализатор MySQL интерпретирует одну из наклонных черт влево, а библиотека регулярных выражений интерпретирует другую. Например, чтобы соответствовать строке 1+2, которая содержит специальный символ +, только последнее из следующих регулярных выражений является правильным:

mysql> SELECT '1+2' REGEXP '1+2';
    -> 0
mysql> SELECT '1+2' REGEXP '1\+2';
    -> 0
mysql> SELECT '1+2' REGEXP '1\\+2';
    -> 1

13.5.3. Набор символов и сопоставление функциональных результатов

У MySQL есть много операторов и функций, которые возвращают строку. Этот раздел отвечает на вопрос: каков набор символов и сопоставление такой строки?

Для простых функций, которые берут строковый ввод и возвращают строковый результат как выход, набор символов вывода и сопоставление те же самые, что и таковые из входного значения. Например, UPPER(X) возвращает строку с той же самой строкой символов и сопоставлением как было в X. То же самое касается функций INSTR(), LCASE(), LOWER(), LTRIM(), MID(), REPEAT(), REPLACE(), REVERSE(), RIGHT(), RPAD(), RTRIM(), SOUNDEX(), SUBSTRING(), TRIM(), UCASE() и UPPER().

Функция REPLACE(), в отличие от всех других функций, всегда игнорирует сопоставление строкового ввода и выполняет чувствительное к регистру сравнение.

Если строковый ввод или функциональный результат двоичная строка, она имеет набор символов и сопоставление binary. Это может быть проверено при использовании функций CHARSET() и COLLATION(), обе из которых возвращают binary для двоичного строкового параметра:

mysql> SELECT CHARSET(BINARY 'a'), COLLATION(BINARY 'a');
+---------------------+-----------------------+
| CHARSET(BINARY 'a') | COLLATION(BINARY 'a') |
+---------------------+-----------------------+
| binary              | binary                |
+---------------------+-----------------------+

Для операций, которые комбинируют много строк и возвращают единственный строковый вывод, используются правила агрегации стандартного SQL для определения сопоставления результата:

Например, с CASE ... WHEN a THEN b WHEN b THEN c COLLATE X END, получающееся сопоставление X. То же самое касается UNION, ||, CONCAT(), ELT(), GREATEST(), IF() и LEAST().

Для операций, которые преобразовывают в символьные данные, набор символов и сопоставление строк, которые следуют из операций, определены переменными character_set_connection и collation_connection , которые определяют набор символов и сопоставление соединения по умолчанию (см. раздел 11.1.4). Это применяется только к CAST(), CONV(), FORMAT(), HEX() и SPACE().

Если есть вопрос о наборе символов или сопоставлении результата, возвращенного строковой функцией, используйте функцию CHARSET() или COLLATION() , чтобы узнать:

mysql> SELECT USER(), CHARSET(USER()), COLLATION(USER());
+----------------+-----------------+-------------------+
| USER()         | CHARSET(USER()) | COLLATION(USER()) |
+----------------+-----------------+-------------------+
| test@localhost | utf8            | utf8_general_ci   |
+----------------+-----------------+-------------------+

mysql> SELECT CHARSET(COMPRESS('abc')), COLLATION(COMPRESS('abc'));
+--------------------------+----------------------------+
| CHARSET(COMPRESS('abc')) | COLLATION(COMPRESS('abc')) |
+--------------------------+----------------------------+
| binary                   | binary                     |
+--------------------------+----------------------------+

13.6. Числовые функции и операторы

Таблица 13.10. Числовые функции и операторы

ИмяОписание
ABS() Возвращает абсолютное значение
ACOS() Возвращает арккосинус
ASIN() Арксинус
ATAN() Арктангенс
ATAN2(), ATAN()Арктангенс двух параметров
CEIL() Возвратить самое маленькое целочисленное значение не меньше, чем параметр
CEILING() Возвратить самое маленькое целочисленное значение не меньше, чем параметр
CONV() Преобразует числа между системами счисления
COS() Косинус
COT() Котангенс
CRC32() Значение циклического контроля по избыточности
DEGREES() Конвертирует радианы в degrees
DIV Целочисленное деление
/ Оператор деления
EXP() Возведение в степень
FLOOR() Самое большое целочисленное значение, не больше, чем параметр
LN() Натуральный логарифм
LOG() Натуральный логарифм первого параметра
LOG10() Десятичный логарифм
LOG2() Двоичный логарифм
- Оператор "-"
MOD() Остаток
%, MODМодуль
PI() Значение числа pi
+ Оператор "+"
POW() Возводит в указанную степень
POWER() Возводит в указанную степень
RADIANS() Конвертирует в радианы
RAND() Возвратит случайное значение с плавающей запятой
ROUND() Округлит параметр
SIGN() Знак аргумента
SIN() Синус
SQRT() Квадратный корень параметра
TAN() Тангенс
* Умножение
TRUNCATE() Урезает к конкретному количеству десятичных разрядов
- Меняет знак аргумента

13.6.1. Арифметические операторы

Таблица 13.11. Арифметические операторы

ИмяОписание
DIV Целочисленное деление
/ Оператор деления
- Оператор "-"
%, MODМодуль
+ Оператор "+"
* Умножение
- Меняет знак аргумента

Обычные арифметические операторы доступны. Результат определен согласно следующим правилам:

Эти правила применены для каждой операции так, что вложенные вычисления подразумевают точность каждого компонента. Следовательно, (14620 / 9432456) / (24250 / 9432456) сначала сведется к (0.0014) / (0.0026) с окончательным результатом, имеющим 8 десятичных разрядов (0.60288653).

Из-за этих правил надо следить за тем, что компоненты и субкомпоненты вычисления используют соответствующий уровень точности. См. раздел 13.10.

Арифметические операторы обращаются к числам. Для других типов значений альтернативные операции могут быть доступны. Например, чтобы добавить значения даты, используйте DATE_ADD().

13.6.2. Математические функции

Таблица 13.12. Математические функции

ИмяОписание
ABS() Возвращает абсолютное значение
ACOS() Возвращает арккосинус
ASIN() Арксинус
ATAN() Арктангенс
ATAN2(), ATAN()Арктангенс двух параметров
CEIL() Возвратить самое маленькое целочисленное значение не меньше, чем параметр
CEILING() Возвратить самое маленькое целочисленное значение не меньше, чем параметр
CONV() Преобразует числа между системами счисления
COS() Косинус
COT() Котангенс
CRC32() Значение циклического контроля по избыточности
DEGREES() Конвертирует радианы в degrees
EXP() Возведение в степень
FLOOR() Самое большое целочисленное значение, не больше, чем параметр
LN() Натуральный логарифм
LOG() Натуральный логарифм первого параметра
LOG10() Десятичный логарифм
LOG2() Двоичный логарифм
MOD() Остаток
PI() Значение числа pi
POW() Возводит в указанную степень
POWER() Возводит в указанную степень
RADIANS() Конвертирует в радианы
RAND() Возвратит случайное значение с плавающей запятой
ROUND() Округлит параметр
SIGN() Знак аргумента
SIN() Синус
SQRT() Квадратный корень параметра
TAN() Тангенс
TRUNCATE() Урезает к конкретному количеству десятичных разрядов

Все математические функции вернут NULL в случае ошибки.

13.7. Функции даты и времени

Таблица 13.13. Функции Date/Time

ИмяОписание
ADDDATE()Добавляет интервал времени к значению даты
ADDTIME() Добавляет время
CONVERT_TZ()Преобразует временные зоны
CURDATE() Текущяя дата
CURRENT_DATE(), CURRENT_DATE Синоним для CURDATE()
CURRENT_TIME(), CURRENT_TIME Синоним для CURTIME()
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP Синоним для NOW()
CURTIME() Текущее время
DATE() Извлекает часть даты из date или datetime
DATE_ADD() Добавляет интервал к дате
DATE_FORMAT()Форматирует дату как надо
DATE_SUB() Вычитает интервал из даты
DATEDIFF() Вычитает две даты
DAY() Синоним для DAYOFMONTH()
DAYNAME() Название дня
DAYOFMONTH()День месяца (0-31)
DAYOFWEEK() День недели (индекс)
DAYOFYEAR() День года (1-366)
EXTRACT() Извлекает часть даты
FROM_DAYS() Конвертирует число дней в дату
FROM_UNIXTIME()Форматирует Unix timestamp в дату
GET_FORMAT()Дата, сформатированная в строку
HOUR() Извлекает час
LAST_DAY Последний день месяца для параметра
LOCALTIME() , LOCALTIMEСиноним для NOW()
LOCALTIMESTAMP, LOCALTIMESTAMP() Синоним для NOW()
MAKEDATE() Создает дату из года и дня года
MAKETIME() Создает время из часа, минуты и секунды
MICROSECOND()Возвратит микросекунды из параметра
MINUTE() Минута из параметра
MONTH() Месяц из значения даты
MONTHNAME() Имя месяца
NOW() Возвратит текущую дату и время
PERIOD_ADD()Добавляет период к году и месяцу
PERIOD_DIFF()Возвратит число месяцев между периодами
QUARTER() Квартал из значения date
SEC_TO_TIME()Конвертирует секунды в формат 'HH:MM:SS'
SECOND() Возвратит секунды (0-59)
STR_TO_DATE()Конвертирует строку в дату
SUBDATE() Синоним для DATE_SUB(), когда вызвана с тремя параметрами
SUBTIME() Вычитает время
SYSDATE() Время выполнения функции
TIME() Извлекает часть времени из выражения
TIME_FORMAT()Форматирует время
TIME_TO_SEC() Возвратит параметр, преобразованный в секунды
TIMEDIFF() Вычитает время
TIMESTAMP() С единственным параметром эта функция возвращает дату или выражение datetime, с двумя параметрами, их сумму
TIMESTAMPADD()Добавляет интервал к datetime
TIMESTAMPDIFF()Вычитает интервал из datetime
TO_DAYS() Возвратит параметр даты, преобразованный в дни
TO_SECONDS()Возвратит параметр даты или datetime, преобразованный в секунды с года 0
UNIX_TIMESTAMP()Unix timestamp
UTC_DATE() Текущая дата в UTC
UTC_TIME() Текущее время в UTC
UTC_TIMESTAMP()Текущие дата и время в UTC
WEEK() Номер недели
WEEKDAY() Индекс дня недели
WEEKOFYEAR()Календарная неделя для даты (1-53)
YEAR() Год
YEARWEEK() Год и неделя

Вот пример, который использует функции даты. Следующий запрос выбирает все строки с date_col в пределах прошлых 30 дней:

mysql> SELECT something FROM tbl_name
    ->        WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= date_col;

Запрос также выбирает строки с датами, которые лежат в будущем.

Функции, которые ожидают значения даты, обычно принимают значения datetime и игнорируют часть времени. Функции, которые ожидают временные значения, обычно принимают значения datetime и игнорируют часть даты.

Функции, которые возвращают текущую дату или время, оцениваются только однажды в начале выполнения запроса. Это означает, что многократные ссылки на функцию такие, как NOW() в пределах единственного запроса всегда приводят к тому же самому результату. В наших целях единственный запрос также включает вызов сохраненной программы и всех подпрограмм, вызванных той программой. Этот принцип также относится к CURDATE(), CURTIME(), UTC_DATE(), UTC_TIME(), UTC_TIMESTAMP() и к любому из их синонимов.

CURRENT_TIMESTAMP() , CURRENT_TIME(), CURRENT_DATE() и FROM_UNIXTIME() возвращают значения функций в зоне текущего времени соединения, которая доступна как значение системной переменной time_zone. Кроме того, UNIX_TIMESTAMP() предполагает, что параметр значение datetime в зоне текущего времени. См. раздел 11.6.

Некоторые функции даты могут использоваться с нулевыми или неполными датами, например, '2001-11-00' , тогда как другие не могут. Функции, которые извлекают части дат, как правило, работают с неполными датами и таким образом могут возвратить 0, когда Вы могли бы ожидать ненулевое значение. Например:

mysql> SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00');
  -> 0, 0

Другие функции ожидают полные даты и возвращают NULL для неполных дат. Они включают функции, которые выполняют арифметику даты или отображают части дат к именам. Например:

mysql> SELECT DATE_ADD('2006-05-00',INTERVAL 1 DAY);
  -> NULL
mysql> SELECT DAYNAME('2006-05-00');
  -> NULL

Несколько функций более строги, когда передано значение DATE() как их параметр и отклонят неполные даты с дневной частью 0. Эти функции: CONVERT_TZ(), DATE_ADD(), DATE_SUB(), DAYOFYEAR(), LAST_DAY() (разрешает дневную часть 0), TIMESTAMPDIFF(), TO_DAYS(), TO_SECONDS(), WEEK(), WEEKDAY(), WEEKOFYEAR(), YEARWEEK().

Дробные секунды для TIME, DATETIME и TIMESTAMP поддержаны до точности микросекунды. Функции, которые берут временные параметры, принимают значения с дробными секундами. Возвращаемые значения от временных функций включают дробные секунды.

13.8. Какой календарь использует MySQL?

MySQL использует то, что известно как старый Григорианский календарь .

Каждая страна, которая переключилась с Юлианского на Григорианский календарь, должна была отказаться по крайней мере от десяти дней. Чтобы видеть, как это работает, рассмотрите месяц октября 1582, когда первый такой переход произошел.

MondayTuesday WednesdayThursday FridaySaturday Sunday
123415 1617
1819202122 2324
2526272829 3031

Нет никаких дат между 4 октября и 15 октября. Эту неоднородность называют cutover. Любые даты перед ней Юлианские, а любые даты после cutover являются Грегорианскими. Даты во время cutover являются несуществующими.

Календарь относящийся к датам, когда он не было фактически использован, назван старым. Таким образом, если мы предполагаем, что никогда не было cutover, и Грегорианские правила всегда работали, у нас есть старый Григорианский календарь. Это то, что используется MySQL, как требуется стандартным SQL. Поэтому даты до cutover, сохраненные как значения MySQL DATE или DATETIME должны быть скорректированы, чтобы дать компенсацию за различие. Важно понять, что cutover не происходил в то же самое время во всех странах, и что, чем позже это произошло, тем больше было потеряно дней. Например, в Великобритании, это имело место в 1752, когда среда 2 сентября сопровождалась четвергом 14 сентября. Россия оставалась на юлианском календаре до 1918, теряя 13 дней в процессе, и именно поэтому Октябрьская революция произошла в ноябре, согласно Григорианскому календарю.

13.9. Функции полнотекстового поиска

MATCH (col1,col2,...) AGAINST (expr [search_modifier])

search_modifier:
  {IN NATURAL LANGUAGE MODE
   | IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
   | IN BOOLEAN MODE
   | WITH QUERY EXPANSION
  }

У MySQL есть поддержка полнотекстовой индексации и поиска:

Полнотекстовый поиск выполнен, используя синтаксис MATCH() ... AGAINST. MATCH() берет список разделенных запятой значений, который называет столбцы, которые будут просмотрены. AGAINST берет строку, чтобы искать и дополнительный модификатор, который указывает какой поиск использовать. Строка поиска должна быть строковым значением, которое является постоянным во время оценки запроса. Это исключает, например, столбец таблицы, потому что это может отличаться для каждой строки.

Есть три типа полнотекстовых поисков:

myisam_ftdump выводит содержание полнотекстового индекса MyISAM. Это может быть полезно для того, чтобы отладить полнотекстовые запросы.

13.9.1. Полнотекстовые поиски на естественном языке

По умолчанию или с модификатором IN NATURAL LANGUAGE MODE MATCH() выполняет поиск естественного языка строки для текстового набора. Набор один или большее количество столбцов, включенных в индекс FULLTEXT. Строка поиска дана как параметр AGAINST(). Для каждой строки в таблице MATCH() возвращает значение уместности, то есть, мера подобия между строкой поиска и текстом в строке в столбцах, названных в списке MATCH().

mysql> CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200), body TEXT, FULLTEXT (title,body)) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles (title,body) VALUES
  ('MySQL Tutorial','DBMS stands for DataBase ...'),
  ('How To Use MySQL Well','After you went through a ...'),
  ('Optimizing MySQL','In this tutorial we will show ...'),
  ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
  ('MySQL vs. YourSQL','In the following database comparison ...'),
  ('MySQL Security','When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM articles WHERE MATCH (title,body)
                   AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

По умолчанию, поиск выполнен нечувствительным к регистру способом. Чтобы выполнить чувствительный к регистру полнотекстовый поиск, используйте двоичное сопоставление для индексированных столбцов. Например, столбцу, который использует набор символов latin1 можно назначить сопоставление latin1_bin, чтобы сделать это чувствительным к регистру для полнотекстовых поисков.

Когда MATCH() используется в WHERE, как в примере, показанном ранее, строки будут автоматически отсортированы с самой высокой уместностью сначала. Значения уместности неотрицательные числа с плавающей запятой. Нулевая уместность не означает подобия. Уместность вычислена основываясь на числе слов в строке (документе), числе уникальных слов в строке, общем количестве слов в наборе и числе строк, которые содержат особое слово.

Термин документ может быть использован попеременно с термином строка, и оба термина относятся к индексированной части строки. Термин набор относится к индексированным столбцам и охватывает все строки.

Чтобы просто посчитать соответствия, Вы можете использовать такой запрос:

mysql> SELECT COUNT(*) FROM articles
                 WHERE MATCH (title,body)
                 AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----------+
| COUNT(*) |
+----------+
|  2       |
+----------+
1 row in set (0.00 sec)

Вы могли бы счесть более быстрым переписать запрос следующим образом:

mysql> SELECT COUNT(IF(MATCH (title,body)
                 AGAINST ('database' IN NATURAL LANGUAGE MODE), 1, NULL))
                 AS count FROM articles;
+-------+
| count |
+-------+
| 2     |
+-------+
1 row in set (0.03 sec)

Первый запрос делает некоторую дополнительную работу (сортирует результаты по уместности), но также может использовать поиск по индексу, основанный на WHERE. Индексированный поиск мог бы сделать первый запрос быстрее, если поиску соответствует немного строк. Второй запрос выполняет полное сканирование таблицы, которое могло бы быть быстрее, чем поиск по индексу, если бы критерий поиска присутствовал в большинстве строк.

Для естественного языка полнотекстовые поиска, столбцы, названные в MATCH() должны быть теми же самыми столбцами, которые включены в индекс FULLTEXT. Для предыдущего запроса, отметьте, что столбцы, названные в MATCH() (title и body) те же самые, что и названные в определении индекса FULLTEXT таблицы article. Чтобы искать title или body отдельно, Вы создали бы отдельный индекс FULLTEXT для каждого столбца.

Вы можете также выполнить булев поиск или поиск с расширением запроса. Эти типы поиска описаны в разделах 13.9.2 и 13.9.3.

Полнотекстовый поиск, который использует индексирование, может назвать столбцы только единственной таблицы в MATCH(), потому что индексирование не может охватить много таблиц. Для таблиц MyISAM булев поиск может быть сделан в отсутствие индексирования (хотя более медленно), тогда возможно назвать столбцы разных таблиц.

Предыдущий пример основная иллюстрация, которая показывает, как использовать MATCH(), когда строки возвращены в порядке уменьшающейся уместности. Следующий пример показывает, как получить значения уместности явно. Возвращенные строки не упорядочены потому, что SELECT не включает ни одного WHERE или ORDER BY:

mysql> SELECT id, MATCH (title,body)
                 AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) AS score
                 FROM articles;
+----+---------------------+
| id | score               |
+----+---------------------+
|  1 | 0.22764469683170319 |
|  2 |   0                 |
|  3 | 0.22764469683170319 |
|  4 |   0                 |
|  5 |   0                 |
|  6 |   0                 |
+----+---------------------+
6 rows in set (0.00 sec)

Следующий пример более сложен. Запрос возвращает значения уместности, а также сортирует строки в порядке уменьшающейся уместности. Чтобы достигчь этого результата, определите MATCH() дважды: первый в списке SELECT, второй в предложении WHERE. Это не вызывает проблем, потому что оптимизатор MySQL замечает два идентичиных вызова MATCH() и вызывает полнотекстовый код поиска только однажды.

mysql> SELECT id, body, MATCH (title,body) AGAINST
                 ('Security implications of running MySQL as root'
                 IN NATURAL LANGUAGE MODE) AS score
                 FROM articles WHERE MATCH (title,body) AGAINST
                 ('Security implications of running MySQL as root'
                 IN NATURAL LANGUAGE MODE);
+----+-------------------------------------+-----------------+
| id | body                                | score           |
+----+-------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |
|  6 | When configured properly, MySQL ... | 1.3114095926285 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

В MySQL FULLTEXT расценивает любую последовательность истинных символов слова (буквы, цифры и подчеркивания) как слово. Та последовательность может также содержать апострофы ('), но не больше, чем один подряд. Это означает, что aaa'bbb расценено как одно слово, но aaa''bbb как два. Апострофы в начале или конце слова игнорируются анализатором в любом количестве: 'aaa'bbb' обрабатывается как aaa'bbb.

Встроенный анализатор FULLTEXT определяет, где слова начинаются и заканчиваются, ища определенные символы-разделители, например, (пробел), , (запятая) и . (точка). Если слова не отделены разделителями (как в, например, китайском языке), встроенный анализатор FULLTEXT не может определить, где слово начинается или заканчивается. Чтобы добавить слова или другие индексированные термины на таких языках к индексу FULLTEXT, который использует встроенный анализатор FULLTEXT, Вы должны предварительно обработать их так, чтобы они были отделены некоторым произвольным разделителем, например, ". Альтернативно, Вы можете создать индексы FULLTEXT, используя плагин анализатора ngram (для китайского, японского или корейского языка) или плагин анализатора MeCab (для японского языка).

Возможно написать плагин, который заменяет встроенный полнотекстовый анализатор. Для деталей см. раздел 26.2. Например исходный код плагина анализатора есть в каталоге plugin/fulltext исходных текстов MySQL.

Некоторые слова проигнорированы в полнотекстовых поисках:

См. раздел 13.9.4 для значения по умолчанию списка стоп-слов и как изменить их. Минимум длины слова по умолчанию может быть изменен как описано в разделе 13.9.6.

Каждое правильное слово в наборе и в запросе взвешено, согласно его значению в наборе или запросе. Таким образом, у слова, которое присутствует во многих документах, есть более низкий вес, потому что у него есть более низкое семантическое значение в этом особом наборе. Наоборот, если слово редко, оно получает более высокий вес. Веса слов объединены, чтобы вычислить уместность строки. Этот метод работает лучше всего с большим количеством слов.

Ограничения MyISAM.

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

mysql> SELECT * FROM articles WHERE MATCH (title,body)
                   AGAINST ('MySQL' IN NATURAL LANGUAGE MODE);
Empty set (0.00 sec)

Результат поиска пуст, потому что MySQL присутствует по крайней мере в 50% строк и поэтому эффективно обработано как стоп-слово. Этот метод фильтрации является более подходящим для больших наборов данных, где Вы не могли бы хотеть, чтобы набор результатов возвратил каждую вторую строку из таблицы в 1GB, чем для маленьких наборов данных, где это могло бы вызвать маленькие результаты для популярных слов.

50% порог может удивить Вас, когда Вы сначала пробуете полнотекстовый поиск, чтобы видеть, как это работает, и делает таблицы InnoDB более подходящими для экспериментирования с полнотекстовыми поисками. Если Вы создаете таблицу MyISAM и вставляете только одну или две строки текста в нее, каждое слово в тексте будет по крайней мере в 50% строк. В результате никакой поиск не возвращает результатов, пока таблица не содержит больше строк. Пользователи, которые должны обойти 50% ограничение, могут создать поисковые индексы на таблицах InnoDB или использовать булев режим поиска, объясненный в разделе 13.9.2.

13.9.2. Булев полнотекстовый поиск

MySQL может выполнить булев полнотекстовый поиск, используя модификатор IN BOOLEAN MODE. С этим модификатором у определенных символов есть особое значение в начале или конце слов в строке поиска. В следующем запросе операторы + и - указывают, что слово должно присутствовать или отсутствовать, соответственно, для соответствия. Таким образом, запрос получает все строки, которые содержат слово MySQL, но не содержат слово YourSQL:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
                   AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+
| id | title                 | body                                |
+----+-----------------------+-------------------------------------+
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Well | After you went through a ...        |
|  3 | Optimizing MySQL      | In this tutorial we will show ...   |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security        | When configured properly, MySQL ... |
+----+-----------------------+-------------------------------------+

В реализации этой опции MySQL использует то, что иногда упоминается как подразумеваемая Булева логика, в которой:

У булевых полнотекстовых поисков есть эти характеристики:

Булев полнотекстовый поиск поддерживает следующие операторы:

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

Ранжирование уместности для режима InnoDB булева поиска

Полнотекстовый поиск InnoDB смоделирован на полнотекстовой поисковой системе Sphinx, используемые алгоритмы основаны на алгоритма ранжирования BM25 и TF-IDF. По этим причинам, ранжирование уместности для булева полнотекстового поиска InnoDB может отличаться от ранжирования уместности MyISAM.

InnoDB использует вариант системы взвешивания term frequency-inverse document frequency (TF-IDF), чтобы оценить уместность документа для данного полнотекстового запроса поиска. TF-IDF основана на том, как часто слово появляется в документе, с поправкой на то, как часто слово появляется во всех документах в наборе. Другими словами, чем более часто слово появляется в документе, и чем менее часто слово появляется в наборе документа, тем выше документ оценивается.

Как ранжирование уместности вычислено

Значение частоты термина (term frequency, TF) число раз, которые слово появляется в документе. Обратная частота документа (IDF) слова вычислено, используя следующую формулу, где total_records число записей в наборе, а matching_records число записей, в которых появляется критерий поиска.

${IDF} = log10( ${total_records} / ${matching_records} )

Когда документ содержит слово многократно, значение IDF умножено на значение TF:

${TF} * ${IDF}

Используя значения TF и IDF, уместность для документа вычислена, используя эту формулу:

${rank} = ${TF} * ${IDF} * ${IDF}

Формула продемонстрирована в следующих примерах.

Уместность для поиска отдельного слова

Этот пример демонстрирует вычисление ранжирования уместности для поиска изолированного слова.

mysql> CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200), body TEXT, FULLTEXT (title,body)) ENGINE=InnoDB;
Query OK, 0 rows affected (1.04 sec)

mysql> INSERT INTO articles (title,body) VALUES
  ('MySQL Tutorial','This database tutorial ...'),
  ("How To Use MySQL",'After you went through a ...'),
  ('Optimizing Your Database','In this database tutorial ...'),
  ('MySQL vs. YourSQL','When comparing databases ...'),
  ('MySQL Security','When configured properly, MySQL ...'),
  ('Database, Database, Database','database database database'),
  ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
  ('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..');
Query OK, 8 rows affected (0.06 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT id, title, body, MATCH (title,body)
                 AGAINST ('database' IN BOOLEAN MODE)
AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+---------------------+
| id | title                        | body                                | score               |
+----+------------------------------+-------------------------------------+---------------------+
|  6 | Database, Database, Database | database database database          |  1.0886961221694946 |
|  3 | Optimizing Your Database     | In this database tutorial ...       | 0.36289870738983154 |
|  1 | MySQL Tutorial               | This database tutorial ...          | 0.18144935369491577 |
|  2 | How To Use MySQL             | After you went through a ...        |   0                 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        |   0                 |
|  5 | MySQL Security               | When configured properly, MySQL ... |   0                 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |   0                 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     |   0                 |
+----+------------------------------+-------------------------------------+---------------------+
8 rows in set (0.00 sec)

Есть 8 записей всего, с 3, которые соответствуют поисковому термину database. Первая запись (id 6) содержит поисковый термин 6 раз и имеет ранжирование уместности 1.0886961221694946. Это значение ранжирования вычислено, используя значение TF 6 критерий поиска появляется 6 раз в записи id 6) и IDF 0.42596873216370745, который вычислен следующим образом (здесь 8 общее количество записей, 3 число записей, в которых критерий поиска появляется):

${IDF} = log10( 8 / 3 ) = 0.42596873216370745

Значения TF и IDF тогда вводятся в формулу:

{rank} = ${TF} * ${IDF} * ${IDF}

Выполнение вычисления в клиенте командной строки MySQL возвращает значение 1.088696164686938.

mysql> SELECT 6*log10(8/3)*log10(8/3);
+-------------------------+
| 6*log10(8/3)*log10(8/3) |
+-------------------------+
| 1.088696164686938       |
+-------------------------+
1 row in set (0.00 sec)

Вы можете заметить незначительные различия в значениях, возвращенных запросом SELECT ... MATCH ... AGAINST и клиентом командной строки MySQL (1.0886961221694946 и 1.088696164686938). Различие происходит из-за проблем округления между целыми числами и floats/doubles, которое выполнено внутренне InnoDB (наряду со связанной точностью и округлением решений) и тем, как оно выполнено в другом месте (в клиенте командной строки MySQL или других типах вычислителей).

Уместность для поиска нескольких слов

Этот пример демонстрирует вычисление ранжирования уместности для полнотекстового поиска нескольких слов, основанного на таблице articles и данных, которые используются в предыдущем примере.

Если Вы ищете больше, чем одно слово, значение ранжирования уместности сумма значений ранжирования уместности для каждого слова, как показано в этой формуле:

${rank} = ${TF} * ${IDF} * ${IDF} + ${TF} * ${IDF} * ${IDF}

Выполнение поиска на двух условиях ('mysql tutorial') возвращает следующие результаты:

mysql> SELECT id, title, body, MATCH (title,body)
                 AGAINST ('mysql tutorial' IN BOOLEAN MODE)
                 AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+----------------------+
| id | title                        | body                                | score                |
+----+------------------------------+-------------------------------------+----------------------+
|  1 | MySQL Tutorial               | This database tutorial ...          |   0.7405621409416199 |
|  3 | Optimizing Your Database     | In this database tutorial ...       |   0.3624762296676636 |
|  5 | MySQL Security               | When configured properly, MySQL ... | 0.031219376251101494 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     | 0.031219376251101494 |
|  2 | How To Use MySQL             | After you went through a ...        | 0.015609688125550747 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        | 0.015609688125550747 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... | 0.015609688125550747 |
|  6 | Database, Database, Database | database database database          | 0                    |
+----+------------------------------+-------------------------------------+----------------------+
8 rows in set (0.00 sec)

В первой записи (id 8) 'mysql' появляется однажды, а 'tutorial' два раза. Есть шесть соответствующих записей для 'mysql' и две для 'tutorial'. Клиент командной строки MySQL возвращает ожидаемое значение ранжирования, вставляя эти значения в формулу для многократного поиска слова:

mysql> SELECT (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2));
+-------------------------------------------------------+
| (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)) |
+-------------------------------------------------------+
| 0.7405621541938003                                    |
+-------------------------------------------------------+
1 row in set (0.00 sec)

Незначительные различия в значениях, возвращенных SELECT ... MATCH ... AGAINST и клиентом командной строки MySQL объяснены в предыдущем примере.

13.9.3. Полнотекстовые поиски с расширением запроса

Полнотекстовый поиск поддерживает расширение запроса (и, в частности, его разновидность blind query expansion). Это вообще полезно, когда фраза поиска слишком коротка, что часто означает, что пользователь полагается на подразумеваемое знание, которого полнотекстовой поисковой системе недостает. Например, пользователь, ищущий database может действительно подразумевать, что MySQL, Oracle, DB2, и RDBMS являются фразами, которые должны соответствовать databases и должны быть возвращены. Это подразумеваемое знание.

Blind query expansion (также известн, как автоматическая обратная связь уместности) включен, добавляя WITH QUERY EXPANSION или IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION после фразы поиска. Это работает, выполняя поиск дважды, поисковая фраза для второго поиска, это оригинальная фраза поиска, связанная с немногими наиболее соответствующими документами из первого поиска. Таким образом, если один из этих документов содержит слова databases и MySQL, второй поиск находит документы, которые содержат MySQL, даже если они не содержат database. Следующий пример показывает это различие:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
                   AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM articles WHERE MATCH (title,body)
                   AGAINST ('database' WITH QUERY EXPANSION);
+----+-----------------------+------------------------------------------+
| id | title                 | body                                     |
+----+-----------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL     | In the following database comparison ... |
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...             |
|  3 | Optimizing MySQL      | In this tutorial we will show ...        |
|  6 | MySQL Security        | When configured properly, MySQL ...      |
|  2 | How To Use MySQL Well | After you went through a ...             |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ...      |
+----+-----------------------+------------------------------------------+
6 rows in set (0.00 sec)

Другой пример мог искать книги Georges Simenon о Maigret, когда пользователь не уверен, как писать Maigret. Поиск Megre and the reluctant witnesses найдет только Maigret and the Reluctant Witnesses без расширения запроса. Поиск с расширением запроса считает все книги со словом Maigret на втором проходе.

Поскольку расширение запроса имеет тенденцию значительно увеличивать шум, возвращая несоответствующие документы, используйте это только, когда фраза поиска коротка.

13.9.4. Полнотекстовые стоп-слова

Список стоп-слов загружен и просматривается для полнотекстовых запросов, используя набор символов сервера и сопоставление (значения переменных character_set_server и collation_server). Ложные хиты или промахи могли бы произойти для стоп-слов поисков, если у стоп-слов файла или столбцов, используемых для полнотекстовой индексации или поисков, есть набор символов или сопоставление, отличающееся от character_set_server или collation_server.

Чувствительность к регистру стоп-слов поисков зависит от сопоставления сервера. Например, поиски являются нечувствительными к регистру, если сопоставление latin1_swedish_ci, тогда как поиски являются чувствительными к регистру, если сопоставление latin1_general_cs или latin1_bin.

Стоп-слова для поисковых индексов InnoDB

InnoDB имеет относительно короткий список стоп-слов по умолчанию, потому что документы из технических, литературных и других источников часто используют короткие слова в качестве ключевых слов или в существенных фразах. Например, Вы могли бы искать to be or not to be и ожидать получения заметного результата, вместо того, чтобы игнорировать все эти слова.

Чтобы посмотреть список стоп-слов в InnoDB по умолчанию, запросите таблицу INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD.

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD;
+-------+
| value |
+-------+
| a     |
| about |
| an    |
| are   |
| as    |
| at    |
| be    |
| by    |
| com   |
| de    |
| en    |
| for   |
| from  |
| how   |
| i     |
| in    |
| is    |
| it    |
| la    |
| of    |
| on    |
| or    |
| that  |
| the   |
| this  |
| to    |
| was   |
| what  |
| when  |
| where |
| who   |
| will  |
| with  |
| und   |
| the   |
| www   |
+-------+
36 rows in set (0.00 sec)

Определить Ваш собственный список стоп-слов для всех таблиц InnoDB можно, определив таблицу с той же самой структурой, как у INNODB_FT_DEFAULT_STOPWORD, заполнив ее стоп-словами и установив значение innodb_ft_server_stopword_table в форме db_name/table_name прежде, чем создать полнотекстовый индекс. У таблицы стоп-слов должен быть один столбец VARCHAR с именем value. Следующий пример демонстрирует создание и конфигурирование новой глобальной таблицы стоп-слов для InnoDB.

-- Create a new stopword table

mysql> CREATE TABLE my_stopwords(value VARCHAR(30)) ENGINE = INNODB;
Query OK, 0 rows affected (0.01 sec)

-- Insert stopwords (for simplicity, a single stopword is used in this example)

mysql> INSERT INTO my_stopwords(value) VALUES ('Ishmael');
Query OK, 1 row affected (0.00 sec)

-- Create the table

mysql> CREATE TABLE opening_lines (
            id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
            opening_line TEXT(500), author VARCHAR(200),
            title VARCHAR(200)) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

-- Insert data into the table

mysql> INSERT INTO opening_lines(opening_line,author,title) VALUES
  ('Call me Ishmael.','Herman Melville','Moby-Dick'),
  ('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
  ('I am an invisible man.','Ralph Ellison','Invisible Man'),
  ('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
  ('It was love at first sight.','Joseph Heller','Catch-22'),
  ('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
  ('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
  ('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

-- Set the innodb_ft_server_stopword_table option to the new stopword table

mysql> SET GLOBAL innodb_ft_server_stopword_table = 'test/my_stopwords';
Query OK, 0 rows affected (0.00 sec)

-- Create the full-text index (which rebuilds the table if no FTS_DOC_ID column is defined)

mysql> CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);
Query OK, 0 rows affected, 1 warning (1.17 sec)
Records: 0  Duplicates: 0  Warnings: 1

Проверьте, что указанное стоп-слово ('Ishmael') не появляется, запрашивая слова в INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.

По умолчанию, слова меньше, чем 3 символа в длину или больше, чем 84 символа не появляются в полнотекстовом индексе InnoDB. Максимальные и минимальные значения длины слова конфигурируются с применеием переменных innodb_ft_max_token_size и innodb_ft_min_token_size. Это поведение не относится к плагину анализатора ngram. Маркерный размер ngram определен опцией ngram_token_size .

mysql> SET GLOBAL innodb_ft_aux_table='test/opening_lines';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT word FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE LIMIT 15;
+-----------+
| word      |
+-----------+
| across    |
| all       |
| burn      |
| buy       |
| call      |
| comes     |
| dalloway  |
| first     |
| flowers   |
| happened  |
| herself   |
| invisible |
| less      |
| love      |
| man       |
+-----------+
15 rows in set (0.00 sec)

Чтобы создать списки стоп-слов на основе таблицы, составьте другие таблицы стоп-слов и используйте опцию innodb_ft_user_stopword_table, чтобы определить таблицу стоп-слов, которую Вы хотите использовать прежде, чем Вы создадите полнотекстовый индекс.

Стоп-слова для поиска в MyISAM

Файл загружен стоп-слов загружен с использованием latin1, если character_set_server ucs2, utf16, utf16le или utf32.

Чтобы переопределить значение по умолчанию списка стоп-слов для таблиц MyISAM, установите переменную ft_stopword_file. См. раздел 6.1.5. Значение должно быть путем к файлу, содержащему список стоп-слов, или пустой строкой, чтобы отключить фильтрацию стоп-слов. Сервер ищет файл в каталоге данных, если абсолютный путь не дан, чтобы определить иной каталог. После изменения значения этой переменной или содержания файла стоп-слов, перезапустите сервер и восстановите Ваши индексы FULLTEXT.

Список стоп-слов имеет свободную форму. Слова разделяются любым знаком (не буквой и не цифрой). Годятся пробелы, запятые или перевод строки. Исключения символ подчеркивания (_) и единственный апостроф ('), которые обработаны как часть слова. Набор символов списка стоп-слов это набор символов сервера, см. раздел 11.1.3.2.

Следующая таблица показывает список стоп-слов по умолчанию для MyISAM. В исходных текстах MySQL он находится в файле storage/myisam/ft_static.c.

a'sableaboutabove according
accordinglyacrossactually afterafterwards
againagainstain'tall allow
allowsalmostalonealong already
alsoalthoughalwaysam among
amongstanandanother any
anybodyanyhowanyone anythinganyway
anywaysanywhereapart appearappreciate
appropriatearearen't aroundas
asideaskaskingassociated at
availableawayawfully bebecame
becausebecomebecomes becomingbeen
beforebeforehandbehind beingbelieve
belowbesidebesidesbest better
betweenbeyondbothbrief but
byc'monc'scame can
can'tcannotcantcause causes
certaincertainlychanges clearlyco
comcomecomesconcerning consequently
considerconsideringcontain containingcontains
correspondingcouldcouldn't coursecurrently
definitelydescribeddespite diddidn't
differentdodoesdoesn't doing
don'tdonedowndownwards during
eacheduegeight either
elseelsewhereenough entirelyespecially
etetcevenever every
everybodyeveryoneeverything everywhereex
exactlyexampleexceptfar few
fifthfirstfivefollowed following
followsforformerformerly forth
fourfromfurtherfurthermore get
getsgettinggivengives go
goesgoinggonegot gotten
greetingshadhadn'thappens hardly
hashasn'thavehaven't having
hehe'shellohelp hence
herherehere'shereafter hereby
hereinhereuponhersherself hi
himhimselfhishither hopefully
howhowbeithoweveri'd i'll
i'mi'veieif ignored
immediateininasmuchinc indeed
indicateindicatedindicates innerinsofar
insteadintoinwardis isn't
itit'dit'llit's its
itselfjustkeepkeeps kept
knowknownknowslast lately
laterlatterlatterlyleast less
lestletlet'slike liked
likelylittlelooklooking looks
ltdmainlymanymay maybe
memeanmeanwhilemerely might
moremoreovermostmostly much
mustmymyselfname namely
ndnearnearlynecessary need
needsneithernever neverthelessnew
nextninenonobody non
nonenoonenornormally not
nothingnovelnownowhere obviously
ofoffoftenohok
okayoldononceone
onesonlyontoor other
othersotherwiseoughtour ours
ourselvesoutoutsideover overall
ownparticularparticularly perperhaps
placedpleasepluspossible presumably
probablyprovidesquequite qv
ratherrdrereally reasonably
regardingregardlessregards relativelyrespectively
rightsaidsamesaw say
sayingsayssecondsecondly see
seeingseemseemedseeming seems
seenselfselvessensible sent
seriousseriouslysevenseveral shall
sheshouldshouldn'tsince six
sosomesomebodysomehow someone
somethingsometimesometimes somewhatsomewhere
soonsorryspecifiedspecify specifying
stillsubsuchsupsure
t'staketakentelltends
ththanthankthanks thanx
thatthat'sthatsthe their
theirsthemthemselvesthen thence
therethere'sthereafterthereby therefore
thereintheresthereuponthese they
they'dthey'llthey'rethey've think
thirdthisthoroughthoroughly those
thoughthreethroughthroughout thru
thustotogethertootook
towardtowardstriedtries truly
trytryingtwicetwoun
underunfortunatelyunless unlikelyuntil
untoupuponususe
usedusefulusesusing usually
valuevariousveryvia viz
vswantwantswaswasn't
waywewe'dwe'llwe're
we'vewelcomewellwent were
weren'twhatwhat'swhatever when
whencewheneverwherewhere's whereafter
whereaswherebywhereinwhereupon wherever
whetherwhichwhilewhither who
who'swhoeverwholewhom whose
whywillwillingwish with
withinwithoutwon'twonder would
wouldn'tДаyetyou you'd
you'llyou'reyou'veyour yours
yourselfyourselveszero

13.9.5. Полнотекстовые ограничения

13.9.6. Точная настройка полнотекстового поиска в MySQL

У полнотекстового поиска MySQL есть немного настраиваемых пользователем параметров. Вы можете осуществить больший контроль над поведением полнотекстового поиска, если у Вас есть исходные тексты MySQL, потому что некоторые изменения требуют модификаций исходного кода. См. раздел 2.8.

Полнотекстовый поиск тщательно настроен для эффективности. Изменение поведения по умолчанию в большинстве случаев может фактически уменьшить эффективность. Не изменяйте исходные тексты MySQL, если Вы не знаете точно, что делаете!

Во время запуска сервера должно быть установлено большинство полнотекстовых переменных, описанных в этом разделе. Перезапуск сервера обязан изменять их, они не могут быть изменены в то время, когда сервер работает.

Некоторые переменные требуют, чтобы Вы пересоздали индексы FULLTEXT в Ваших таблицах. Инструкции для этого даны позже в этом разделе.

7084

Конфигурирование минимальной и максимальной длины слова

Минимальные и максимальные длины слов, которые будут индексированы, определены innodb_ft_min_token_size и innodb_ft_max_token_size для InnoDB или ft_min_word_len и ft_max_word_len для MyISAM.

Минимальная и максимальная длина слова не относится к индексам FULLTEXT создаваемым с использованием анализатора ngram. Маркерный размер для него определен опцией ngram_token_size .

После изменения любой из этих опций пересоздайте индексы FULLTEXT, чтобы вступили в силу изменения. Например, чтобы сделать двухсимвольные слова доступными для поиска, Вы могли поместить следующие строки в файл опции:

[mysqld]
innodb_ft_min_token_size=2
ft_min_word_len=2

Теперь перезапустите сервер и пересоздайте индексы FULLTEXT. Для таблиц MyISAM отметьте замечания относительно myisamchk в инструкциях ниже для того, чтобы пересоздать индексы MyISAM.

Конфигурирование порога поиска естественного языка

Для поисковых индексов MyISAM 50% порог для поисков естественного языка определен особой выбранной схемой. Чтобы отключить это, ищите следующую строку в storage/myisam/ftdefs.h:

#define GWS_IN_USE GWS_PROB

Замените ее на:

#define GWS_IN_USE GWS_FREQ

Повторно соберите MySQL. Нет никакой потребности пересоздавать индексы в этом случае.

Производя это изменение, Вы строго уменьшаете способность MySQL обеспечить соответствующие значения уместности для функции MATCH(). Если Вы действительно должны искать такие общие слова, было бы лучше искать с использованием IN BOOLEAN MODE, который не имеет 50% порога.

Изменение булевых полнотекстовых операторов поиска

Чтобы изменить операторы, используемые для булевых полнотекстовых поисков в таблицах MyISAM, установите переменную ft_boolean_syntax . InnoDB не имеет эквивалентной установки. Эта переменная может быть изменена в то время, как сервер работает, но Вы должны иметь привилегию SUPER. Никакое пересоздание индексов не нужно в этом случае. См. раздел 6.1.5, который описывает правила, как установить эту переменную.

Модификации набора символов

Для встроенного полнотекстового анализатора Вы можете изменить набор символов, которые считаются символами слова, несколькими способами, как описано в следующем списке. После создания модификации, восстановите индексирование для каждой таблицы, которая содержит любой индекс FULLTEXT. Предположите, что Вы хотите обработать символ дефиса ('-') как символ слова. Используйте один из этих методов:

Пересоздание полнотекстового индекса InnoDB

Если Вы изменяете полнотекстовые переменные ( innodb_ft_min_token_size, innodb_ft_max_token_size, innodb_ft_server_stopword_table, innodb_ft_user_stopword_table, innodb_ft_enable_stopword, ngram_token_size Вы должны восстановить Ваш индекс FULLTEXT после произведения изменений. Изменение переменных innodb_ft_min_token_size, innodb_ft_max_token_size или ngram_token_size , которые не могут быть установлены динамически, требует перезапуска сервера и восстановления индекса.

Для пересоздания индекса FULLTEXT таблицы InnoDB, используйте ALTER TABLE с опциями DROP INDEX и ADD INDEX, чтобы удалить и обновить каждый индекс.

Оптимизация полнотекстового индексирования InnoDB

Выполнение OPTIMIZE TABLE на таблице с полнотекстовым индексом восстанавливает полнотекстовое индексирование, физически удаляя удаленные логически Document ID и объединяя записи для того же самого слова, где только возможно.

Чтобы оптимизировать полнотекстовый индекс, включите innodb_optimize_fulltext_only и выполните OPTIMIZE TABLE.

mysql> set GLOBAL innodb_optimize_fulltext_only=ON;
Query OK, 0 rows affected (0.01 sec)

mysql> OPTIMIZE TABLE opening_lines;
+--------------------+----------+----------+----------+
| Table              | Op       | Msg_type | Msg_text |
+--------------------+----------+----------+----------+
| test.opening_lines | optimize | status   | OK       |
+--------------------+----------+----------+----------+
1 row in set (0.01 sec)

Чтобы избежать длинного пересоздания полнотекстового индекса на больших таблицах, Вы можете использовать опцию innodb_ft_num_word_optimize, чтобы выполнить оптимизацию шаг за шагом. Опция innodb_ft_num_word_optimize определяет число слов, которые оптимизированы каждый раз при запуске OPTIMIZE TABLE. Настройка по умолчанию 2000, что означает, что 2000 слов оптимизированы каждый раз при запуске OPTIMIZE TABLE. Последующий запуск OPTIMIZE TABLE продолжит работу с того места, где завершился предыдущий.

Восстановление полнотекстового индекса MyISAM

Если Вы изменяете полнотекстовые переменные (ft_min_word_len , ft_max_word_len или ft_stopword_file ), или если Вы изменяете файл стоп-слов непосредственно, Вы должны восстановить Ваш индекс FULLTEXT после произведения изменений и перезапуска сервера.

Для этого на таблице MyISAM достаточно сделать восстановление в режиме QUICK:

mysql> REPAIR TABLE tbl_name QUICK;

Альтернативно, можно использовать ALTER TABLE. В некоторых случаях, это может быть быстрее, чем работа восстановления.

Каждая таблица, которая содержит любой индекс FULLTEXT, должна быть восстановлена. Иначе запросы к таблице могут привести к неправильным результатам, и модификации к таблице заставят сервер рассматривать таблицу как поврежденную и нуждающуюся в ремонте.

Если Вы используете myisamchk, чтобы выполнить работу, которая изменяет индексы таблицы MyISAM (например, repair или analyze), индексы FULLTEXT должны быть восстановлены, используя значения по умолчанию параметров для минимальной длины слова, максимальной длины слова и файла стоп-слов, если Вы не определяете иное. Это может привести к провалу попытки запросов.

Проблема происходит, потому что эти параметры известны только серверу. Они не сохранены в индексных файлах MyISAM. Чтобы избежать проблемы, если Вы изменили минимальную или максимальную длину слова или значения файла стоп-слов, используемые сервером, определите те же самые значения для переменных ft_min_word_len, ft_max_word_len и ft_stopword_file для программы myisamchk , которые Вы используете для mysqld. Например, если Вы установили минимальную длину слова 3, Вы можете восстановить таблицу с myisamchk так:

shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI

Чтобы гарантировать, что myisamchk и сервер используют те же самые значения для полнотекстовых параметров, разместите их в обоих секциях [mysqld] и [myisamchk] файла опций:

[mysqld]
ft_min_word_len=3

[myisamchk]
ft_min_word_len=3

Альтернатива использованию myisamchk для модификации табличных индексов MyISAM состоит в применении запросов the REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE или ALTER TABLE. Они выполнены сервером, который знает надлежащие значения параметров.

13.9.7. Добавление сопоставления для полнотекстовой индексации

Этот раздел описывает, как добавить новое сопоставление для полнотекстовых поисков, используя встроенный полнотекстовый анализатор. Типовое сопоставление походит на latin1_swedish_ci, но обработает символ '-' как букву, а не символ пунктуации так, чтобы это могло быть индексировано как символ слова. Общая информация о добавлении сопоставлений дана в разделе 11.4. Предполагается, что Вы читали это и знакомы с вовлеченными файлами.

Чтобы добавить сопоставление для полнотекстовой индексации, используйте эту процедуру:

  1. Добавьте сопоставление к файлу Index.xml. ID сопоставления должен быть уникальным.

    <charset name="latin1">
    ...
    <collation name="latin1_fulltext_ci" id="1000"/>
    </charset>
    
  2. Объявите порядок сортировки для сопоставления в файле latin1.xml. В этом случае порядок может быть скопирован с latin1_swedish_ci:
    <collation name="latin1_fulltext_ci">
    <map>
    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
    20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
    30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
    50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
    60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
    50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
    80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
    90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
    A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
    B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
    41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
    44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
    41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
    44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
    </map>
    </collation>
    
  3. Измените массив ctype в latin1.xml. Измените значение, соответствующее 0x2D (код символа '-') с 10 (пунктуация) на 01 (строчная буква). В следующем массиве это элемент в четвертой строке, третье значение от конца.
    <ctype>
    <map>
    00
    20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
    20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
    48 10 10 10 10 10 10 10 10 10 10 10 10 01 10 10
    84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
    10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
    01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
    10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
    02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
    10 00 10 02 10 10 10 10 10 10 01 10 01 00 01 00
    00 10 10 10 10 10 10 10 10 10 02 10 02 00 02 01
    48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
    10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
    01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
    01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
    02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
    02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
    </map>
    </ctype>
    
  4. Перезапустите сервер.
  5. Чтобы использовать новое сопоставление, включите это в определение столбцов, которые должны его использовать:
    mysql> DROP TABLE IF EXISTS t1;
    Query OK, 0 rows affected (0.13 sec)
    
    mysql> CREATE TABLE t1 (
      a TEXT CHARACTER SET latin1 COLLATE latin1_fulltext_ci,
      FULLTEXT INDEX(a)) ENGINE=InnoDB;
    Query OK, 0 rows affected (0.47 sec)
    
  6. Проверьте сопоставление, чтобы проверить, что дефис рассматривают как символ слова:
    mysql> INSERT INTO t1 VALUEs ('----'),('....'),('abcd');
    Query OK, 3 rows affected (0.22 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SELECT * FROM t1 WHERE MATCH a AGAINST ('----' IN BOOLEAN MODE);
    +------+
    | a    |
    +------+
    | ---- |
    +------+
    1 row in set (0.00 sec)
    

13.9.8. Полнотекстовый анализатор ngram

Полнотекстовый анализатор MySQL использует пробел между словами как разделитель, чтобы определить, где слова начинаются и заканчиваются. Это является ограничением, работая с идеографическими языками, которые не используют разделители слова. Чтобы обойти это ограничение, MySQL обеспечивает полнотекстовый анализатор ngram, который поддерживает китайский, японский и корейский язык (CJK). ngram поддержан для использования с InnoDB и MyISAM.

MySQL также предоставляет полнотекстовый плагин MeCab анализатора японского языка, который размечает документы на значащие слова. Для получения дополнительной информации см. раздел 13.9.9.

ngram это непрерывная последовательность из n символов данной последовательности текста. ngram анализатор размечает последовательность текста в непрерывную последовательность n символов. Например, Вы можете разметить abcd для различных значений n:

n=1: 'a', 'b', 'c', 'd'
n=2: 'ab', 'bc', 'cd'
n=3: 'abc', 'bcd'
n=4: 'abcd'

Полнотекстовый анализатор ngram встроенный плагин сервера. Как и с другими встроенными плагинами сервера, это автоматически загружено, когда сервер запущен.

Полнотекстовый синтаксис поиска, описанный в разделе 13.9 относится к плагину анализатора ngram. Различия в поведении парсинга описаны в этом разделе. Связанные параметры конфигурации, за исключением минимальных и максимальных длин слова также применимы.

Конфигурирование маркерного размера ngram

У анализатора ngram есть значение по умолчанию маркерного размера 2 (bigram). Например, с маркерным размером 2, ngram разбирает строку abc def на четыре маркера: ab, bc, de и ef.

Маркерный размер ngram конфигурируется опцией ngram_token_size , у которой есть минимальное значение 1 и максимальное 10.

Как правило, ngram_token_size установлен в размер самого большого маркера, который Вы хотите искать. Если Вы намереваетесь искать только единственные символы, надо установить ngram_token_size в 1. Меньший маркерный размер производит меньший полнотекстовый индекс и более быстрые поиски. Если Вы должны искать слова, состоявшие больше, чем из одного символа, стоит установить ngram_token_size соответственно. Например, Happy Birthday Г■÷Ф≈╔Е©╚Д╧░ в простом китайском, где Г■÷Ф≈╔ birthday, а Е©╚Д╧░ переводится как happy. Чтобы искать на двухсимвольных словах, установите ngram_token_size в 2 или выше.

Как переменная только для чтения, ngram_token_size может быть установлена как часть строки запуска или в конфигурационном файле:

Следующие параметры конфигурации длины слова проигнорированы для индексов FULLTEXT анализатором ngram: innodb_ft_min_token_size, innodb_ft_max_token_size, ft_min_word_len и ft_max_word_len .

Создание индексов FULLTEXT для ngram

Чтобы создать индекс FULLTEXT, который использует анализатор ngram, определите WITH PARSER ngram в CREATE TABLE, ALTER TABLE или CREATE INDEX.

Следующий пример демонстрирует составление таблицы с индексом ngram FULLTEXT, вставляя типовые данные (текст на упрощенном китайском) и рассматривая размеченные данные в таблице INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE.

mysql> USE test;
mysql> CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200), body TEXT, FULLTEXT (title,body)
  WITH PARSER ngram) ENGINE=InnoDB CHARACTER SET utf8mb4;
mysql> SET NAMES utf8mb4;

INSERT INTO articles (title,body) VALUES
('Ф∙╟Ф█╝Е╨⌠Г╝║Г░├','Е°╗Ф°╛Ф∙≥Г╗▀Д╦╜Ф┬▒Е╟├Е░▒Д╫═Е╠∙Г╓╨Е╕┌Д╫∙Г╝║Г░├Ф∙╟Ф█╝Е╨⌠'),
('Ф∙╟Ф█╝Е╨⌠Е╨■Г■╗Е╪─Е▐▒','Е╜╕Д╧═Е╪─Е▐▒Ф∙╟Ф█╝Е╨⌠Е╨■Г■╗Г╗▀Е╨▐');

mysql> SET GLOBAL innodb_ft_aux_table="test/articles";
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
                   ORDER BY doc_id, position;

Добавить индекс FULLTEXT к существующей таблице Вы можете, используя ALTER TABLE или CREATE INDEX. Например:

CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200), body TEXT) ENGINE=InnoDB CHARACTER SET utf8;
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title, body)
      WITH PARSER ngram;
# Или:
CREATE FULLTEXT INDEX ft_index ON articles (title, body) WITH PARSER ngram;

Обработка пробелов в ngram

Анализатор ngram устраняет пробелы, разбирая текст. Например:

Обработка стоп-слов в ngram

Встроенный в MySQL полнотекстовый анализатор сравнивает слова с записями в списке стоп-слов. Если слово равно записи в списке стоп-слов, оно будет исключено из индексирования. Для анализатора ngram обработка стоп-слов выполнена по-другому. Вместо исключения маркеров, которые равны записям в списке стоп-слов, анализатор ngram исключает маркеры, которые содержат стоп-слова. Например, приняв ngram_token_size=2 , документ, который содержит a,b разберется как a, и ,b. Если запятая (,) определена как стоп-слово, a, и ,b исключены из индексирования, потому что они содержат запятую.

По умолчанию, ngram использует список стоп-слов, который содержит список английского стоп-слов. Для списка стоп-слов применимого к китайскому, японскому или корейскому языку Вы должны создать свой собственный. Для информации о создании списка стоп-слов см. раздел 13.9.4.

Игнорируются стоп-слова с длиной больше ngram_token_size .

Поиск терминов в ngram

Для поиска в режиме режиме естественного языка критерий поиска преобразован в союз слов в ngram. Например, строка abc ( ngram_token_size=2) станет ab bc. Учитывая два документа, один содержащий ab, другой abc, критерий поиска ab bc соответствует обоим документам.

Для режима boolean search критерий поиска преобразован в поисковую фразу ngram. Например, строка 'abc' (ngram_token_size=2 ) разберется на 'ab bc'. Учитывая два документа, один содержащий 'ab' и другой содержащий 'abc', фраза поиска 'ab bc' соответствует только документу, содержащему 'abc'.

Подстановочный поиск анализатора ngram

Поскольку индекс ngram FULLTEXT содержит только токены и не содержит информацию о начале слов, подстановочные поиски могут возвратить неожиданные результаты. Следующие примеры поведения относятся к подстановочным поискам, использующим индексы ngram FULLTEXT:

Поиск фразы в ngram

Поисковые фразы преобразованы в поисковые фразы ngram. Например, фраза поиска abc преобразована в ab bc, которая возвращает документы, содержащие abc и ab bc.

Фраза поиска abc def преобразована в ab bc de ef , которая возвращает документы, содержащие abc def и ab bc de ef. Документ, который содержит abcdef не будет возвращен.

13.9.9. Полнотекстовый плагин анализатора MeCab

Полнотекстовый анализатор встроенного MySQL использует пробел между словами как разделитель, чтобы определить, где слова начинаются и заканчиваются. Это является ограничением, работая с идеографическими языками, которые не используют разделители слова. Чтобы обойти это ограничение для японского языка, MySQL предоставляет полнотекстовый плагин анализатора MeCab. Он поддержан для использования с InnoDB и MyISAM.

Полнотекстовый плагин анализатора MeCab это плагин для японского языка, который размечает последовательность текста на значащие слова. Например, MeCab размечает Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├ (Database Management) в Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧ (Database) и Г╝║Г░├ (Management). В сравнении с ngram полнотекстовый анализатор размечает текст в непрерывную последовательность из n символов, где n от 1 до 10.

В дополнение к разметке текста на значащие слова MeCab индексирует, как правило, меньше, чем ngram, а полнотекстовые поиски MeCab вообще быстрее. Один недостаток состоит в том, что разметка документа может занять больше времени у MeCab, чем у ngram.

Для дополнительной информации об анализаторе MeCab обратитесь к ресурсу MeCab Documentation.

Установка плагина анализатора MeCab

Плагин анализатора MeCab требует mecab и mecab-ipadic.

На Fedora, Debian и Ubuntu (кроме Ubuntu 12.04, где версия системы mecab слишком стара) MySQL динамически соединяется с системной установкой mecab, если это установлено по умолчанию. На других поддерживаемых Unix-подобных платформах libmecab.so статически скомпонована с libpluginmecab.so, которая расположена в каталоге плагина MySQL. mecab-ipadic включен в исполняемый код MySQL и находится в MYSQL_HOME\lib\mecab.

Вы можете установить mecab и mecab-ipadic используя утилиту управления пакетами (в Fedora, Debian или Ubuntu) или собрать mecab и mecab-ipadic из исходных текстов.

В Windows libmecab.dll находится в каталоге MySQL bin, а mecab-ipadic в MYSQL_HOME/lib/mecab.

Чтобы установить и сконфигурировать плагин анализатора MeCab, выполните следующие шаги:

  1. В конфигурационном файле MySQL установите опцию mecab_rc_file к местоположению конфигурационного файла mecabrc для MeCab. Если Вы используете пакет MeCab, распределенный с MySQL mecabrc находится в MYSQL_HOME/lib/mecab/etc/.

    [mysqld]
    loose-mecab-rc-file=MYSQL_HOME/lib/mecab/etc/mecabrc
    

    Префикс loose это модификатор опции. Опция mecab_rc_file не признана MySQL, пока плагин анализатора MeCaB не установлен, но это должно быть установлено прежде, чем попытаться установить плагин анализатора. Префикс loose позволяет Вам перезапустить MySQL, не сталкиваясь с ошибкой из-за непризнанной переменной.

    Если Вы используете свою собственную установку MeCab или создаете MeCab из исходных текстов, местоположение файла опций mecabrc может быть другим.

  2. Также в конфигурационном файле MySQL установите минимальный маркерный размер в 1 или 2, которые являются значениями, рекомендуемыми для использования с анализатором MeCab. Для таблиц InnoDB минимальный маркерный размер определен опцией innodb_ft_min_token_size, у которой есть значение по умолчанию 3. Для таблиц MyISAM минимальный маркерный размер определен опцией ft_min_word_len (значение по умолчанию 4).
    [mysqld]
    innodb_ft_min_token_size=1
    
  3. Измените конфигурационный файл mecabrc, чтобы определить словарь, который Вы хотите использовать. Пакет mecab-ipadic включает три словаря (ipadic_euc-jp, ipadic_sjis и ipadic_utf-8). Конфигурационный файл mecabrc, поставляемый с MySQL содержит запись, подобную следующему:
    dicdir = /path/to/mysql/lib/mecab/lib/mecab/dic/ipadic_euc-jp
    

    Чтобы использовать словарь ipadic_utf-8, модифицируйте запись так:

    dicdir=MYSQL_HOME/lib/mecab/dic/ipadic_utf-8
    

    Если Вы используете свою собственную установку MeCab или создали MeCab из исходных текстов, значение по умолчанию dicdir в файле mecabrc будет отличаться, соответственно координатам словарей.

    После того, как плагин анализатора MeCab установлен, Вы можете использовать статусную переменную mecab_charset, чтобы просмотреть набор символов, используемый MeCab. Три словаря MeCab, представленные в MySQL, поддерживают следующие наборы символов.

    mecab_charset только сообщает о первом поддержанном наборе символов. Например, словарь ipadic_utf-8 поддерживает utf8 и utf8mb4. mecab_charset всегда сообщает о utf8, когда этот словарь используется.

  4. Перезапустите MySQL.

  5. Установите плагин анализатора MeCab:

    Плагин анализатора MeCab установлен, используя синтаксис INSTALL PLUGIN. Имя плагина mecab, совместно используемое имя библиотеки libpluginmecab.so.

    INSTALL PLUGIN mecab SONAME 'libpluginmecab.so';
    

    После того, как установлен, плагин анализатора MeCab загружается при каждом нормальном перезапуске MySQL.

  6. Проверьте, что плагин анализатора MeCab загружен, используя SHOW PLUGINS.
    mysql> SHOW PLUGINS;
    

    Плагин mecab должен появиться в списке плагинов.

Создание индекса FULLTEXT, который использует анализатор MeCab

Чтобы создать индекс FULLTEXT, который использует анализатор mecab, определите WITH PARSER ngram с CREATE TABLE, ALTER TABLE или CREATE INDEX.

Этот пример демонстрирует составление таблицы с индексом mecab FULLTEXT, вставляя типовые данные и рассматривая размеченные данные в таблице INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE:

mysql> USE test;
mysql> CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200), body TEXT,
  FULLTEXT (title,body) WITH PARSER mecab) ENGINE=InnoDB CHARACTER SET utf8;

mysql> SET NAMES utf8;
mysql> INSERT INTO articles (title,body) VALUES
('Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├','Ц│⌠Ц│╝Ц┐│Ц┐╔Ц┐╪Ц┐┬Ц┐╙Ц┌╒Ц┐╚Ц│╖Ц│╞Ц─│Г╖│Ц│╞Ц│╘Ц│╝Ц┌┬Ц│├Ц│╚Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Ц┌▓Г╝║Г░├Ц│≥Ц┌▀Ф√╧ФЁ∙Ц┌▓Г╢╧Д╩▀Ц│≈Ц│╬Ц│≥'),
('Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Ц┌╒Ц┐≈Ц┐╙Ц┌╠Ц┐╪Ц┌╥Ц┐╖Ц┐ЁИ√▀Г≥╨','Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Ц┌╒Ц┐≈Ц┐╙Ц┌╠Ц┐╪Ц┌╥Ц┐╖Ц┐ЁЦ┌▓И√▀Г≥╨Ц│≥Ц┌▀Ц│⌠Ц│╗Ц┌▓Е╜╕Ц│╤');

mysql> SET GLOBAL innodb_ft_aux_table="test/articles";
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
                   ORDER BY doc_id, position;

Чтобы добавить индекс FULLTEXT к существующей таблице, Вы можете использовать ALTER TABLE или CREATE INDEX:

CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200), body TEXT) ENGINE=InnoDB CHARACTER SET utf8;
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body)
      WITH PARSER mecab;

# или:
CREATE FULLTEXT INDEX ft_index ON articles (title,body) WITH PARSER mecab;

Обработка пробелов анализатором MeCab

Анализатор MeCab использует пробелы в качестве разделителей в строках запроса. Например, анализатор MeCab размечает 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧ Г╝║Г░├' как 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧' и 'Г╝║Г░├'.

Обработка стоп-слов анализатором MeCab

По умолчанию анализатор MeCab использует короткий список английских стоп-слов. Поскольку список стоп-слов перечисляет применимые к японскому языку слова, Вы должны создать свой собственный. Для информации о создании списка стоп-слов см. раздел 13.9.4.

Поиск термина анализатором MeCab

Для поиска в режиме естественного языка критерий поиска преобразован в союз маркеров. Например, 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├' преобразуется в 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧ Г╝║Г░├'.

SELECT COUNT(*) FROM articles WHERE MATCH(title,body)
       AGAINST('Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├' IN NATURAL LANGUAGE MODE);

Для булева поиска критерий преобразован во фразу поиска. Например, 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├' преобразуется в '"Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧ Г╝║Г░├"'.

SELECT COUNT(*) FROM articles WHERE MATCH(title,body)
       AGAINST('Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├' IN BOOLEAN MODE);

Подстановочный поиск анализатором MeCab

Подстановочные критерии поиска не размечены. Поиск 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├*' выполнен на префиксе 'Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├'.

SELECT COUNT(*) FROM articles WHERE MATCH(title,body)
       AGAINST('Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧*' IN BOOLEAN MODE);

Поиск фразы анализатором MeCab

Фразы размечены. Например, "Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├" размечена как "Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧ Г╝║Г░├".

SELECT COUNT(*) FROM articles WHERE MATCH(title,body)
       AGAINST('"Ц┐┤Ц┐╪Ц┌©Ц┐≥Ц┐╪Ц┌╧Г╝║Г░├"' IN BOOLEAN MODE);

Установка MeCab из двоичного дистрибутива

Этот раздел описывает, как установить mecab и mecab-ipadic из двоичного дистрибутива, используя утилиту управления пакетами. Например, на Fedora Вы можете использовать Yum, чтобы выполнить установку:

yum mecab-devel

На Debian или Ubuntu Вы можете выполнить установку через APT:

apt-get install mecab
apt-get install mecab-ipadic

Установка MeCab из исходных текстов

Если Вы хотите создать mecab и mecab-ipadic из исходных текстов, основные шаги установки обеспечены ниже. Для дополнительной информации обратитесь к документации MeCab.

  1. Загрузите tar.gz пакеты для mecab и mecab-ipadic с http://taku910.github.io/mecab/#download.

  2. Установите mecab:
    tar zxfv mecab-0.996.tar
    cd mecab-0.996
    ./configure
    make
    make check
    su
    make install
    
  3. Установите mecab-ipadic:
    tar zxfv mecab-ipadic-2.7.0-20070801.tar
    cd mecab-ipadic-2.7.0-20070801
    ./configure
    make
    su
    make install
    
  4. Соберите MySQL, используя опцию WITH_MECAB для CMake. Установите опцию WITH_MECAB в system, если Вы установили mecab и mecab-ipadic в места по умолчанию.
    -DWITH_MECAB=system
    

    Если Вы определили пользовательский каталог установки, установите WITH_MECAB к пользовательскому каталогу. Например:

    -DWITH_MECAB=/path/to/mecab
    

13.10. Функции и операторы преобразования

Таблица 13.14. Функции и операторы преобразования

ИмяОписание
BINARY Преобразует обычную строку в двоичную
CAST() Приводит значение к определенному типу
CONVERT() Возвращает значение в качестве определенного типа

Функции и операторы преобразования включают преобразование значений одного типа данных в другой.

CONVERT() с параметром USING обеспечивает способ преобразовать данные между различными наборами символов:

CONVERT(expr USING transcoding_name)

В MySQL транскодирующие имена то же самое, что и соответствующие имена набора символов. Примеры:

SELECT CONVERT(_latin1'Mц╪ller' USING utf8);
INSERT INTO utf8_table (utf8_column)
SELECT CONVERT(latin1_column USING utf8) FROM latin1_table;

Вы можете также использовать CONVERT() без USING или CAST(), чтобы преобразовать строки между различными наборами символов:

CONVERT(string, CHAR[(N)]
        CHARACTER SET charset_name)
CAST(string AS CHAR[(N)]
     CHARACTER SET charset_name)

Примеры:

SELECT CONVERT('test', CHAR CHARACTER SET utf8);
SELECT CAST('test' AS CHAR CHARACTER SET utf8);

Если Вы определяете CHARACTER SET charset_name как показано, получающийся набор символов и сопоставление charset_name и сопоставление по умолчанию для charset_name. Если Вы опускаете CHARACTER SET charset_name , получающийся набор символов и сопоставление определены переменными character_set_connection и collation_connection , которые определяют набор символов соединения и сопоставление по умолчанию (см. раздел 11.1.4).

Пункт COLLATE не разрешен в пределах вызова CONVERT() или CAST(), но Вы можете применить это к функциональному результату. Например, это является законным:

SELECT CAST('test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;

Но это незаконно:

SELECT CAST('test' AS CHAR CHARACTER SET utf8 COLLATE utf8_bin);

Обычно Вы не можете сравнить значения BLOB или другие двоичные строки нечувствительным к регистру способом, потому что двоичные строки используют набор символов binary, у которого нет никакого сопоставления с понятием регистра символов. Чтобы выполнить нечувствительное к регистру сравнение, используйте функцию CONVERT() или CAST(), чтобы преобразовать значение в недвоичную строку. Сравнения получающейся строки используют ее сопоставление. Например, если у конверсионного набора символов результата есть нечувствительное к регистру сопоставление, операция LIKE не является чувствительной к регистру:

SELECT 'A' LIKE CONVERT(blob_col USING latin1)
           FROM tbl_name;

Чтобы использовать иной набор символов, замените его именем latin1 в предыдущем запросе. Чтобы определить особое сопоставление для переделанной строки, используйте предложение COLLATE после вызова CONVERT():

SELECT 'A' LIKE CONVERT(blob_col USING latin1)
           COLLATE latin1_german1_ci
           FROM tbl_name;

CONVERT() и CAST() могут использоваться более широко для того, чтобы сравнить строки, которые представлены в различных наборах символов.

Преобразование набора символов также полезное преобразование двоичных строк. LOWER() и UPPER() неэффективны, когда применено непосредственно к двоичным строкам, потому что понятие регистра не применяется. Чтобы выполнить смену регистра двоичной строки, сначала преобразуйте это в недвоичную строку:

mysql> SET @str = BINARY 'New York';
mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));
+-------------+-----------------------------------+
| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |
+-------------+-----------------------------------+
| New York    | new york                          |
+-------------+-----------------------------------+

Если Вы преобразовываете индексированные столбцы, применяя BINARY, CAST() или CONVERT(), MySQL, возможно, не в состоянии использовать индексирование эффективно.

Функции конвертации полезны для создания столбца с определенным типом в CREATE TABLE ... SELECT:

mysql> CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE) AS c1;
mysql> SHOW CREATE TABLE new_table\G
*************************** 1. row ***************************
 Table: new_table
Create Table: CREATE TABLE `new_table` (`c1` date DEFAULT NULL)
                     ENGINE=InnoDB DEFAULT CHARSET=latin1

Функции конвертации также могут быть полезными для сортировки столбцов ENUM в лексическом порядке. Обычно сортировка ENUM происходит, используя внутренние числовые значения. Преобразование значений в CHAR дает результаты в лексическом виде:

SELECT enum_col FROM tbl_name
       ORDER BY CAST(enum_col AS CHAR);

CAST() также изменяет результат, если Вы используете его в качестве части более сложного выражения, например, CONCAT('Date: ',CAST(NOW() AS DATE)).

Для временных значений есть небольшая потребность использовать CAST(), чтобы извлечь данные в различных форматах. Вместо этого используйте такие функции: EXTRACT(), DATE_FORMAT() или TIME_FORMAT().

Чтобы преобразовать строку к числу, Вы обычно должны просто использовать строковое значение в числовом контексте:

mysql> SELECT 1+'1';
    -> 2

Это также истина для шестнадцатеричных и двоичных литералов, которые являются двоичными строками по умолчанию:

mysql> SELECT X'41', X'41'+0;
    -> 'A', 65
mysql> SELECT b'1100001', b'1100001'+0;
    -> 'a', 97

Строка, используемая в арифметической работе, преобразована в число с плавающей запятой во время оценки выражения.

Число, используемое в строковом контексте, преобразовано в строку:

mysql> SELECT CONCAT('hello you ',2);
    -> 'hello you 2'

MySQL поддерживает арифметику 64-bit для значений со знаком и без него. Если Вы используете числовые операторы (+ или -, например) и один из операндов целое число без знака, результат без знака по умолчанию. Вы можете переопределить это при использовании оператора SIGNED или UNSIGNED, чтобы привести значение к соответствующему 64-bit целому числу.

mysql> SELECT 1 - 2;
    -> -1
mysql> SELECT CAST(1 - 2 AS UNSIGNED);
    -> 18446744073709551615
mysql> SELECT CAST(CAST(1 - 2 AS UNSIGNED) AS SIGNED);
    -> -1

Если любой операнд значение с плавающей запятой, результат значение с плавающей запятой и не затронут предыдущим правилом. В этом контексте значения столбцов DECIMAL расценены как значения с плавающей запятой.

mysql> SELECT CAST(1 AS UNSIGNED) - 2.0;
    -> -1.0

Режим SQL затрагивает результат конверсионных операций (см. раздел 6.1.8). Например:

Следующий список описывает доступные функции конвертации:

13.11. Функции XML

Таблица 13.15. Функции XML

ИмяОписание
ExtractValue()Извлекает значение из строки XML, используя нотацию XPath
UpdateXML() Возвратит замененный фрагмент XML

Этот раздел обсуждает XML и связанную функциональность в MySQL.

Возможно получить XML-отформатированный вывод из MySQL в клиентах mysql и mysqldump, вызывая их с опцией --xml .

Две функции, обеспечивающие основные возможности XPath 1.0 (XML Path Language, version 1.0) доступны. Некоторая основная информация о синтаксисе XPath и использовании обеспечена позже в этом разделе, однако, всестороннее обсуждение этих тем находится вне контекста этого Руководства, и Вы должны изучить XML Path Language (XPath) 1.0 standard для получения нужной информации. Полезный ресурс для плохо знакомых с XPath или кто желает получить базовые знания: Zvon.org XPath Tutorial, который доступен на нескольких языках.

Эти функции остаются разрабатываемыми. Мы продолжаем улучшать эти и другие аспекты XML и функциональности XPath в MySQL 8.0. Вы можете обсудить их, задать вопросы о них и получить справку от других пользователей на MySQL XML User Forum.

Выражения XPath, используемые с этими функциями, поддерживают пользовательские переменные и местные сохраненные переменные программы. Пользовательские переменные слабо проверены, локальные переменные сохраненных программ проверены хорошо (см. также Bug #26518):

Выражения, содержащие пользовательские переменные или переменные, локальные к сохраненным программам, должны (за исключением нотации) соответствовать правилам для выражений XPath, содержащих переменные, как дано в спецификации XPath 1.0.

Пользовательская переменная, используемая, чтобы сохранить выражение XPath, обработана как пустая строка. Из-за этого не возможно сохранить выражение XPath как пользовательскую переменную (Bug #32911).

Обсуждение подробно синтаксиса XPath и его использования вне контекста этого руководства. Пожалуйста, см. XML Path Language (XPath) 1.0 specification.

Описания и примеры некоторых основных выражений XPath:

XPath Limitations. Синтаксис XPath, поддержанный этими функциями, в настоящее время подвергается следующим ограничениям:

Выражения XPath, переданные как параметры в ExtractValue() и UpdateXML(), могут содержать символ двоеточия (:) в селекторах элемента, который включает их с разметкой, использующей нотацию пространств имен XML. Например:

mysql> SET @xml = '<a>111<b:c>222<d>333</d><e:f>444</e:f></b:c></a>';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT ExtractValue(@xml, '//e:f');
+-----------------------------+
| ExtractValue(@xml, '//e:f') |
+-----------------------------+
| 444                         |
+-----------------------------+
1 row in set (0.00 sec)

mysql> SELECT UpdateXML(@xml, '//b:c', '<g:h>555</g:h>');
+--------------------------------------------+
| UpdateXML(@xml, '//b:c', '<g:h>555</g:h>') |
+--------------------------------------------+
| <a>111<g:h>555</g:h></a>   |
+--------------------------------------------+
1 row in set (0.00 sec)

Это подобно в некотором отношении тому, что разрешено Apache Xalan и и некоторыми другими анализаторами, и намного проще, чем требование деклараций пространства имен или использования функций namespace-uri() и local-name().

Обработка ошибок. Для ExtractValue() и UpdateXML() используемый локатор XPath должен быть допустимым, и XML, который будет искаться, должен состоять из элементов, которые должным образом вложены и закрыты. Если локатор недопустим, ошибка произведена:

mysql> SELECT ExtractValue('<a>c</a><b/>', '/&a');
ERROR 1105 (HY000): XPATH syntax error: '&a'

Если xml_frag не состоит из элементов, которые должным образом вложены и закрыты, NULL возвращен и предупреждение произведено, как показано в этом примере:

mysql> SELECT ExtractValue('<a>c</a><b', '//a');
+-----------------------------------+
| ExtractValue('<a>c</a><b', '//a') |
+-----------------------------------+
| NULL                              |
+-----------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1525
Message: Incorrect XML value: 'parse error at line 1 pos 11:
   END-OF-INPUT unexpected ('>' wanted)'
1 row in set (0.00 sec)

mysql> SELECT ExtractValue('<a>c</a><b/>', '//a');
+-------------------------------------+
| ExtractValue('<a>c</a><b/>', '//a') |
+-------------------------------------+
| c                                   |
+-------------------------------------+
1 row in set (0.00 sec)

Заменяющий XML, используемый в качестве третьего параметра UpdateXML() не проверен, чтобы определить, состоит ли это исключительно из элементов, которые должным образом вложены и закрыты.

Инъекция XPath. Инъекция кода происходит, когда вредоносный код введен в систему, чтобы получить несанкционированный доступ к привилегиям и данным. Это основано на эксплуатации предположений, сделанных разработчиками о типе и контенте ввода данных от пользователей. XPath не исключение в этом отношении.

Общий сценарий, в котором это может произойти: приложение обрабатывает авторизацию на основе комбинации имени для входа в систему и пароля, которые берутся из файла XML, используя выражение XPath наподобие:

//user[login/text()='neapolitan' and password/text()='1c3cr34m']/attribute::id

Это XPath-эквивалент SQL-запроса:

SELECT id FROM users WHERE login='neapolitan' AND password='1c3cr34m';

Приложение PHP, использующее XPath, могло бы обработать процесс входа в систему так:

<?php
  $file =   "users.xml";
  $login=   $POST["login"];
  $password =   $POST["password"];
  $xpath = "//user[login/text()=$login and password/text()=$password]/attribute::id";

  if (file_exists($file)) {
     $xml = simplexml_load_file($file);
     if ($result = $xml->xpath($xpath))
        echo "You are now logged in as user $result[0].";
     else echo "Invalid login name or password.";
  }
  else exit("Failed to open $file.");
?>

Никакие проверки не выполнены на вводе. Это означает, что пользователь может ввести ' or 1=1 для имени для входа в систему и для пароля, в итоге $xpath будет оценен как показано здесь:

//user[login/text()='' or 1=1 and password/text()='' or 1=1]/attribute::id

Так как выражение в квадратных скобках всегда оценивается как true, это эффективно то же самое, как будто признак id каждого элемента user соответствет в XML-документе:

//user/attribute::id

Один путь, которым можно обойти это особое нападение: просто заключить имена переменной в кавычки, которые будут интерполированы в определении $xpath, принудительно конвертируя значение из Web-формы в строку:

$xpath = "//user[login/text()='$login' and password/text()='$password']/attribute::id";

Это та же самая стратегия, которая часто рекомендуется для того, чтобы предотвратить атаки с использованием кода SQL. Вообще, методы, которым Вы должны следовать для того, чтобы предотвратить нападения инъекции XPath, являются теми же самыми, что касаются предотвращения инъекции SQL:

Так же, как атаки с использованием кода на SQL могут использоваться, чтобы получить информацию о схемах базы данных, так может использоваться и инъекция XPath: Blind XPath Injection (PDF file, 46KB).

Также важно проверить вывод, отсылаемый назад к клиенту. Рассмотрите то, что может произойти, когда мы используем MySQL ExtractValue():

mysql> SELECT ExtractValue(LOAD_FILE('users.xml'),
    -> '//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'
    -> ) AS id;
+-------------------------------+
| id                            |
+-------------------------------+
| 00327 13579 02403 42354 28570 |
+-------------------------------+
1 row in set (0.01 sec)

Поскольку ExtractValue() возвращает многократные соответствия как разграниченную одинарным интервалом строку, это нападение инъекции обеспечивает передачу всех допустимых ID в пределах users.xml пользователю как единственную строка вывода. Как дополнительная гарантия, Вы должны также проверить вывод прежде, чем возвратить это пользователю. Вот простой пример:

mysql> SELECT @id = ExtractValue(
    -> LOAD_FILE('users.xml'),
    -> '//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT IF (
    -> INSTR(@id, ' ') = 0, @id,
    -> 'Unable to retrieve user ID') AS singleID;
+----------------------------+
| singleID                   |
+----------------------------+
| Unable to retrieve user ID |
+----------------------------+
1 row in set (0.00 sec)

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

13.12. Битовые функции и операторы

Таблица 13.16. Битовые функции и операторы

ИмяОписание
BIT_COUNT()Возвратить число битов, которые установлены
& Битовое AND
~ Битовая инверсия
| Битовое OR
^ Битовое XOR
<< Сдвиг влево
>> Сдвиг вправо

Разрядные функции и операторы включают BIT_COUNT(), BIT_AND(), BIT_OR(), BIT_XOR(), &, |, ^, ~, << и >>. BIT_AND(), BIT_OR() и BIT_XOR() это совокупные функции, описанные в разделе 13.19.1. До MySQL 8.0 разрядные функции и операторы требовали параметры BIGINT (64-bit integer) и возвращали значения BIGINT . Не-BIGINT параметры были преобразованы в BIGINT до выполнения работы, и усечение могло произойти.

В MySQL 8.0 разрядные функции и операторы разрешают двоичные строковые параметры типа BINARY, VARBINARY и BLOB и возвращают значение подобного типа, что позволяет им взять параметры и произвести возвращаемые значения больше, чем 64 бита.

Значение этого изменения в поведении: битовые операции на двоичных параметрах могли бы привести к различному результату в MySQL 8.0 и 5.7. Для получения дополнительной информации об изменении, включая то, как подготовиться в MySQL 5.7 для потенциальных несовместимостей между MySQL 5.7 и 8.0 см. Bit Functions and Operators в MySQL 5.7 Reference Manual.

Следующий список описывает доступные разрядные функции и операторы:

13.13. Функции шифрования и сжатия

Таблица 13.17. Функции шифрования и сжатия

ИмяОписание
AES_DECRYPT()Дешифрует с использованием AES
AES_ENCRYPT()Шифрует с использованием AES
COMPRESS() Возвращает результат как двоичную строку
DECODE() Декодирует строку из ENCODE()
DES_DECRYPT()Дешифрует строку
DES_ENCRYPT()Шифрует строку
ENCODE() Шифрует строку
ENCRYPT() Шифрует строку
MD5() Вычисляет хэш MD5
PASSWORD() Вычислит и возвратит строку пароля
RANDOM_BYTES()Возвратит случайный вектор байта
SHA1(), SHA()SHA-1 160-bit хэш
SHA2() Хэш SHA-2
UNCOMPRESS()Распаковывает сжатую строку
UNCOMPRESSED_LENGTH()Возвратит длину строки перед сжатием
VALIDATE_PASSWORD_STRENGTH()Определяет силу пароля

Многие функции шифрования и сжатия возвращают строки в которых результат мог бы содержать произвольные значения байта. Если Вы хотите сохранить эти результаты, используйте столбец с типом двоичной строки VARBINARY или BLOB. Это позволит избежать потенциальных проблем с удалением конечного пробела или преобразованием набора символов, которое изменило бы значения данных, которые могут произойти, если Вы используете недвоичной строковый тип данных (CHAR, VARCHAR или TEXT).

Некоторое функции шифрования возвращают строки символов ASCII: MD5(), PASSWORD(), SHA(), SHA1(), SHA2(). Их возвращаемое значение - недвоичная строка, у которой есть набор символов и сопоставление, определенные системными переменными character_set_connection и collation_connection.

Для ситуаций, в которых функции, подобные MD5() или SHA1(), вернут строку шестнадцатеричных цифр как двоичную, возвращаемое значение не может быть преобразовано в верхний регистр или сравнено нечувствительным к регистру способом. Вы должны преобразовать значение в недвоичную строку. См. обсуждение двоичного строкового преобразования в разделе 13.10.

Если приложение хранит значения функции MD5() или SHA1(), которые возвращают строку шестнадцатеричных цифр, более эффективное хранение и сравнения могут быть получены, преобразовывая шестнадцатеричное представление в двоичное, используя UNHEX() и сохраняя результат в столбце BINARY(N). Каждая пара шестнадцатеричных цифр требует одного байта в двоичной форме, таким образом, значение N зависит от длины строки. N 16 для MD5() и 20 для SHA1(). Для SHA2() N от 28 до 32в зависимости от параметра, определяющего желаемую длину результата в битах.

Накладные расходы для хранения шестнадцатеричных строк в столбце CHAR от 2 до 8 раз, если значение сохранено в столбце, который использует набор символов utf8 (где каждый символ использует 4 байта). Хранение строки также приводит к более медленным сравнениям из-за больших значений и потребности принять правила сопоставления набора символов во внимание.

Предположите, что приложение хранит значение MD5() в столбце CHAR(32):

CREATE TABLE md5_tbl (md5_val CHAR(32), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(MD5('abcdef'), ...);

Чтобы преобразовать строки в более компактную форму, измените приложение, чтобы использовать UNHEX() и BINARY(16):

CREATE TABLE md5_tbl (md5_val BINARY(16), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(UNHEX(MD5('abcdef')), ...);

Приложения должны быть подготовлены обработать очень редкий случай, когда хеширующая функция производит то же самое значение для двух различных входных значений. Один способ сделать обнаруживаемые столкновения состоит в том, чтобы сделать столбец хеша первичным ключом.

Пароли или другие чувствительные значения, поставляемые как параметры функциям шифрования, посылают открытым текстом серверу MySQL, если соединение SSL не используется. Кроме того, такие значения появятся в любых журналах MySQL. Чтобы избежать этих типов проблем, приложения могут зашифровать чувствительные значения на стороне клиента прежде, чем послать их серверу. Те же самые соображения относятся к ключам шифрования. Чтобы избежать выставлять их, приложения могут использовать хранимые процедуры, чтобы зашифровать и дешифровать значения на стороне сервера.

13.14. Информационные функции

Таблица 13.18. Информационные функции

ИмяОписание
BENCHMARK()Неоднократно выполняет выражение
CHARSET() Набор символов параметра
COERCIBILITY()Сопоставление значения строкового параметра
COLLATION() Сопоставление значения строкового параметра
CONNECTION_ID()ID соединения (ID потока)
CURRENT_ROLE()Текущяя активная роль
CURRENT_USER(), CURRENT_USER Имя пользователя и имя хоста
DATABASE() Имя базы данных по умолчанию
FOUND_ROWS()Для SELECT с предложением LIMIT число строк, которые были бы возвращены, если бы там не было LIMIT
LAST_INSERT_ID()Значение столбца AUTOINCREMENT для последнего INSERT
ROLES_GRAPHML()Возвращает документ GraphML, представляющий ролевые подграфы памяти
ROW_COUNT() Сколько строк обновлено
SCHEMA() Синоним для DATABASE()
SESSION_USER()Синоним для USER()
SYSTEM_USER()Синоним для USER()
USER() Имя пользователя и имя хоста клиента
VERSION() Строка версии сервера MySQL

13.15. Пространственные аналитические функции

MySQL обеспечивает функции, чтобы выполнить различные операции на пространственных данных. Эти функции могут быть сгруппированы в несколько главных категорий согласно типу работы, которую они выполняют:

Для общего обзора о поддержке MySQL использования пространственных данных см. раздел 12.5.

13.15.1. Обзор пространственных функций

Следующая таблица приводит каждую пространственную функцию и обеспечивает краткое описание каждой.

Таблица 13.19. Пространственные функции

ИмяОписание
GeometryCollection() Создает набор геометрии из конфигураций
LineString()Создает LineString из значений Point
MBRContains()Содержит ли MBR одной геометрии MBR другой
MBRCoveredBy()Покрыт ли один MBR другим
MBRCovers() Покрывает ли один MBR другого
MBRDisjoint()Являются ли MBR двух конфигураций несвязными
MBREquals() Равны ли MBR двух конфигураций
MBRIntersects()Пересекаются ли MBR двух конфигураций
MBROverlaps()Есть ли перекрытие у двух MBR
MBRTouches()Есть ли касание у двух MBR
MBRWithin() Находится ли MBR одной геометрии в пределах MBR другой
MultiLineString()Собирает MultiLineString из LineString
MultiPoint()Собирает MultiPoint из Point
MultiPolygon()Собирает MultiPolygon из Polygon
Point() Собирает Point из координат
Polygon() Собирает Polygon из LineString
ST_Area() Вернет область Polygon или MultiPolygon
ST_AsBinary(), ST_AsWKB() Переходит от внутренней геометрии к WKB
ST_AsGeoJSON()Генерирует объект GeoJSON
ST_AsText() , ST_AsWKT()Переходит от внутренней геометрии к WKT
ST_Buffer() Возвратит геометрию точек в пределах данного расстояния от геометрии
ST_Buffer_Strategy()Произведет опцию стратегии для ST_Buffer()
ST_Centroid()Вернет центр как точку
ST_Contains()Содержит ли одна геометрия другую
ST_ConvexHull()Возвратит выпуклый корпус геометрии
ST_Crosses()Пересекает ли одна геометрия другую
ST_Difference()Возвратит различие в наборе точек двух конфигураций
ST_Dimension()Измерение геометрии
ST_Disjoint()Является ли одна геометрия несвязной с другой
ST_Distance()Расстояние одной геометрии от другой
ST_Distance_Sphere()Минимальное расстояние на земле между двумя конфигурациями
ST_EndPoint()Конечный Point LineString
ST_Envelope()MBR геометрии
ST_Equals() Равна ли одна геометрия другой
ST_ExteriorRing()Возвратит внешнее кольцо Polygon
ST_GeoHash()Произведит значение geohash
ST_GeomCollFromText(), ST_GeometryCollectionFromText(), ST_GeomCollFromTxt()Набор геометрии из WKT
ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB() Набор геометрии из WKB
ST_GeometryN()Возвратит N-ую геометрию из набора геометрий
ST_GeometryType()Возвратит название типа геометрии
ST_GeomFromGeoJSON()Произведет геометрию из объекта GeoJSON
ST_GeomFromText(), ST_GeometryFromText() Набор геометрии из WKT
ST_GeomFromWKB(), ST_GeometryFromWKB() Набор геометрии из WKB
ST_InteriorRingN()Вернет N-ое внутреннее кольцо Polygon
ST_Intersection() Пересечение набора точек двух конфигураций
ST_Intersects()Пересекает ли одна геометрия другую
ST_IsClosed()Закрыта ли геометрия и проста
ST_IsEmpty()Функция заполнителя
ST_IsSimple()Проста ли геометрия
ST_IsValid()Допустима ли геометрия
ST_LatFromGeoHash()Возвратит широту из значения geohash
ST_Length() Возвратит длину LineString
ST_LineFromText(), ST_LineStringFromText() Собирает LineString из WKT
ST_LineFromWKB(), ST_LineStringFromWKB() Собирает LineString из WKB
ST_LongFromGeoHash()Возвратит долготу из значения geohash
ST_MakeEnvelope()Прямоугольник вокруг двух точек
ST_MLineFromText(), ST_MultiLineStringFromText() Собирает MultiLineString из WKT
ST_MLineFromWKB(), ST_MultiLineStringFromWKB() Собирает MultiLineString из WKB
ST_MPointFromText(), ST_MultiPointFromText() Собирает MultiPoint из WKT
ST_MPointFromWKB(), ST_MultiPointFromWKB() Собирает MultiPoint из WKB
ST_MPolyFromText(), ST_MultiPolygonFromText() Собирает MultiPolygon из WKT
ST_MPolyFromWKB(), ST_MultiPolygonFromWKB() Собирает MultiPolygon из WKB
ST_NumGeometries()Число конфигураций в наборе геометрии
ST_NumInteriorRing(), ST_NumInteriorRings() Число углов в Polygon
ST_NumPoints()Число точек в LineString
ST_Overlaps()Перекрывает ли одна геометрия другую
ST_PointFromGeoHash() Конвертирует geohash в POINT
ST_PointFromText()Собирает Point из WKT
ST_PointFromWKB()Собирает Point из WKB
ST_PointN() Возвратит N-ую точку LineString
ST_PolyFromText(), ST_PolygonFromText() Собирает Polygon из WKT
ST_PolyFromWKB(), ST_PolygonFromWKB() Собирает Polygon из WKB
ST_Simplify()Возвратит упрощенную геометрию
ST_SRID() Возвратит пространственный ссылочный системный ID для геометрии
ST_StartPoint()Стартовая Point LineString
ST_SymDifference()Возвратит набор точек симметрического различия двух конфигураций
ST_Touches()Касается ли одна геометрия другой
ST_Union() Возвратит набор общих точек двух конфигураций
ST_Validate()Возвратит утвержденную геометрию
ST_Within() Является ли одна геометрия в пределах другой
ST_X() Координата X Point
ST_Y() Координата Y Point

13.15.2. Обработка параметров пространственными функциями

Пространственные значения, или конфигурации, имеют свойства, описанные в разделе 12.5.2.2. Следующее обсуждение рассматривает общие пространственные функциональные характеристики параметров. У определенных функций или групп функций могут быть дополнительные характеристики, как обсуждается в разделах, где те функции описаны.

Пространственные функции определены только для допустимых значений геометрии. Если недопустимую геометрию передают к пространственной функции, результат неопределен.

Spatial Reference Identifier (SRID) идентифицирует координатное пространство, в котором определена геометрия. В MySQL значение SRID целое число, связанное со значением геометрии. Однако, все вычисления сделаны, принимая SRID 0, представляя декартовские (плоские) координаты, независимо от фактического значения SRID. В будущем вычисления могут использовать указанные значения SRID. Чтобы гарантировать поведение для SRID 0, создавайте конфигурации, используя SRID 0. SRID 0 является значением по умолчанию для новых конфигураций, если никакой SRID не определен.

Максимальное применимое значение SRID 232-1. Если большее значение дано, используются только первые 32 бита.

Значения геометрии, произведенные любой пространственной функцией, наследуют SRID параметров геометрии.

Пространственные функции, которые берут много параметров геометрии, требуют, чтобы у тех параметров было то же самое значение SRID. Предполагая, что SRIDs равны, пространственные функции ничего не делают с ними после выполнения проверки равенства, значения геометрии неявно обработаны, используя декартовские координаты. Если пространственная функция возвращает ER_GIS_DIFFERENT_SRIDS , это означает, что у параметров геометрии не было того же самого SRID. Вы должны изменить их, чтобы иметь тот же самый SRID.

Пространственные функции возвращают ошибку ER_GIS_INVALID_DATA , если передан недопустимый параметр геометрии.

Open Geospatial Consortium требует, чтобы вводные многоугольники уже были закрытыми, таким образом, открытые многоугольники отклонены как недопустимые вместо того, чтобы закрыть.

Пустая обработка набора геометрии следующяя: пустой входной набор геометрии WKT может быть определен как 'GEOMETRYCOLLECTION()'. Это также вывод WKT, следующий из пространственной работы, которая производит пустой набор геометрии.

Во время парсинга вложенного набора геометрии набор обработан, и его основные компоненты используются в различных операциях GIS, чтобы вычислить результаты. Это предоставляет дополнительную гибкость пользователям, потому что не нужно касаться уникальности данных о геометрии. Вложенные наборы геометрии могут быть произведены из вложенных вызовов функции GIS.

13.15.3. Функции, которые создают значения геометрии из значений WKT

Эти функции берут в качестве параметров представление Well-Known Text (WKT) и, произвольно, SRID. Они возвращают соответствующую геометрию.

ST_GeomFromText() принимает значение WKT любого типа геометрии как первый параметр. Другие функции обеспечивают определенные для типа функции конструкции для значений геометрии каждого типа геометрии.

Функции, которые принимают параметры набора геометрии WKT, понимают оба синтаксиса: стандартный OpenGIS 'GEOMETRYCOLLECTION EMPTY' и нестандартный MySQL 'GEOMETRYCOLLECTION()'. Функции, которые производят значения WKT, производят стандартный синтаксис 'GEOMETRYCOLLECTION EMPTY':

mysql> SET @s1 = ST_GeomFromText('GEOMETRYCOLLECTION()');
mysql> SET @s2 = ST_GeomFromText('GEOMETRYCOLLECTION EMPTY');
mysql> SELECT ST_AsWKT(@s1), ST_AsWKT(@s2);
+--------------------------+--------------------------+
| ST_AsWKT(@s1)            | ST_AsWKT(@s2)            |
+--------------------------+--------------------------+
| GEOMETRYCOLLECTION EMPTY | GEOMETRYCOLLECTION EMPTY |
+--------------------------+--------------------------+

Для описания формата WKT см. раздел 12.5.3.1.1.

13.15.4. Функции, которые создают значения геометрии из значений WKB

Эти функции берут в качестве параметров BLOB, содержащий представление Well-Known Binary (WKB) и, произвольно, пространственный ссылочный системный идентификатор (SRID). Они возвращают соответствующую геометрию.

Эти функции также принимают объекты геометрии для совместимости с возвращаемым значением функций в разделе 13.15.5. Таким образом, те функции могут использоваться, чтобы обеспечить первый параметр функциям в этом разделе.

ST_GeomFromWKB() принимает значение WKB любого типа геометрии как первый параметр. Другие функции обеспечивают определенные для типа функции для конструкции значений геометрии каждого типа.

13.15.5. Функции MySQL, которые создают значения геометрии

MySQL обеспечивает ряд полезных нестандартных функций для того, чтобы создать значения геометрии. Функции, описанные в этом разделе, являются расширениями MySQL к спецификации OpenGIS.

Эти функции производят объекты геометрии или из значений WKB или из объектов геометрии как параметры. Если какой-либо параметр не надлежащий WKB или представление геометрии надлежащего типа объекта, возвращаемое значение NULL.

Например, Вы можете вставить возвращаемое значение геометрии из Point() непосредственно в столбец POINT:

INSERT INTO t1 (pt_col) VALUES(Point(1,2));

13.15.6. Конверсионные функции формата геометрии

MySQL поддерживает функции, перечисленные в этом разделе для того, чтобы преобразовать значения геометрии из внутреннего формата геометрии в формат WKB или WKT.

Кроме того, есть функции, чтобы преобразовать строку из WKT или WKB к внутреннему формату геометрии. См. разделы 13.15.3 и 13.15.4.

Функции, которые принимают параметры набора геометрии WKT, понимают оба синтаксиса: OpenGIS 'GEOMETRYCOLLECTION EMPTY' и MySQL 'GEOMETRYCOLLECTION()'. Функции, которые производят значения WKT, производят стандартный синтаксис 'GEOMETRYCOLLECTION EMPTY':

mysql> SET @s1 = ST_GeomFromText('GEOMETRYCOLLECTION()');
mysql> SET @s2 = ST_GeomFromText('GEOMETRYCOLLECTION EMPTY');
mysql> SELECT ST_AsWKT(@s1), ST_AsWKT(@s2);
+--------------------------+--------------------------+
| ST_AsWKT(@s1)            | ST_AsWKT(@s2)            |
+--------------------------+--------------------------+
| GEOMETRYCOLLECTION EMPTY | GEOMETRYCOLLECTION EMPTY |
+--------------------------+--------------------------+

13.15.7. Функции свойства геометрии

Каждая функция, которая принадлежит этой группе, берет значение геометрии в качестве своего параметра и возвращает некоторое количественное или качественное свойство геометрии. Некоторые функции ограничивают свой тип параметра. Такие функции возвращают NULL, если параметр имеет неправильный тип геометрии. Например, ST_Area() вернет NULL, если тип объекта не Polygon или MultiPolygon.

13.15.7.1. Общие функции свойства геометрии

Функции, перечисленные в этом разделе, не ограничивают свой параметр и принимают значение геометрии любого типа.

13.15.7.2. Функции и свойства точки

Point состоит из координат X и Y, которые могут быть получены, используя функции ST_X() и ST_Y(), соответственно. Эти функции также разрешают дополнительный второй параметр, который определяет X или значение координаты Y, когда функциональный результат Point является объектом от первого параметра с соответствующей измененной координатой, чтобы быть равным второму параметру.

13.15.7.3. Функции и свойства LineString и MultiLineString

LineString состоит из значений Point. Вы можете извлечь особые точки LineString, посчитайте число точек, которое это содержит, или получить его длину.

Некоторые функции в этом разделе также работают на значениях MultiLineString.

13.15.7.4. Функции и свойства Polygon и MultiPolygon

Эти функции возвращают свойства значения Polygon или MultiPolygon.

13.15.7.5. Функции и свойства GeometryCollection

Эти функции возвращают свойства значения GeometryCollection.

13.15.8. Пространственные функции и операторы

OpenGIS предлагает много функций, которые могут произвести конфигурации. Они разработаны, чтобы осуществить пространственные операторы.

Эти функции поддерживают все комбинации типа параметра кроме тех, которые являются неподходящими согласно спецификации Open Geospatial Consortium.

Кроме того, раздел 13.15.7 обсуждает несколько функций, которые создают новые конфигурации из существующих.

13.15.9. Функции, которые проверяют пространственные отношения между объектами геометрии

Функции, описанные в этом разделе, берут две конфигурации в качестве параметров и возвращают качественное или количественное отношение между ними.

MySQL осуществляет два набора функций, используя имена функций, определенные спецификацией OpenGIS. Один набор проверяет отношения между двумя значениями геометрии, используя точные формы объекта, другой использует минимальный ограничительный прямоугольник объекта.

Есть также MySQL-специфичный набор функций, доступных, чтобы проверить отношения между двумя значениями геометрии.

13.15.9.1. Пространственные функции с использованием формы объекта

Спецификация OpenGIS определяет следующие функции. Они проверяют отношения между двумя значениями геометрии g1 и g2, с использованием точных форм объекта. Возвращаемые значения 1 и 0 указывают на истину и ложь, соответственно, за исключением ST_Distance(), который возвращает значения расстояния.

Эти функции поддерживают все комбинации типа параметра кроме тех, которые являются неподходящими согласно Open Geospatial Consortium. Они возвращают ложнь, если вызваны с неподходящей комбинацией типов параметров геометрии. Например, ST_Overlaps() возвращает ложь, если вызвана с конфигурациями различных измерений.

13.15.9.2. MySQL-специфичные пространственные функции, использующие ограничивающие прямоугольники минимума

MySQL обеспечивает несколько функций, которые проверяют отношения между минимальными ограничительными прямоугольниками двух конфигураций g1 и g2. Возвращаемые значения 1 и 0 указывают на истину и ложь, соответственно.

13.15.10. Пространственные функции Geohash

Geohash система для того, чтобы закодировать широту и долготу произвольной точности в текстовую строку. Значения Geohash строки, которые содержат только символы, выбранные из "0123456789bcdefghjkmnpqrstuvwxyz".

Функции в этом разделе включают манипуляции значениями geohash, которые обеспечивают приложения способностями импорта и экспорта geohash-данных, индексации и поиска geohash-значений.

13.15.11. Пространственные функции GeoJSON

Этот раздел описывает функции для того, чтобы преобразовать между документами GeoJSON и пространственными значениями. GeoJSON открытый стандарт для того, чтобы закодировать геометрические/географические особенности. Для получения дополнительной информации см. http://geojson.org. Функции, обсужденные здесь, следуют спецификации GeoJSON revision 1.0.

GeoJSON поддерживает те же самые геометрические/географические типы данных, что и MySQL. Объекты Feature и FeatureCollection не поддержаны, за исключением того, что объекты геометрии извлечены из них. Поддержка CRS ограничена значениями, которые идентифицируют SRID.

MySQL также поддерживает тип данных JSON и ряд SQL функций для работы с ним. См. разделы 12.6 и 13.16.

13.15.12. Вспомогательные пространственные функции

Функции в этом разделе обеспечивают вспомогательные операции на значениях геометрии.

13.16. Функции JSON

Функции, описанные в этом разделе, выполняют операции на значениях JSON. Для обсуждения типа данных JSON и дополнительных примеров, показывающих, как использовать эти функции, см. раздел 12.6.

Для функций, которые берут параметр JSON, происходит ошибка, если параметр не допустимое значение JSON.

Ряд пространственных функций для того, чтобы воздействовать на значения GeoJSON также доступен. См. раздел 13.15.11.

13.16.1. Функции JSON (обзор)

Таблица 13.20. Функции JSON

ИмяОписание
JSON_ARRAY()Создает массив JSON
JSON_ARRAY_APPEND()Добавляет данные в документ JSON
JSON_ARRAY_INSERT()Вставляет в массив JSON
->Возвращаемое значение столбца JSON после оценки пути, эквивалент JSON_EXTRACT().
JSON_CONTAINS()Содержит ли документ JSON указанный объект
JSON_CONTAINS_PATH()Содержит ли документ JSON какие-либо данные в пути
JSON_DEPTH()Максимальная глубина документа JSON
JSON_EXTRACT()Данные из документа JSON
->>Возвращаемое значение столбца JSON после оценки пути и закрытия кавычки результат, эквивалент JSON_UNQUOTE(JSON_EXTRACT())
JSON_INSERT()Вставляет данные в документ JSON
JSON_KEYS() Массив ключей из документа JSON
JSON_LENGTH()Число элементов в документе
JSON_MERGE()Объединение документов JSON
JSON_OBJECT()Создать объект JSON
JSON_QUOTE()Цитировать документ JSON
JSON_REMOVE()Удалить данные из документа JSON
JSON_REPLACE()Заменить значения в документе JSON
JSON_SEARCH()Путь в пределах документа JSON
JSON_SET() Вставить данные в документ JSON
JSON_TYPE() Тип значения JSON
JSON_UNQUOTE()Отменить цитирование значения JSON
JSON_VALID()Допустимо ли значение JSON

MySQL 8.0.1 и более поздний поддерживает две совокупных функции JSON JSON_ARRAYAGG() и JSON_OBJECTAGG() . См. раздел 13.19 для их описания.

13.16.2. Функции, которые создают значения JSON

Функции в этом разделе составляют значения JSON из составляющих элементов.

Вы можете также получить значения JSON, конвертируя значения других типов в JSON с помощью CAST(value AS JSON).

13.16.3. Функции поиска значений JSON

Функции в этом разделе выполняют операции поиска на значениях JSON, чтобы извлечь данные из них, сообщить, существуют ли данные в их пределах или сообщить о пути к данным в их пределах.

13.16.4. Функции, которые изменяют значения JSON

Функции в этом разделе изменяют значения JSON и возвращают результат.

13.16.5. Функции, возвращающие атрибуты значений JSON

Функции в этом разделе возвращают признаки значений JSON.

13.16.6. Синтаксис JSON Path

Многие из функций, описанных в предыдущих разделах, требуют выражения пути, чтобы идентифицировать определенный элемент в документе JSON. Путь состоит из контекста пути, сопровождаемого одной или более метками пути. Для путей, используемых в MySQL-функциях JSON, контекст всегда документ, который обрабатывается, представленный лидирующим символом $. Метки пути отделены символами точки (.). Элементы в массивах представлены [N], здесь N неотрицательное целое число. Названия ключей должны быть заключены в двойные кавычки строки или являться допустимыми идентификаторами ECMAScript (см. http://www.ecma-international.org/ecma-262/5.1/#sec-7.6). Выражения пути, как текст JSON, должны быть закодированы, используя наборы символов ascii, utf8 или utf8mb4. Другие кодировки символов неявно приводятся к utf8mb4. Полный синтаксис выглядит так:

pathExpression:
scope[(pathLeg)*]
pathLeg:
member | arrayLocation | doubleAsterisk
member:
period ( keyName | asterisk )
arrayLocation:
leftBracket ( nonNegativeInteger | asterisk ) rightBracket
keyName:
ESIdentifier | doubleQuotedString
doubleAsterisk: '**'
period: '.'
asterisk: '*'
leftBracket: '['
rightBracket: ']'

Как отмечено ранее, в MySQL, контекст пути всегда обрабатываемый документ, представленный как $. Вы можете использовать '$' как синоним для документа в выражениях пути JSON.

Некоторые реализации поддерживают ссылки столбца для контекстов путей JSON, в настоящее время, MySQL не поддерживает их.

Подстановочные знаки * и ** используются следующим образом:

Для примеров синтаксиса пути см. описания различных функций JSON, которые берут пути в качестве параметров, например, JSON_CONTAINS_PATH() и JSON_REPLACE() . Для примеров, которые включают использование * и ** см. описание функции JSON_SEARCH().

13.17. Функции, используемые с глобальными транзакционными ID

Функции, описанные в этом разделе, используются с GTID-репликацией. Важно иметь в виду, что все эти функции берут строковые представления наборов GTID как параметры, наборы GTID должны всегда заключаться в кавычки, когда используются с ними.

Союз двух наборов GTID просто их представления как строки, объединенные запятой. Другими словами, Вы можете определить очень простую функцию для того, чтобы получить союз двух наборов GTID, подобных создаваемому здесь:

CREATE FUNCTION GTID_UNION(g1 TEXT, g2 TEXT)
RETURNS TEXT DETERMINISTIC
RETURN CONCAT(g1,',',g2);

Таблица 13.22. Функции GTID

ИмяОписание
GTID_SUBSET()Возвратит истину, если все GTID в подмножестве установлены, иначе ложь
GTID_SUBTRACT()Возвратит все GTID в наборе, которые не находятся в подмножестве
WAIT_FOR_EXECUTED_GTID_SET() Ждать, пока данные GTID не выполнятся на ведомом устройстве
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() Ждать, пока данные GTID не выполнятся на ведомом устройстве

13.18. Прочие функции

Таблица 13.23. Прочие функции

ИмяОписание
ANY_VALUE()Подавить отклонение значения ONLY_FULL_GROUP_BY
BIN_TO_UUID()Конвертирует двоичный UUID в строку
DEFAULT() Значение по умолчанию для столбца таблицы
GET_LOCK() Получить названную блокировку
INET_ATON() Числовое значение IP-адреса
INET_NTOA() IP-адрес из числового значения
INET6_ATON()Числовое значение IPv6-адреса
INET6_NTOA()IPv6-адрес из числового значения
IS_FREE_LOCK()Свободна ли названная блокировка
IS_IPV4() Является ли параметр адресом IPv4
IS_IPV4_COMPAT()Является ли параметр IPv4-совместимым адресом
IS_IPV4_MAPPED()Является ли параметр IPv4-отображенным адресом
IS_IPV6() Является ли параметр адресом IPv6
IS_USED_LOCK()Используется ли названная блокировка, возвратит идентификатор соединения, если да
IS_UUID() Является ли параметр допустимым UUID
MASTER_POS_WAIT()Блокировка, пока ведомое устройство считает и применит все обновления до указанной позиции
NAME_CONST()Присваивает имя столбцу
RAND() Возвратит случайное значение с плавающей запятой
RELEASE_ALL_LOCKS() Освобождает все текущие именованные блокировки
RELEASE_LOCK()Освобождает именованную блокировку
SLEEP() Сон в течение указанного числа секунд
UUID() Universal Unique Identifier (UUID)
UUID_SHORT()Числовое значение UUID
UUID_TO_BIN()Конвертирует UUID в двоичную строку
VALUES() Определяет значения, которые будут использоваться в INSERT

13.19. Агрегатные функции (GROUP BY)

13.19.1. Обзор агрегатных функций (GROUP BY)

Таблица 13.24. Агрегатные функции (GROUP BY)

ИмяОписание
AVG() Среднее значение
BIT_AND() Битовое AND
BIT_OR() Битовое OR
BIT_XOR() Битовое XOR
COUNT() Число строк
COUNT(DISTINCT)Число различных значений
GROUP_CONCAT()Конкатенация строк
JSON_ARRAYAGG()Возвратит набор результатов как единственный массив JSON
JSON_OBJECTAGG()Возвратит набор результатов как единственный объект JSON
MAX() Максимальное значение
MIN() Минимальное значение
STD() Возвратит стандартное отклонение
STDDEV() Возвратит стандартное отклонение
STDDEV_POP()Возвратит стандартное отклонение
STDDEV_SAMP()Возвратит типовое стандартное отклонение
SUM() Вернет сумму
VAR_POP() Возвратит различие стандарта
VAR_SAMP() Возвратит типовое различие
VARIANCE() Возвратит стандартное отклонение

Этот раздел описывает агрегатные (совокупные) функции, которые воздействуют на наборы значений. Если иное не заявлено, групповые функции игнорируют значения NULL.

Если Вы используете групповую функцию в запросе, не содержащем GROUP BY, это эквивалентно группировке на всех строках. Для получения дополнительной информации см. раздел 13.19.3.

Для числовых параметров различие и функции стандартного отклонения возвращают DOUBLE. Функции SUM() и AVG() возвращают значение DECIMAL для параметров точного значения (целое число или DECIMAL) и значение DOUBLE для для параметров приблизительной точности (FLOAT или DOUBLE).

Совокупные функции SUM() и AVG() не работают с временными значениями. Они преобразовывают значения в числа, теряя все после первого нечислового символа. Чтобы работать без этой проблемы, преобразуйте в числовые модули, выполните совокупную работу, и преобразуйте назад во временное значение. Примеры:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

Функции вроде SUM() или AVG() конвертируют параметр в число в случае необходимости. Для значений SET или ENUM используется основное числовое значение.

Функции BIT_AND(), BIT_OR() и BIT_XOR() выполняют битовые операции. Они требуют параметры BIGINT (64-bit integer) и возвращают BIGINT. Параметры других типов преобразованы в BIGINT и усечение могло бы произойти.

13.19.2. Модификаторы GROUP BY

Предложение GROUP BY разрешает модификатор WITH ROLLUP, который заставляет добавить дополнительные строки к итоговому выводу. Эти строки представляют более высокий уровень (или суперсовокупность). ROLLUP позволяет Вам ответить на вопросы на многих уровнях анализа единственным запросом. Это может использоваться, например, чтобы оказать поддержку для OLAP (Online Analytical Processing).

Предположите, что таблица названа sales и имеет столбцы year, country, product и profit для того, чтобы сделать запись доходности продаж:

CREATE TABLE sales (yearINT NOT NULL,
       country VARCHAR(20) NOT NULL,
       product VARCHAR(32) NOT NULL, profit INT);

Содержание таблицы может быть получено в итоге ежегодно с простым GROUP BY так:

mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 |  4525       |
| 2001 |  3010       |
+------+-------------+

Этот вывод показывает полную прибыль в течение каждого года, но если Вы также хотите определить полную прибыль, суммированную за все годы, Вы должны сложить отдельные значения самостоятельно или выполнить дополнительный запрос.

Или Вы можете использовать ROLLUP, который обеспечивает оба уровня анализа с единственным запросом. Добавление модификатора WITH ROLLUP к GROUP BY заставляет запрос производить другую строку, которая показывает общий итог по всем значениям года:

mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 |  4525       |
| 2001 |  3010       |
| NULL |  7535       |
+------+-------------+

Итоговая строка суперсовокупности идентифицирована значением NULL в столбце year.

ROLLUP имеет более сложный эффект, когда там многократные столбцы в GROUP BY. В этом случае каждый раз есть изменение в значении в любом, но обязательно последнем столбце группировки, а запрос производит дополнительную суперсовокупную сводную строку.

Например, без ROLLUP резюме для таблицы sales, основанное на year, country и product могло бы быть похожим на это:

mysql> SELECT year, country, product, SUM(profit)
    ->        FROM sales GROUP BY year, country, product;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |  1500       |
| 2000 | Finland | Phone      |   100       |
| 2000 | India   | Calculator |   150       |
| 2000 | India   | Computer   |  1200       |
| 2000 | USA     | Calculator |    75       |
| 2000 | USA     | Computer   |  1500       |
| 2001 | Finland | Phone      |    10       |
| 2001 | USA     | Calculator |    50       |
| 2001 | USA     | Computer   |  2700       |
| 2001 | USA     | TV         |   250       |
+------+---------+------------+-------------+

Вывод указывает, что резюме оценивает только на уровне year/country/product анализа. Когда ROLLUP добавлен, запрос производит несколько дополнительных строк:

mysql> SELECT year, country, product, SUM(profit)
    ->        FROM sales GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |  1500       |
| 2000 | Finland | Phone      |   100       |
| 2000 | Finland | NULL       |  1600       |
| 2000 | India   | Calculator |   150       |
| 2000 | India   | Computer   |  1200       |
| 2000 | India   | NULL       |  1350       |
| 2000 | USA     | Calculator |    75       |
| 2000 | USA     | Computer   |  1500       |
| 2000 | USA     | NULL       |  1575       |
| 2000 | NULL    | NULL       |  4525       |
| 2001 | Finland | Phone      |    10       |
| 2001 | Finland | NULL       |    10       |
| 2001 | USA     | Calculator |    50       |
| 2001 | USA     | Computer   |  2700       |
| 2001 | USA     | TV         |   250       |
| 2001 | USA     | NULL       |  3000       |
| 2001 | NULL    | NULL       |  3010       |
| NULL | NULL    | NULL       |  7535       |
+------+---------+------------+-------------+

Для этого запроса добавление ROLLUP заставляет вывод включить итоговую информацию по четырем уровням анализа, а не только одному. Вот как интерпретировать вывод ROLLUP:

Другие соображения, используя ROLLUP

Следующие элементы перечисляют некоторые особенности поведения, определенные для выполнения MySQL ROLLUP.

Когда Вы используете ROLLUP, Вы не можете также использовать ORDER BY, чтобы сортировать результаты. Другими словами, ROLLUP и ORDER BY являются взаимоисключающими. Однако, Вы все еще имеете некоторый контроль над порядком сортировки. GROUP BY в MySQL неявно сортирует результаты, и Вы можете использовать явные ключевые слова ASC и DESC со столбцами, названными в списке GROUP BY, чтобы определить порядок сортировки для отдельных столбцов. Высокоуровневые сводные строки, добавленные ROLLUP все еще появятся после строк, от которых они вычислены, независимо от порядка сортировки.

Неявная сортировка GROUP BY в MySQL 8.0 устарела. Чтобы достигнуть определенного порядка сортировки сгруппированных результатов, предпочтительно использовать явное предложение ORDER BY. Это можно обойти помещая ROLLUP в пределах подзапроса. Например:

mysql> SELECT * FROM (SELECT year, country, SUM(profit) FROM sales
    ->          GROUP BY year WITH ROLLUP) derived_t1 ORDER BY year;

LIMIT может использоваться, чтобы ограничить число строк, возвращенных клиенту. LIMIT применен после ROLLUP, таким образом, предел применяется против дополнительных строк, добавленных ROLLUP. Например:

mysql> SELECT year, country, product, SUM(profit)
    ->        FROM sales GROUP BY year, country, product WITH ROLLUP
    ->        LIMIT 5;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |  1500       |
| 2000 | Finland | Phone      |   100       |
| 2000 | Finland | NULL       |  1600       |
| 2000 | India   | Calculator |   150       |
| 2000 | India   | Computer   |  1200       |
+------+---------+------------+-------------+

Использование LIMIT с ROLLUP может привести к результатам, которые трудно интерпретировать, потому что у Вас есть меньше контекста для того, чтобы понять суперсовокупные строки.

NULL в каждой суперсовокупной строке произведен, когда строку посылают клиенту. Сервер смотрит на столбцы, названные в GROUP BY после крайнего левого, который изменил значение. Для любого столбца в наборе результатов с именем, которое соответствует любому из тех имен, его значение установлено в NULL. Если Вы определяете группирующиеся столбцы номером столбца, сервер идентифицирует который столбец установить в NULL по номеру.

Поскольку значения NULL в суперсовокупных строках помещены в набор результатов в такой позднец стадии в обработке запроса, Вы не можете проверить их как значения NULL в пределах запроса непосредственно. Например, Вы не можете добавить HAVING product IS NULL к запросу, чтобы устранить из вывода все, кроме суперсовокупных строк.

С другой стороны, значения NULL действительно появляются как NULL на стороне клиента и могут быть проверены с использованием любого клиента MySQL.

MySQL разрешает столбец, который не появляется в списке GROUP BY и назван в списке select. В этом случае сервер свободен выбрать любое значение из этого несоединенного столбца в сводных строках, и это включает дополнительные строки, добавленные WITH ROLLUP. Например, в следующем запросе country несоединенный столбец, который не появляется в списке GROUP BY и значения, выбранные для этого столбца, неопределенны:

mysql> SELECT year, country, SUM(profit)
    ->        FROM sales GROUP BY year WITH ROLLUP;
+------+---------+-------------+
| year | country | SUM(profit) |
+------+---------+-------------+
| 2000 | India   |  4525       |
| 2001 | USA     |  3010       |
| NULL | USA     |  7535       |
+------+---------+-------------+

Это поведение происходит, если режим SQL ONLY_FULL_GROUP_BY выключен. Иначе сервер отклоняет запрос как незаконный потому, что country не перечислен в предложении GROUP BY. Для получения дополнительной информации о несоединенных столбцах и GROUP BY см. раздел 13.19.3.

13.19.3. Обработка MySQL GROUP BY

SQL92 и ранее не разрешает запросы для которых список select с выражением HAVING или списком ORDER BY обращается к несоединенным столбцам, которые не называются в GROUP BY или функционально зависят от (уникально определены) столбцов GROUP BY. Например, этот запрос незаконен в стандартном SQL92 потому что несоединенный столбец name в списке select не появляется в GROUP BY:

SELECT o.custid, c.name, MAX(o.payment)
       FROM orders AS o, customers AS c
       WHERE o.custid = c.custid GROUP BY o.custid;

Чтобы запрос был законным в SQL92, столбец name должен быть исключен из списка select или назван в GROUP BY.

SQL99 и позже разрешает такие несовокупности, если они функционально зависят от столбцов GROUP BY: если такие отношения существуют между name и custid, запрос является законным. Это имело бы место, например, если custid первичный ключ customers.

MySQL осуществляет обнаружение функциональной зависимости. Если режим SQL ONLY_FULL_GROUP_BY включен (это так по умолчанию), MySQL отклоняет запросы, для который список select, выражение HAVING или список ORDER BY обращаются к несоединенным столбцам, которые не называют в GROUP BY и функционально не зависят от столбцов в GROUP BY.

Если ONLY_FULL_GROUP_BY выключен, расширение MySQL к стандартному использованию SQL GROUP BY разрешает такие запросы. Это заставляет MySQL принимать предыдущий запрос. В этом случае сервер свободен выбрать любое значение из каждой группы, так что, если они не то же самое, выбранные значения не определены. Кроме того, выбор значений из каждой группы не может быть под влиянием ORDER BY. Сортировка набора результатов происходит после того, как значения были выбраны, и ORDER BY не затрагивает, какое значение в пределах каждой группы сервер выбирает. Отключение ONLY_FULL_GROUP_BY полезно прежде всего, когда Вы знаете что, из-за некоторого свойства данных, все значения в каждом несоединенном столбце, не названном в GROUP BY те же самые для каждой группы.

Вы можете достигнуть того же самого эффекта без отключения ONLY_FULL_GROUP_BY , используя ANY_VALUE() и обратиться к несоединенному столбцу.

Следующее обсуждение демонстрирует функциональную зависимость, сообщение об ошибке, которое производит MySQL, когда функциональная зависимость отсутствует, и способы заставить MySQL принимать запрос в отсутствие функциональной зависимости.

Этот запрос мог бы быть недопустимым с включенным ONLY_FULL_GROUP_BY , потому что несоединенный столбец address в списке select не называют в GROUP BY:

SELECT name, address, MAX(age) FROM t GROUP BY name;

Запрос допустим, если name первичный ключ t или уникальный столбец NOT NULL. В таких случаях MySQL признает, что выбранный столбец функционально зависит от группирующего столбца. Например, если name первичный ключ, его значение определяет значение address потому что у каждой группы есть только одно значение первичного ключа и таким образом только одна строка. В результате нет никакой хаотичности в выборе значения address в группе и никакой потребности отклонить запрос.

Запрос недопустим, если name не первичный ключ t или уникальный столбец NOT NULL. В этом случае никакая функциональная зависимость не может быть выведена, и ошибка происходит:

mysql> SELECT name, address, MAX(age) FROM t GROUP BY name;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP
BY clause and contains nonaggregated column 'mydb.t.address' which
is not functionally dependent on columns in GROUP BY clause; this
is incompatible with sql_mode=only_full_group_by

Если Вы знаете, что для определенных данных каждое значение name фактически уникально определяет address, то address эффективно функционально зависит от name. Чтобы сказать MySQL принять запрос, Вы можете использовать ANY_VALUE() :

SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;

Альтернативно, отключите ONLY_FULL_GROUP_BY .

Предыдущий пример довольно прост, как бы то ни было. В частности, маловероятно, что Вы сгруппировались бы на единственном столбце первичного ключа, потому что каждая группа будет содержать только одну строку. Для примеров, демонстрирующих функциональную зависимость в более сложных запросах см. раздел 13.19.4.

Если у запроса есть совокупные функции и нет GROUP BY, он не может иметь несоединенные столбцы в списке select, выражении HAVING или списке ORDER BY с включенным режимом ONLY_FULL_GROUP_BY :

mysql> SELECT name, MAX(age) FROM t;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression
#1 of SELECT list contains nonaggregated column 'mydb.t.name'; this
is incompatible with sql_mode=only_full_group_by

Без GROUP BY есть единственная группа и неопределенно, которое значение name выбрать для группы. Здесь также может использоваться ANY_VALUE() , если несущественно, которое значение name MySQL выбирает:

SELECT ANY_VALUE(name), MAX(age) FROM t;

ONLY_FULL_GROUP_BY также влияет на обработку DISTINCT и ORDER BY. Рассмотрите случай таблицы t с тремя столбцами c1, c2 и c3, которые содержат эти строки:

c1 c2 c3
1  2  A
3  4  B
1  2  C

Предположите, что мы выполняем следующий запрос, ожидая, что результаты будут упорядочены по c3:

SELECT DISTINCT c1, c2 FROM t ORDER BY c3;

Чтобы упорядочить результат, сначала должны быть устранены дубликаты. Но какую строку мы должны сохранить, первую или третью? Этот произвольный выбор влияет на сохраненное значение c3, что в свою очередь влияет на упорядочивание и делает его произвольным. Чтобы предотвратить эту проблему, запрос, который имеет DISTINCT и ORDER BY отклонен как недопустимый, если выражение ORDER BY не удовлетворяет по крайней мере одно из этих условий:

Другое расширение MySQL к стандартному SQL разрешает ссылки в HAVING выражениям в списке select. Например, следующий запрос возвращает значения name, которые только одни в таблице orders:

SELECT name, COUNT(name) FROM orders GROUP BY name HAVING COUNT(name) = 1;

Расширение MySQL разрешает использование псевдонима в HAVING для соединенного столбца:

SELECT name, COUNT(name) AS c FROM orders GROUP BY name HAVING c = 1;

Включение ONLY_FULL_GROUP_BY отключает это расширение, таким образом требуя HAVING, который будет написан, используя выражения без псевдонимов.

Стандартный SQL не разрешает выражения в GROUP BY, таким образом, этот запрос недопустим:

SELECT id, FLOOR(value/100) FROM tbl_name
       GROUP BY id, FLOOR(value/100);

MySQL расширяет стандартный SQL, чтобы разрешить выражения в GROUP BY и считает предыдущий запрос допустимым.

Стандартный SQL также не разрешает псевдонимы в GROUP BY. MySQL расширяет стандартный SQL, чтобы разрешить псевдонимы, таким образом, другой способ написать запрос следующий:

SELECT id, FLOOR(value/100) AS val
       FROM tbl_name
       GROUP BY id, val;

13.19.4. Обнаружение функциональной зависимости

Следующее обсуждение обеспечивает несколько примеров путей, которыми MySQL обнаруживает функциональные зависимости. Примеры используют эту нотацию:

{X} -> {Y}

Поймите это как X уникально определяет Y, это также означает, что Y функционально зависит от X.

Примеры используют базу данных world, которая может быть загружена с MySQL Documentation page. Вы можете найти детали о том, как установить базу данных на той же самой странице.

Функциональные зависимости, полученные из ключей

Следующий запрос выбирает для каждой страны количество разговорных языков:

SELECT co.Name, COUNT(*) FROM countrylanguage cl, country co
       WHERE cl.CountryCode = co.Code GROUP BY co.Code;

co.Code первичный ключ co, так что все столбцы co функционально зависят от этого, как выражено здесь:

{co.Code} -> {co.*}

Таким образом, co.name функционально зависит от столбцов GROUP BY и запрос допустим.

Индекс UNIQUE по столбцу NOT NULL мог использоваться вместо первичного ключа, и та же самая функциональная зависимость применится. Это не истина для индекса UNIQUE, который разрешает значения NULL, потому что это разрешает многократные значения NULL и в этом случае уникальность потеряна.

Функциональные зависимости, полученные из ключей нескольких столбцов и из равенств

Этот запрос выбирает для каждой страны список всех разговорных языков и сколько людей говорит на них:

SELECT co.Name, cl.Language,
       cl.Percentage * co.Population / 100.0 AS SpokenBy
       FROM countrylanguage cl, country co
       WHERE cl.CountryCode = co.Code
       GROUP BY cl.CountryCode, cl.Language;

Пара (cl.CountryCode, cl.Language) задает сложный первичный ключ на двух столбцах cl, так, чтобы пара столбцов уникально определила все столбцы cl:

{cl.CountryCode, cl.Language} -> {cl.*}

Кроме того, из-за равенства в WHERE:

{cl.CountryCode} -> {co.Code}

И потому что co.Code первичный ключ co:

{co.Code} -> {co.*}

Уникально определенные являются переходными, поэтому:

{cl.CountryCode, cl.Language} -> {cl.*,co.*}

В результате запрос допустим.

Как с предыдущим примером, ключ UNIQUE на столбцах NOT NULL мог бы использоваться вместо первичного ключа.

Условие INNER JOIN может использоваться вместо WHERE. Те же самые функциональные зависимости применяются:

SELECT co.Name, cl.Language, cl.Percentage * co.Population/100.0 AS SpokenBy
       FROM countrylanguage cl INNER JOIN country co
       ON cl.CountryCode = co.Code
       GROUP BY cl.CountryCode, cl.Language;

Особые случаи функциональной зависимости

Принимая во внимание, что тест равенства в WHERE или INNER JOIN симметричен, тест равенства во внешнем условии соединения не такой, потому что таблицы играют различные роли.

Предположите, что целостность была случайно сломана и там существует строка countrylanguage без соответствующей строки в country. Рассмотрите тот же самый запрос как в предыдущем примере, но с LEFT JOIN:

SELECT co.Name, cl.Language,
       cl.Percentage * co.Population/100.0 AS SpokenBy
       FROM countrylanguage cl LEFT JOIN country co
       ON cl.CountryCode = co.Code
       GROUP BY cl.CountryCode, cl.Language;

Для данного значения cl.CountryCode значение co.Code в соединеннном результате найден в соответствующей строке (определенной cl.CountryCode) или дополнен NULL, если там нет соответствия (также определено cl.CountryCode). В каждом случае применяются эти отношения:

{cl.CountryCode} -> {co.Code}

cl.CountryCode самостоятельно функционально зависит от {cl.CountryCode, cl.Language}, который является первичным ключом.

Если в результате соединения co.Code дополнен NULL, то и co.Name тоже. Если co.Code не дополнен NULL, это потому, что co.Code первичный ключ, это определяет co.Name. Поэтому во всех случаях:

{co.Code} -> {co.Name}

что уступает:

{cl.CountryCode, cl.Language} -> {cl.*,co.*}

В результате запрос допустим.

Однако, предположите, что таблицы поменяны, как в этом запросе:

SELECT co.Name, cl.Language,
       cl.Percentage * co.Population/100.0 AS SpokenBy
       FROM country co LEFT JOIN countrylanguage cl
       ON cl.CountryCode = co.Code
       GROUP BY cl.CountryCode, cl.Language;

Теперь эти отношения не применяются:

{cl.CountryCode, cl.Language} -> {cl.*,co.*}

Действительно, все NULL-дополненные строки, сделанные для cl будут помещены в единственную группу (у них есть оба столбца GROUP BY равные NULL), и в этой группе значение co.Name может измениться. Запрос недопустим, и MySQL отклоняет его.

Функциональная зависимость во внешних соединениях, таким образом, соединена с тем, принадлежат ли определяющие столбцы левой или правой стороне LEFT JOIN. Определение функциональной зависимости становится более сложным, если там вложены внешние соединения или условие соединения не состоит полностью из сравнений равенства.

Функциональные зависимости и представления

Предположите, что представление о странах производит их код, их имя в верхнем регистре, и сколько различных официальных языков они имеют:

CREATE VIEW Country2 AS
       SELECT co.Code, UPPER(co.Name) AS UpperName,
              COUNT(cl.Language) AS OfficialLanguages
              FROM country AS co JOIN countrylanguage AS cl
              ON cl.CountryCode = co.Code WHERE cl.isOfficial = 'T'
              GROUP BY co.Code;

Это определение допустимо потому, что:

{co.Code} -> {co.*}

В результате представления первый выбранный столбец co.Code, который является также групповым столбцом и таким образом определяет все другие выбранные выражения:

{Country2.Code} -> {Country2.*}

MySQL понимает это и использует эту информацию, как описано после.

Этот запрос выводит на экран страны, сколько различных официальных языков они имеют, и сколько городов они имеют, присоединяясь к представлению с таблицей city:

SELECT co2.Code, co2.UpperName, co2.OfficialLanguages,
       COUNT(*) AS Cities FROM country2 AS co2 JOIN city ci
       ON ci.CountryCode = co2.Code GROUP BY co2.Code;

Этот запрос допустим потому что, как замечено ранее:

{co2.Code} -> {co2.*}

MySQL в состоянии обнаружить функциональную зависимость в результате представления и применить ее, чтобы утвердить запрос, который использует представление. То же самое было бы истиной, если country2 была созданной таблицей, как в:

SELECT co2.Code, co2.UpperName, co2.OfficialLanguages, COUNT(*) AS Cities
       FROM (SELECT co.Code, UPPER(co.Name) AS UpperName,
             COUNT(cl.Language) AS OfficialLanguages
             FROM country AS co JOIN countrylanguage AS cl
             ON cl.CountryCode=co.Code WHERE cl.isOfficial='T'
             GROUP BY co.Code)
       AS co2 JOIN city ci ON ci.CountryCode = co2.Code GROUP BY co2.Code;

Комбинации функциональных зависимостей

MySQL в состоянии объединить все предыдущие типы функциональных зависимостей, чтобы утвердить более сложные запросы.

13.20. Точная математика

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

Эти особенности имеют несколько значений для числовых операций и обеспечивают высокую степень согласия со стандартным SQL:

Следующее обсуждение покрывает несколько аспектов того, как математика точности работает, включая возможные несовместимости с более старыми приложениями. В конце некоторые примеры демонстрируют, как MySQL обрабатывает числовые операции точно. Для информации об управлении режимом SQL см. раздел 6.1.8.

13.20.1. Типы числовых значений

Контекст математики точности для операций точного значения включает типы данных точного значения (целое число и DECIMAL) и точное значение числовых литералов. Типы данных приблизительной точности и числовые литералы обработаны как числа с плавающей запятой.

У точного значения числовых литералов есть часть целого числа или дробная часть, или обе. Они могут быть со знаком. Примеры: 1, .2, 3.4, -5, -6.78, +9.10.

Числа приблизительной точности представлены в экспоненциальном представлении с мантиссой и экспонентой. Обе части могут быть со знаком. Примеры: 1.2E3, 1.2E-3, -1.2E3, -1.2E-3.

Два числа, которые выглядят подобными, могут быть обработаны по-другому. Например, 2.34 точное значение (фиксированная точка), тогда как 2.34E0 приблизительное число (с плавающей запятой).

Тип данных DECIMAL тип с фиксированной точкой, вычисления точны. В MySQL тип у типа DECIMAL есть несколько синонимов: NUMERIC, DEC, FIXED. Типы целого числа это типы точного значения.

Типы FLOAT и DOUBLE типы с плавающей запятой, вычисления приблизительны. В MySQL типы, которые синонимичны с FLOAT или DOUBLE это DOUBLE PRECISION и REAL.

13.20.2. Характеристики типа данных DECIMAL

Этот раздел обсуждает характеристики типа данных DECIMAL (и его синонимов) с особым отношением к следующим темам:

Синтаксис декларации для столбцов DECIMAL DECIMAL(M,D). Диапазоны значений для параметров следующие:

Максимальное значение 65 для M означает, что вычисления на значениях DECIMAL точны до 65 цифр. Этот предел точности в 65 цифр также относится к точному значению числовых литералов, таким образом, максимальный диапазон таких литералов отличается.

Значения для столбцов DECIMAL сохранены, используя двоичный формат, который упаковывает девять десятичных цифр в 4 байта. Требования хранения для целого числа и дробных частей каждого значения определены отдельно. Каждое число, кратное девяти цифрам, требует 4 байтов, и любые остающиеся перенесенные цифры требуют некоторой части 4 байтов. Хранение, требуемое для оставшихся цифр, дано следующей таблицей.

Оставшиеся цифры Число байтов
00
1-21
3-42
5-63
7-94

Например, у столбца DECIMAL(18,9) есть девять цифр по обе стороны от десятичной запятой, таким образом, часть целого числа и дробная часть требуют по 4 байта. Столбец DECIMAL(20,6) имеет четырнадцать цифр целого числа и шесть дробных цифр. Цифры целого числа требуют четырех байтов для девяти цифр и 3 байтов для оставшихся пяти. Шесть дробных цифр требуют еще 3 байтов.

Столбцы DECIMAL не хранят символы + или -, также старотовые нули. Если Вы вставляете +0003.1 в столбец типа DECIMAL(5,1) , это сохранено как 3.1. Для отрицательных чисел символ - не сохранен.

Столбцы DECIMAL не разрешают значения, больше чем диапазон, подразумеваемый определением столбца. Например, столбец DECIMAL(3,0) поддерживает диапазон от -999 до 999. Столбец DECIMAL(M, D) разрешает самое большее M-D цифр слева от десятичной запятой.

Стандарт SQL требует, чтобы точность NUMERIC(M,D) была точно M цифр. Для DECIMAL(M,D) стандарт требует точности, по крайней мере, M цифр, но разрешает и больше. В MySQL DECIMAL(M,D) и NUMERIC(M,D) то же самое, и у обоих есть точность строго M цифр.

Для полного объяснения внутреннего формата значения DECIMAL см. файл strings/decimal.c в исходных текстах MySQL. Формат объяснен (с примером) в функции decimal2bin().

13.20.3. Обработка выражений

С математикой числа точного значения используются как дано, когда это возможно. Например, числа в сравнениях используются точно как даны без изменения в значении. В строгом режиме SQL для INSERT в столбец с точным типом данных (DECIMAL или integer), число вставлено с его точным значением, если это в пределах диапазона столбца. Когда получено, значение должно быть тем же самым как то, что было вставлено. Если строгий режим SQL не включен, усечение для INSERT допустимо.

Обработка числового выражения зависит от того, какие значения выражение содержит:

Если числовое выражение содержит какие-либо строки, они преобразованы в двоичную точность, значения с плавающей запятой и выражение приблизительны.

Вставки в числовые столбцы, затронуты режимом SQL, которым управляет системная переменная sql_mode . См. раздел 6.1.8. Следующее обсуждение упоминает строгий режим (выбранный значениями режима STRICT_ALL_TABLES или STRICT_TRANS_TABLES) и ERROR_FOR_DIVISION_BY_ZERO. Чтобы включить все ограничения, Вы можете просто использовать режим TRADITIONAL, который включает строгие значения режима и ERROR_FOR_DIVISION_BY_ZERO:

mysql> SET sql_mode='TRADITIONAL';

Если число вставлено в столбец точного типа (DECIMAL или integer), оно вставлено с его точным значением, если это в пределах диапазона столбца.

Если у значения есть слишком много цифр в дробной части, округление происходит, и предупреждение произведено. Округление сделано как описано в разделе 13.20.4.

Если у значения есть слишком много цифр в части целого числа, оно является слишком большим и обработано следующим образом:

Для вставок строк в числовые столбцы преобразование строки в число обработано следующим образом, если у строки есть нечисловое содержание:

По умолчанию деление на ноль приводит к результату NULL и ни к какому предупреждению. Устанавливая режим SQL соответственно, деление на ноль может быть ограничено.

В режиме SQL ERROR_FOR_DIVISION_BY_ZERO MySQL обрабатывает деление на ноль по-другому:

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

Предположите, что у нас есть этот запрос:

INSERT INTO t SET i = 1/0;

Это то, что происходит для комбинации строгого режима и ERROR_FOR_DIVISION_BY_ZERO.

Значение sql_modeРезультат
'' (Значение по умолчанию) Никакого предупреждения, никакой ошибки i установлен в NULL.
strict Никакого предупреждения, никакой ошибки i установлен в NULL.
ERROR_FOR_DIVISION_BY_ZERO Предупреждение, но никакой ошибки i установлен в NULL.
strict, ERROR_FOR_DIVISION_BY_ZERO Состояние ошибки: никакая строка не вставлена.

13.20.4. Логика округления

Этот раздел обсуждает математику точности, округляющую для функции ROUND() и для вставок в столбцы с типами точного значения ( DECIMAL и integer).

Функция ROUND() округляет по-разному в зависимости от того, точен ли параметр или приблизителен:

Следующие примеры показывают, как округление отличается для точных и приблизительных чисел:

mysql> SELECT ROUND(2.5), ROUND(25E-1);
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3          | 2            |
+------------+--------------+

Для вставок в столбец DECIMAL или целого числа цель точный тип данных, таким образом, округлениея использует правило округления половины вверх независимо от того, точно ли значение, которое будет вставлено, или приблизительно:

mysql> CREATE TABLE t (d DECIMAL(10,0));
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t VALUES(2.5),(2.5E0);
Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 2

mysql> SELECT d FROM t;
+---+
| d |
+---+
| 3 |
| 3 |
+---+

13.20.5. Примеры точной математики

Этот раздел обеспечивает некоторые примеры, которые показывают математические результаты запроса точности в MySQL. Эти примеры демонстрируют принципы, описанные в разделах 13.20.3 и 13.20.4.

Пример 1. Числа используются с их точным значением как даны, когда возможно:

mysql> SELECT (.1 + .2) = .3;
+----------------+
| (.1 + .2) = .3 |
+----------------+
| 1              |
+----------------+

Для значений с плавающей запятой результаты неточны:

mysql> SELECT (.1E0 + .2E0) = .3E0;
+----------------------+
| (.1E0 + .2E0) = .3E0 |
+----------------------+
| 0                    |
+----------------------+

Другой способ видеть различие в обработке точных и приблизительных чисел состоит в том, чтобы добавить небольшое число к сумме много раз. Рассмотрите следующую хранимую процедуру, которая добавляет .0001 к переменным 1,000 раз.

CREATE PROCEDURE p ()
BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE d DECIMAL(10,4) DEFAULT 0;
  DECLARE f FLOAT DEFAULT 0;
  WHILE i < 10000 DO
    SET d = d + .0001;
    SET f = f + .0001E0;
    SET i = i + 1;
  END WHILE;
  SELECT d, f;
END;

Сумма для обоих d и f логически должна быть 1, но это истина только для десятичного вычисления. Вычисление с плавающей запятой вводит маленькие ошибки:

+--------+------------------+
| d      | f                |
+--------+------------------+
| 1.0000 | 0.99999999999991 |
+--------+------------------+

Пример 2. Умножение выполнено с масштабом, требуемым стандартным SQL. Таким образом, для двух чисел X1 и X2 есть масштаб S1 и S2, масштаб результата S1+S2 :

mysql> SELECT .01 * .01;
+-----------+
| .01 * .01 |
+-----------+
| 0.0001    |
+-----------+

Пример 3. Округление для чисел точного значения является четким:

Округление (например, функцией ROUND()) независимо от выполнения основной библиотеки C, это означает, что результаты последовательны, независмо от платформы.

Пример 4. В строгом режиме, вставляя значение, которое вне диапазона для столбца, Вы получите ошибку, а не усечение к легальному значению.

Когда MySQL не работает в строгом режиме, усечение к легальному значению происходит:

mysql> SET sql_mode='';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SET i = 128;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> SELECT i FROM t;
+-----+
| i   |
+-----+
| 127 |
+-----+
1 row in set (0.00 sec)

Однако, ошибка происходит, если строгий режим активен:

mysql> SET sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 128;
ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1

mysql> SELECT i FROM t;
Empty set (0.00 sec)

Пример 5. В строгом режиме и с установленной опцией ERROR_FOR_DIVISION_BY_ZERO деление на ноль вызывает ошибку, а не результат NULL.

В нестрогом режиме у деления есть результат NULL:

mysql> SET sql_mode='';
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 1/0;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT i FROM t;
+------+
| i    |
+------+
| NULL |
+------+
1 row in set (0.03 sec)

Однако, деление на ноль ошибка, если надлежащие режимы SQL включены:

mysql> SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 1 / 0;
ERROR 1365 (22012): Division by 0

mysql> SELECT i FROM t;
Empty set (0.01 sec)

Пример 6. Литералы точного значения оценены как точные значения.

Числа приблизительной точности оценены, используя плавающую запятую, но числа точного значения обработаны как DECIMAL:

mysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> DESCRIBE t;
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| a     | decimal(2,1) unsigned | NO   |     | 0.0     |       |
| b     | double                | NO   |     | 0       |       |
+-------+-----------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

Пример 7. Если параметр совокупной функции точный числовой тип, результат также точный числовой тип, с масштабом, по крайней мере таким, как у параметра.

Рассмотрите эти запросы:

mysql> CREATE TABLE t (i INT, d DECIMAL, f FLOAT);
mysql> INSERT INTO t VALUES(1,1,1);
mysql> CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;

Результат double только для параметра с плавающей запятой. Для точных параметров типа результат также точный тип:

mysql> DESCRIBE y;
+--------+---------------+------+-----+---------+-------+
| Field  | Type          | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| AVG(i) | decimal(14,4) | YES  |     | NULL    |       |
| AVG(d) | decimal(14,4) | YES  |     | NULL    |       |
| AVG(f) | double        | YES  |     | NULL    |       |
+--------+---------------+------+-----+---------+-------+