RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 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.

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

  • Если один или оба параметра NULL, результат сравнения NULL, за исключением NULL-безопасного оператора <=>. Для NULL <=> NULL результат true. Никакое преобразование не нужно.

  • Если оба параметра строки, они сравнены как строки.
  • Если оба параметра целые числа, они сравнены как целые числа.
  • Шестнадцатеричные значения обработаны как двоичные строки, если не сравниваются с числом.
  • Если один из параметров столбец TIMESTAMP или DATETIME, а другой параметр константа, она преобразована в timestamp прежде, чем сравнение будет выполнено. Это сделано, чтобы быть более ODBC-благоприятным. Отметьте, что это не сделано для параметров в IN() ! Для надежности всегда используйте полный datetime, дату или строки времени, делая сравнения. Например, чтобы достичь лучших результатов, используя BETWEEN с датой или временем, надо использовать CAST(), чтобы явно преобразовать значения в желаемый тип данных.

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

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

Сравнение значений 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:

  • Преобразование одинаково для платформ.

  • Точное представление значений в случаях, где результаты ранее не обеспечивали достаточную точность, это касается значений близко к пределам IEEE.
  • Преобразование чисел, чтобы представить формат в виде строки с самой лучшей точностью. Точность dtoa всегда та же самая или лучше, чем у стандартных функций C-библиотеки.

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

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

  • F -> D преобразование сделано с самой лучшей точностью, возвращая D как самую короткую строку, которая уступает F когда чтение назад округляется к самому близкому значению в родном двоичном формате как определено IEEE.

  • D -> F преобразование сделано таким образом что F самое близкое родное двоичное число к входной строке десятичного числа D.

Эти свойства подразумевают, что 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:

  • По умолчанию || это логический OR. Если включен PIPES_AS_CONCAT , || объединяет строки с приоритетом между ^ и одноместными операторами.

  • По умолчанию ! имеет более высокий приоритет чем NOT. С включенным HIGH_NOT_PRECEDENCE ! и NOT имеют тот же самый приоритет.

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

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), которое также работает хорошо на английском языке.

  • =

    Равенство:

    mysql> SELECT 1 = 0;
        -> 0
    mysql> SELECT '0' = 0;
        -> 1
    mysql> SELECT '0.0' = 0;
        -> 1
    mysql> SELECT '0.01' = 0;
        -> 0
    mysql> SELECT '.01' = 0.01;
        -> 1
    

    Для сравнений строки (a, b) = (x, y) эквивалентно:

    (a = x) AND (b = y)
    
  • <=>

    NULL-безопасное равенство. Этот оператор выполняет сравнение равенства как =, но возвращает 1 вместо NULL, если оба операнда NULL и 0 вместо NULL, если один операнд NULL.

    Оператор <=> эквивалентен стандартному SQL IS NOT DISTINCT FROM.

    mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
        -> 1, 1, 0
    mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
        -> 1, NULL, NULL
    

    Для сравнений строк (a, b) <=> (x, y) эквивалентно:

    (a <=> x) AND (b <=> y)
    
  • <>, !=

    Не равно:

    mysql> SELECT '.01' <> '0.01';
      -> 1
    mysql> SELECT .01 <> '0.01';
      -> 0
    mysql> SELECT 'zapp' <> 'zappp';
      -> 1
    

    Для сравнений строк (a, b) <> (x, y) и (a, b) != (x, y) эквивалентно:

    (a <> x) OR (b <> y)
    
  • <=

    Меньше или равно:

    mysql> SELECT 0.1 <= 2;
      -> 1
    

    Для сравнений строк (a, b) <= (x, y) эквивалентно:

    (a < x) OR ((a = x) AND (b <= y))
    
  • <

    Меньше:

    mysql> SELECT 2 < 2;
      -> 0
    

    Для сравнений строк (a, b) < (x, y) эквивалентно:

    (a < x) OR ((a = x) AND (b < y))
    
  • >=

    Больше или равно:

    mysql> SELECT 2 >= 2;
      -> 1
    

    Для сравнений строк (a, b) >= (x, y) эквивалентно:

    (a > x) OR ((a = x) AND (b >= y))
    
  • >

    Больше:

    mysql> SELECT 2 > 2;
      -> 0
    

    Для сравнений строк (a, b) > (x, y) эквивалентно:

    (a > x) OR ((a = x) AND (b > y))
    
  • IS boolean_value

    Сравнивает значение с булевым значением, где boolean_value может быть TRUE, FALSE или UNKNOWN.

    mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;
      -> 1, 1, 1
    
  • IS NOT boolean_value

    Сравнивает значение с булевым значением, где boolean_value может быть TRUE, FALSE или UNKNOWN.

    mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;
      -> 1, 1, 0
    
  • IS NULL

    Является ли значение NULL.

    mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
      -> 0, 0, 1
    

    Чтобы работать хорошо с программами ODBC, MySQL поддерживает следующие дополнительные функции, используя IS NULL:

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

      SELECT * FROM tbl_name WHERE auto_col IS NULL
      

      Если запрос возвращает строку, значение возврата то же самое, как будто Вы вызвали LAST_INSERT_ID() . Если нет успешно вставленного значения AUTO_INCREMENT , запрос SELECT не возвращает строки.

      Поведение получения AUTO_INCREMENT при использовании IS NULL может быть отключено, устанавливая sql_auto_is_null = 0 .

      Значение по умолчанию sql_auto_is_null 0.

    • Для столбцов DATE и DATETIME, которые объявлены как NOT NULL, Вы можете найти специальную дату '0000-00-00' при использовании запроса:
      SELECT * FROM tbl_name WHERE date_column IS NULL
      

      Это необходимо, чтобы заставить некоторые приложения ODBC работать, потому что ODBC не поддерживает значение даты '0000-00-00'.

      См. Obtaining Auto-Increment Values и описание для опции FLAG_AUTO_IS_NULL на Connector/ODBC Connection Parameters.

  • IS NOT NULL

    Проверяет, не является ли значение NULL.

    mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
      -> 1, 1, 0
    
  • expr BETWEEN min AND max

    Если expr больше чем или равен min и expr меньше чем или равно max, BETWEEN возвращает 1, иначе 0. Это эквивалентно выражению (min <= expr AND expr <= max), если все параметры имеют тот же самый тип. Иначе имеет место преобразование типов, согласно правилам, описанным в разделе 13.2, но ко всем этим трем параметрам.

    mysql> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;
      -> 1, 0
    mysql> SELECT 1 BETWEEN 2 AND 3;
      -> 0
    mysql> SELECT 'b' BETWEEN 'a' AND 'c';
      -> 1
    mysql> SELECT 2 BETWEEN 2 AND '3';
      -> 1
    mysql> SELECT 2 BETWEEN 2 AND 'x-3';
      -> 0
    

    Для лучших результатов, используя BETWEEN с датой или временем, надо использовать CAST(), чтобы явно преобразовать значения в желаемый тип данных. Если Вы сравниваете DATETIME с двумя значениями DATE, преобразуйте DATE в DATETIME. Если Вы используете такую строку, как '2001-1-1' в сравнении с DATE, преобразуйте строку к DATE.

  • expr NOT BETWEEN min AND max

    Это то же самое, как NOT (expr BETWEEN min AND max).

  • COALESCE(value ,...)

    Возвращает первое не-NULL значение в списке, или NULL, если нет не-NULL значений.

    mysql> SELECT COALESCE(NULL,1);
      -> 1
    mysql> SELECT COALESCE(NULL,NULL,NULL);
      -> NULL
    
  • GREATEST(value1 ,value2,...)

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

    mysql> SELECT GREATEST(2,0);
      -> 2
    mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
      -> 767.0
    mysql> SELECT GREATEST('B','A','C');
      -> 'C'
    

    GREATEST() возвращает NULL, если какой-либо параметр NULL.

  • expr IN (value,...)

    Возвращает 1, если expr равно любому из значений в списке IN, иначе 0. Если все значения константы, они оценены согласно типу expr и отсортированы. Поиск элемента тогда сделан, используя двоичный поиск. Это означает, что IN очень быстр, если список значений IN состоит полностью из констант. Иначе имеет место преобразование типов, согласно правилам, описанным в разделе 13.2, но ко всем параметрам.

    mysql> SELECT 2 IN (0,3,5,7);
      -> 0
    mysql> SELECT 'wefwf' IN ('wee','wefwf','weg');
      -> 1
    

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

    mysql> SELECT (3,4) IN ((1,2), (3,4));
      -> 1
    mysql> SELECT (3,4) IN ((1,2), (3,5));
      -> 0
    

    Вы никогда не должны смешивать заключенные в кавычки значения со значениями без кавычек, потому что правила сравнения для заключенных в кавычки значений (таких как строки) отличаются. Смешивание типов может поэтому привести к непоследовательным результатам. Например, не пишите такое выражение IN:

    SELECT val1 FROM tbl1 WHERE val1 IN (1,2,'a');
    

    Вместо этого напишите так:

    SELECT val1 FROM tbl1 WHERE val1 IN ('1','2','a');
    

    Число значений в списке IN ограничено только значением max_allowed_packet .

    Для выполнения стандарта SQL, IN вернет NULL не только если выражение на левой стороне NULL, но также если никакое соответствие не найдено в списке, и одно из выражений в списке NULL.

    Синтаксис IN() может также использоваться, чтобы написать определенные типы подзапросов. См. раздел 14.2.10.3.

  • expr NOT IN (value,...)

    Аналог NOT (expr IN (value,...)).

  • ISNULL(expr)

    Если expr NULL, ISNULL() вернет 1, иначе 0.

    mysql> SELECT ISNULL(1+1);
      -> 0
    mysql> SELECT ISNULL(1/0);
      -> 1
    

    ISNULL() может использоваться вместо =, чтобы проверить, является ли значение NULL. Сравнение значения с NULL, используя = всегда вернет NULL.

    Функция ISNULL() совместно использует некоторые специальные поведения с оператором IS NULL. См. описание IS NULL.

  • INTERVAL(N, N1,N2,N3, ...)

    Вернет 0 если N < N1, 1 если N < N2 и так далее или -1 если N NULL. Все параметры обработаны как целые числа. Для этой функции требуется N1 < N2 < N3 < ... < Nn, чтобы работать правильно. Это потому, что двоичный поиск используется (очень быстрый).

    mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
      -> 3
    mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
      -> 2
    mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
      -> 0
    
  • LEAST(value1, value2,...)

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

    • Если какой-либо параметр NULL, результат NULL. Никакое сравнение не нужно.

    • Если возвращаемое значение используется в контексте INTEGER или все параметры оценены как целые числа, они сравнены как целые числа.
    • Если возвращаемое значение используется в контексте REAL или все параметры оценены как реальные, они сравнены как реальные.
    • Если параметры включают соединение чисел и строк, они сравнены как числа.
    • Если какой-либо параметр символьная строка, параметры сравнены как строки.
    • Во всех других случаях параметры сравнены как двоичные строки.

    mysql> SELECT LEAST(2,0);
      -> 0
    mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
      -> 3.0
    mysql> SELECT LEAST('B','A','C');
      -> 'A'
    

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

    mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) AS SIGNED);
      -> -9223372036854775808
    

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

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
  • NOT, !

    Логический NOT. Оценивается как 1, если операнд 0, как 0, если операнд отличен от нуля и NOT NULL вернет NULL.

    mysql> SELECT NOT 10;
      -> 0
    mysql> SELECT NOT 0;
      -> 1
    mysql> SELECT NOT NULL;
      -> NULL
    mysql> SELECT ! (1+1);
      -> 0
    mysql> SELECT ! 1+1;
      -> 1
    

    Последний пример производит 1 потому, что выражение оценивает тем же самым путь, как (!1)+1.

  • AND, &&

    Логический AND. Оценивается как 1, если все операнды являются отличными от нуля и не NULL, как 0, если один или более операндов 0, иначе NULL возвращен.

    mysql> SELECT 1 AND 1;
      -> 1
    mysql> SELECT 1 AND 0;
      -> 0
    mysql> SELECT 1 AND NULL;
      -> NULL
    mysql> SELECT 0 AND NULL;
      -> 0
    mysql> SELECT NULL AND 0;
      -> 0
    
  • OR, ||

    Логический OR. Когда оба операнда не-NULL, результат 1, если какой-либо операнд является отличным от нуля, и 0 иначе. Если один операнд NULL, результат 1, если другой операнд является отличным от нуля, иначе NULL. Если оба операнда NULL, результат NULL.

    mysql> SELECT 1 OR 1;
      -> 1
    mysql> SELECT 1 OR 0;
      -> 1
    mysql> SELECT 0 OR 0;
      -> 0
    mysql> SELECT 0 OR NULL;
      -> NULL
    mysql> SELECT 1 OR NULL;
      -> 1
    
  • XOR

    Логический XOR. Возвращает NULL, если любой операнд NULL. Для не-NULL операндов, оценивает как 1, если нечетное число операндов является отличным от нуля, иначе вернет 0.

    mysql> SELECT 1 XOR 1;
      -> 0
    mysql> SELECT 1 XOR 0;
      -> 1
    mysql> SELECT 1 XOR NULL;
      -> NULL
    mysql> SELECT 1 XOR 1 XOR 1;
      -> 1
    

    a XOR b математически равно (a AND (NOT b)) OR ((NOT a) and b).

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

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

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

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

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

    mysql> SELECT @var1, @var2;
      -> NULL, NULL
    mysql> SELECT @var1 := 1, @var2;
      -> 1, NULL
    mysql> SELECT @var1, @var2;
      -> 1, NULL
    mysql> SELECT @var1, @var2 := @var1;
      -> 1, 1
    mysql> SELECT @var1, @var2;
      -> 1, 1
    mysql> SELECT @var1:=COUNT(*) FROM t1;
      -> 4
    mysql> SELECT @var1;
      -> 4
    

    Вы можете сделать присвоение значения, используя := в других запросах, кроме SELECT, например, в UPDATE:

    mysql> SELECT @var1;
      -> 4
    mysql> SELECT * FROM t1;
      -> 1, 3, 5, 7
    
    mysql> UPDATE t1 SET c1 = 2 WHERE c1 = @var1:= 1;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT @var1;
      -> 1
    mysql> SELECT * FROM t1;
      -> 2, 3, 5, 7
    

    В то же время возможно установить и считать значение той же самой переменной в единственном запросе SQL, используя :=, но это не рекомендуется. Раздел 10.4 объясняет, почему Вы должны избегать делать это.

  • =

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

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

    В предложении SET запроса UPDATE = также действует как оператор назначения. В этом случае это заставляет столбец, названный на левой стороне оператора, предполагать, что значение, данное на правой стороне, предоставило любому WHERE условия, которые являются частью UPDATE. Вы можете сделать многократные назначения в том же самом SET запроса UPDATE.

    В любом другом контексте = обработан как оператор сравнения.

    mysql> SELECT @var1, @var2;
      -> NULL, NULL
    mysql> SELECT @var1 := 1, @var2;
      -> 1, NULL
    mysql> SELECT @var1, @var2;
      -> 1, NULL
    mysql> SELECT @var1, @var2 := @var1;
      -> 1, 1
    mysql> SELECT @var1, @var2;
      -> 1, 1
    

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

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

ИмяОписание
CASE Case
IF() If/else
IFNULL() Null if/else
NULLIF() NULL, если expr1 = expr2
  • CASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN result ...] [ELSE result] END

    CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END

    Первая версия возвращает result, где value=compare_value. Вторая версия возвращает результат для первого условия, которое является истиной. Если не было никакого значения результата соответствия, вернется результат после ELSE или NULL, если нет ELSE.

    mysql> SELECT CASE 1 WHEN 1 THEN 'one'
      -> WHEN 2 THEN 'two' ELSE 'more' END;
      -> 'one'
    mysql> SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;
      -> 'true'
    mysql> SELECT CASE BINARY 'B'
      -> WHEN 'a' THEN 1 WHEN 'b' THEN 2 END;
      -> NULL
    

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

    Синтаксис CASE expression, показанный здесь, отличается немного от SQL CASE statement, описанного в разделе 14.6.5.1 для использования в сохраненных программах. Оператор CASE не может иметь ELSE NULL и это закончено END CASE вместо END.

  • IF(expr1, expr2,expr3)

    Если expr1 TRUE (expr1 <> 0 и expr1 <> NULL), то IF() вернет expr2, иначе вернет expr3. IF() возвращает числовое или строковое значение, в зависимости от контекста, в котором используется.

    mysql> SELECT IF(1>2,2,3);
      -> 3
    mysql> SELECT IF(1<2,'yes','no');
      -> 'yes'
    mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
      -> 'no'
    

    Если только один из expr2 или expr3 явно NULL, тип результата функции IF() будет типом выражения не-NULL.

    Тип возврата по умолчанию IF() (который может иметь значение, когда это сохранено во временную таблицу), вычислен следующим образом.

    ВыражениеВозвращаемое значение
    expr2 или expr3 возвращает строкуСтрока
    expr2 или expr3 возвращает значение с плавающей запятой Значение с плавающей запятой
    expr2 или expr3 возвращает целое числоinteger

    Если expr2 и expr3 строки, результат является чувствительным к регистру, если любая строка является чувствительной к регистру.

    Есть также команда IF, которая отличается от функции IF() . См. раздел 14.6.5.2.

  • IFNULL(expr1, expr2)

    Если expr1 не NULL, IFNULL() вернет expr1, иначе expr2. IFNULL() возвращает числовое или строковое значение, в зависимости от контекста, в котором оно используется.

    mysql> SELECT IFNULL(1,0);
      -> 1
    mysql> SELECT IFNULL(NULL,10);
      -> 10
    mysql> SELECT IFNULL(1/0,10);
      -> 10
    mysql> SELECT IFNULL(1/0,'yes');
      -> 'yes'
    

    Значение результата по умолчанию IFNULL(expr1, expr2) более общее из двух выражений в следующем порядке: STRING, REAL или INTEGER. Считайте случай таблицы основанным на выражениях или где MySQL должен внутренне сохранить значение, возвращенное IFNULL() во временной таблице:

    mysql> CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;
    mysql> DESCRIBE tmp;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | test  | varbinary(4) | NO   |     |         |       |
    +-------+--------------+------+-----+---------+-------+
    

    В этом примере тип столбца test VARBINARY(4).

  • NULLIF(expr1, expr2)

    Вернет NULL, если expr1 = expr2 true, иначе вернет expr1. Это то же самое, как CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.

    mysql> SELECT NULLIF(1,1);
      -> NULL
    mysql> SELECT NULLIF(1,2);
      -> 1
    

    Отметьте, что MySQL оценивает expr1 дважды, если параметры не равны.

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.

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

  • ASCII(str)

    Возвращает числовое значение крайнего левого символа строки str . Возвращает 0, если str пустая строка. Возвращает NULL, если str NULL. ASCII() работает для 8-битовых символов.

    mysql> SELECT ASCII('2');
      -> 50
    mysql> SELECT ASCII(2);
      -> 50
    mysql> SELECT ASCII('dx');
      -> 100
    
  • BIN(N)

    Возвращает строковое представление двоичного значения N, где N число типа longlong (BIGINT). Это эквивалентно CONV(N , 10, 2). Вернет NULL, если N NULL.

    mysql> SELECT BIN(12);
        -> '1100'
    
  • BIT_LENGTH(str )

    Возвращает длину строки str в битах.

    mysql> SELECT BIT_LENGTH('text');
        -> 32
    
  • CHAR(N,... [USING charset_name])

    CHAR() интерпретирует каждый параметр N как integer и возвращает строку, состоящую из символов, данных кодовыми обозначениями тех целых чисел. NULL пропущены.

    mysql> SELECT CHAR(77,121,83,81,'76');
      -> 'MySQL'
    mysql> SELECT CHAR(77,77.3,'77.3');
      -> 'MMM'
    

    Параметры CHAR(), больше чем 255, преобразованы в многобайтные результаты. Например, CHAR(256) аналог CHAR(1,0), а CHAR(256*256) аналог CHAR(1,0,0):

    mysql> SELECT HEX(CHAR(1,0)), HEX(CHAR(256));
    +----------------+----------------+
    | HEX(CHAR(1,0)) | HEX(CHAR(256)) |
    +----------------+----------------+
    | 0100           | 0100           |
    +----------------+----------------+
    
    mysql> SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));
    +------------------+--------------------+
    | HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) |
    +------------------+--------------------+
    | 010000           | 010000             |
    +------------------+--------------------+
    

    По умолчанию CHAR() возвращает двоичную строку. Чтобы произвести строку в заданном наборе символов, используйте дополнительное определение USING:

    mysql> SELECT CHARSET(CHAR(X'65')), CHARSET(CHAR(X'65' USING utf8));
    +----------------------+---------------------------------+
    | CHARSET(CHAR(X'65')) | CHARSET(CHAR(X'65' USING utf8)) |
    +----------------------+---------------------------------+
    | binary               | utf8                            |
    +----------------------+---------------------------------+
    

    Если USING задан, а строка результата незаконна для данного набора символов, выдается предупреждение. Кроме того, если строгий режим SQL включен, результатом CHAR() будет NULL.

  • CHAR_LENGTH(str )

    Возвращает длину строки str в символах. Мультибайтный символ считается единственным символом. Это означает, что для строки, содержащей пять 2-байтовых символов, LENGTH() вернет 10, а CHAR_LENGTH() 5.

  • CHARACTER_LENGTH( str)

    CHARACTER_LENGTH() синоним для CHAR_LENGTH().

  • CONCAT(str1, str2,...)

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

    CONCAT() вернет NULL, если какой-либо параметр NULL.

    mysql> SELECT CONCAT('My', 'S', 'QL');
        -> 'MySQL'
    mysql> SELECT CONCAT('My', NULL, 'QL');
        -> NULL
    mysql> SELECT CONCAT(14.3);
        -> '14.3'
    

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

    mysql> SELECT 'My' 'S' 'QL';
        -> 'MySQL'
    
  • CONCAT_WS(separator ,str1,str2,...)

    CONCAT_WS() специальная форма CONCAT() . Первый параметр разделитель для остальной части параметров. Разделитель добавлен между строками, которые будут связаны. Разделитель может быть строкой. Если разделитель NULL, результат NULL.

    mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name');
        -> 'First name,Second name,Last Name'
    mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name');
        -> 'First name,Last Name'
    

    CONCAT_WS() не пропускает пустые строки. Однако, это действительно пропускает любой NULL после параметра разделителя.

  • ELT(N, str1,str2, str3,...)

    ELT() вернет N-ый списка строк: str1, если N = 1, str2, если N = 2 и т.д. NULL, если N меньше 1 или больше, чем число параметров. ELT() дополнение FIELD().

    mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
      -> 'ej'
    mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
      -> 'foo'
    
  • EXPORT_SET(bits ,on,off[, separator[,number_of_bits]])

    Возвращает строку, где для каждого установленного бита в значении bits будет значение on, а для каждого не установленного off. Биты в bits исследованы справа налево (от младшего разряда до старшего). Строки добавлены к результату слева направо и отделены параметром separator (значение по умолчанию: символ запятой ,). Числом исследуемых битов задано number_of_bits, по умолчанию 64, если не определено. number_of_bits тихо усечено до 64, если больше, чем 64. Это обработано как целое число без знака, таким образом, значение -1 является эффективно тем же самым, что и 64.

    mysql> SELECT EXPORT_SET(5,'Y','N',',',4);
        -> 'Y,N,Y,N'
    mysql> SELECT EXPORT_SET(6,'1','0',',',10);
        -> '0,1,1,0,0,0,0,0,0,0'
    
  • FIELD(str, str1,str2,str3 ,...)

    Возвращает индекс (позицию) str в списке str1, str2, str3, .... 0, если str не найдена.

    Если все параметры FIELD() строки, все параметры сравнены как строки. Если все параметры числа, они сравнены как числа. Иначе, параметры сравнены как double.

    Если str NULL, вернет 0 потому, что NULL подводит сравнение равенства с любым значением. FIELD() дополняет ELT().

    mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 2
    mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 0
    
  • FIND_IN_SET(str ,strlist)

    Возвращает значение в диапазоне от 1 до N, если строка str находится в строковом списке strlist из N подстрок. Строковый список это строка, составленная из подстрок, отделенных символом ,. Если первый параметр постоянная строка, а вторым является столбец типа SET, функция FIND_IN_SET() оптимизирована, чтобы использовать разрядную арифметику. Возвращает 0, если str не в strlist или strlist пустая строка. Возвращает NULL, если любой параметр NULL. Эта функция не работает должным образом, если первый параметр содержит запятую (,).

    mysql> SELECT FIND_IN_SET('b','a,b,c,d');
      -> 2
    
  • FORMAT(X, D[,locale])

    Форматирует число X как '#,###,###.##', округляя к D десятичных разрядов и возвращая результат как строку. Если D 0, у результата нет никакой десятичной запятой или дробной части.

    Дополнительный третий параметр позволяет определить локаль, из которой брать символы для десятичной запятой, разделителя тысяч и групп. Допустимые значения такие же, как и для системной переменной lc_time_names (см. раздел 11.7). Если локаль не определена, значение по умолчанию 'en_US'.

    mysql> SELECT FORMAT(12332.123456, 4);
      -> '12,332.1235'
    mysql> SELECT FORMAT(12332.1,4);
      -> '12,332.1000'
    mysql> SELECT FORMAT(12332.2,0);
      -> '12,332'
    mysql> SELECT FORMAT(12332.2,2,'de_DE');
      -> '12.332,20'
    
  • FROM_BASE64(str )

    Берет строку, закодированную base-64 (например, с помощью TO_BASE64()) и возвращает расшифрованный результат как двоичную строку. Результат NULL, если параметр NULL или не допустимая строка base-64. См. описание TO_BASE64().

    mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc'));
        -> 'JWJj', 'abc'
    
  • HEX(str) , HEX(N)

    Для строкового параметра str, HEX() возвращает шестнадцатеричное строковое представление str, где каждый байт каждого символа в str преобразован в две шестнадцатеричных цифры. Мультибайтные символы поэтому становятся больше, чем двумя цифрами. Инверсия этой работы выполнена функцией UNHEX().

    Для числового параметра N, HEX() возвращает шестнадцатеричное строковое представление значения N как число longlong (BIGINT). Это эквивалентно CONV(N,10,16) . Инверсия этой работы выполнена CONV(HEX(N), 16,10).

    mysql> SELECT X'616263', HEX('abc'), UNHEX(HEX('abc'));
        -> 'abc', 616263, 'abc'
    mysql> SELECT HEX(255), CONV(HEX(255),16,10);
        -> 'FF', 255
    
  • INSERT(str, pos,len,newstr )

    Возвращает строку str с подстрокой, начинающейся в позиции pos и len символов длиной замененных строкой newstr. Возвращает оригинальную строку, если pos не в пределах длины строки. Заменяет остаток строки с позиции pos, если len не в пределах длины остальной части строки. Возвращает NULL, если какой-либо параметр NULL.

    mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
        -> 'QuWhattic'
    mysql> SELECT INSERT('Quadratic', -1, 4, 'What');
        -> 'Quadratic'
    mysql> SELECT INSERT('Quadratic', 3, 100, 'What');
        -> 'QuWhat'
    

    Нормально работает с мультибайтными символами.

  • INSTR(str, substr)

    Возвращает позицию первого возникновения подстроки substr в строке str. Это то же самое, что и форма с двумя параметрами LOCATE(), за исключением того, что порядок параметров полностью изменен.

    mysql> SELECT INSTR('foobarbar', 'bar');
        -> 4
    mysql> SELECT INSTR('xbar', 'foobar');
        -> 0
    

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

  • LCASE(str)

    LCASE() синоним для LOWER().

    LCASE() используемая в представлении переписана как LOWER() при сохранении определения представления (Bug #12844279).

  • LEFT(str, len)

    Возвращает крайние левые len символы строки str или NULL, если какой-либо параметр NULL.

    mysql> SELECT LEFT('foobarbar', 5);
        -> 'fooba'
    

    Нормально работает с мультибайтными символами.

  • LENGTH(str)

    Возвращает длину строки str в байтах. Мультибайтный символ считается несколькими байтами. Это означает, что для строки, содержащей пять 2-байтовых символов, LENGTH() вернет 10, а CHAR_LENGTH() 5.

    mysql> SELECT LENGTH('text');
        -> 4
    

    Пространственная функция Length() OpenGIS называется ST_Length() в MySQL.

  • LOAD_FILE(file_name )

    Читает файл и возвращает содержание файла как строку. Чтобы использовать эту функцию, файл должен быть расположен на хосте сервера, Вы должны определить полный путь к файлу и иметь привилегию FILE. Файл должен быть читаемым всеми и его размер меньше, чем max_allowed_packet байт. Если системная переменная secure_file_priv установлена в непустое имя каталога, файл, который будет загружен, должен быть расположен в том каталоге.

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

    Системная переменная character_set_filesystem управляет интерпретацией имен файлов, которые даны как буквальные строки.

    mysql> UPDATE t SET blob_col=LOAD_FILE('/tmp/picture') WHERE id=1;
    
  • LOCATE(substr ,str), LOCATE(substr ,str,pos)

    Первый синтаксис возвращает позицию первого возникновения подстроки substr в str. Второй синтаксис возвращает позицию первого возникновения подстроки substr в str, начиная с позиции pos. Вернет 0, если substr нет в str. Вернет NULL, если какой-либо параметр NULL.

    mysql> SELECT LOCATE('bar', 'foobarbar');
      -> 4
    mysql> SELECT LOCATE('xbar', 'foobar');
      -> 0
    mysql> SELECT LOCATE('bar', 'foobarbar', 5);
      -> 7
    

    Функция является чувствительной к регистру, только если по крайней мере один параметр двоичная строка.

  • LOWER(str)

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

    mysql> SELECT LOWER('QUADRATICALLY');
      -> 'quadratically'
    

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

    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                          |
    +-------------+-----------------------------------+
    

    Для сопоставлений наборов символов Unicode LOWER() и UPPER() работают согласно Unicode Collation Algorithm (UCA) в версии для имени сопоставления, если оно задано, и UCA 4.0.0, если версия не указана. Например, utf8mb4_0900_ai_ci и utf8_unicode_520_ci работают согласно UCA 9.0.0 и 5.2.0, соответственно, тогда как utf8_unicode_ci работает по UCA 4.0.0. См. раздел 11.1.10.1.

    LCASE(), используемая в пределах представлений, переписана как LOWER().

  • LPAD(str, len,padstr)

    Возвращает строку str, доплненную слева строкой padstr до длины len символов. Если str длинней, чем len, возвращаемое значение сокращено до len символов.

    mysql> SELECT LPAD('hi',4,'??');
      -> '??hi'
    mysql> SELECT LPAD('hi',1,'??');
      -> 'h'
    
  • LTRIM(str)

    Возвращает строку str из которой удалены лидирующие пробелы.

    mysql> SELECT LTRIM('  barbar');
        -> 'barbar'
    
  • MAKE_SET(bits , str1, str2, ...)

    Возвращает значение набора (строка, содержащая подстроки, отделенные ,) состоящее из строк, у которых есть соответствующий бит в bits. str1 соответствует биту 0, str2 1 и т.д. Значения NULL в str1, str2, ... не добавлены к результату.

    mysql> SELECT MAKE_SET(1,'a','b','c');
      -> 'a'
    mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
      -> 'hello,world'
    mysql> SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world');
      -> 'hello'
    mysql> SELECT MAKE_SET(0,'a','b','c');
      -> ''
    
  • MID(str, pos,len)

    MID(str, pos,len) синоним для SUBSTRING(str ,pos,len).

  • OCT(N)

    Возвращает строковое представление октального значения N, где N число longlong (BIGINT). Это эквивалентно CONV( N,10,8). Вернет NULL, если N NULL.

    mysql> SELECT OCT(12);
      -> '14'
    
  • OCTET_LENGTH(str )

    OCTET_LENGTH() синоним для LENGTH().

  • ORD(str)

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

      (1st byte code)
    + (2nd byte code * 256)
    + (3rd byte code * 2562) ...
    

    Если крайний левый символ однобайтный, ORD() возвращает то же самое значение, как функция ASCII().

    mysql> SELECT ORD('2');
        -> 50
    
  • POSITION(substr IN str)

    POSITION(substr IN str) синоним для LOCATE(substr ,str).

  • QUOTE(str)

    Заключает строку в кавычки, чтобы привести к результату, который может использоваться в качестве должным образом составленного значения данных в запросе SQL. Строка заключается в одинарные кавычки, каждый экземпляр обратного слэша (\), одинарной кавычки ('), ASCII NUL и Control+Z предваряются наклонной чертой влево. Если параметр NULL, возвращаемое значение слово NULL без одинарных кавычек.

    mysql> SELECT QUOTE('Don\'t!');
      -> 'Don\'t!'
    mysql> SELECT QUOTE(NULL);
      -> NULL
    

    Для сравнения, см. правила заключения в кавычки для буквальных строк и в C API в разделах 10.1.1 и 25.8.7.56.

  • REPEAT(str, count)

    Возвращает строку, состоящую из строки str, повторенной count раз. Если count меньше 1, вернется пустая строка. Вернет NULL, если str или count NULL.

    mysql> SELECT REPEAT('MySQL', 3);
      -> 'MySQLMySQLMySQL'
    
  • REPLACE(str, from_str,to_str)

    Возвращает строку str, в которой все вхождения from_str заменены строкой to_str. REPLACE() выполняет чувствительное к регистру соответствие, ища from_str.

    mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
      -> 'WwWwWw.mysql.com'
    
  • REVERSE(str)

    Возвращает строку str, у которой порядок символов перевернут.

    mysql> SELECT REVERSE('abc');
      -> 'cba'
    
  • RIGHT(str, len)

    Возвращает самые правые len символы строки characters from the string str или NULL, если какой-либо параметр NULL.

    mysql> SELECT RIGHT('foobarbar', 4);
      -> 'rbar'
    
  • RPAD(str, len,padstr)

    Возвращает строку str, к которой справа добавлена padstr до длины в len символов. Если str длинней len, возвращаемое значение сокращено до len символов.

    mysql> SELECT RPAD('hi',5,'?');
      -> 'hi???'
    mysql> SELECT RPAD('hi',1,'?');
      -> 'h'
    
  • RTRIM(str)

    Возвращает строку str с удаленными символами конечного пробела.

    mysql> SELECT RTRIM('barbar   ');
      -> 'barbar'
    
  • SOUNDEX(str)

    Возвращает строку soundex из str. У двух строк, которые кажутся почти теми же самыми, должны быть идентичные строки soundex. Стандарт soundex строка имеет длину 4 байта, но функция SOUNDEX() возвращает произвольно длинную строку. Вы можете использовать SUBSTRING() на результате, чтобы получить стандартную soundex-строку. Все небуквенные символы в str проигнорированы. Все международные буквенные символы вне диапазона A-Z обработаны как гласные.

    Используя SOUNDEX(), Вы должны знать о следующих ограничениях:

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

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

      Мы надеемся удалить эти ограничения в будущем выпуске. См. Bug #22638.

    mysql> SELECT SOUNDEX('Hello');
      -> 'H400'
    mysql> SELECT SOUNDEX('Quadratically');
      -> 'Q36324'
    

    Эта функция осуществляет оригинальный алгоритм Soundex, а не более популярную улучшенную версию (также описанный D. Knuth). Различие в том, что оригинальная версия отказывается от первой гласной и дублирует вторую, тогда как улучшенная пропускает дубликаты первой и второй гласной.

  • expr1 SOUNDS LIKE expr2

    Аналог SOUNDEX(expr1 ) = SOUNDEX(expr2).

  • SPACE(N)

    Возвращает строку, состоящую из N пробелов.

    mysql> SELECT SPACE(6);
        -> '      '
    
  • SUBSTR(str, pos), SUBSTR(str FROM pos), SUBSTR(str, pos,len), SUBSTR(str FROM pos FOR len)

    SUBSTR() синоним для SUBSTRING().

  • SUBSTRING(str ,pos), SUBSTRING(str FROM pos), SUBSTRING(str ,pos,len), SUBSTRING(str FROM pos FOR len)

    Формы без len возвращают подстроку из str, начиная с позиции pos. Формы с len возвращают подстроку длиной len символов из str, начиная с позиции pos. Формы, которые используют FROM, это стандартный синтаксис SQL. Также возможно использовать отрицательную величину для pos. В этом случае подстрока начинается с pos символа от конца строки, а не начала. Отрицательная величина может использоваться для pos в любой из форм этой функции.

    Для всех форм SUBSTRING() позицию первого символа в строке, из которой должна быть извлечена подстрока, считают как 1.

    mysql> SELECT SUBSTRING('Quadratically',5);
      -> 'ratically'
    mysql> SELECT SUBSTRING('foobarbar' FROM 4);
      -> 'barbar'
    mysql> SELECT SUBSTRING('Quadratically',5,6);
      -> 'ratica'
    mysql> SELECT SUBSTRING('Sakila', -3);
      -> 'ila'
    mysql> SELECT SUBSTRING('Sakila', -5, 3);
      -> 'aki'
    mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
      -> 'ki'
    

    Если len меньше 1, результат пустая строка.

  • SUBSTRING_INDEX( str,delim,count)

    Возвращает подстроку из строки str до count возникновения разделителя delim. Если count положительно, возвращено все слева от заключительного разделителя (счет слева направо). Если count отрицательно, возвращено все справа от заключительного разделителя (считая справа). SUBSTRING_INDEX() выполняет чувствительное к регистру соответствие, ища delim.

    mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
      -> 'www.mysql'
    mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
      -> 'mysql.com'
    
  • TO_BASE64(str )

    Преобразовывает строковый параметр в base-64 и возвращает результат как строку символов с набором символов соединения и сопоставлением. Если параметр не строка, он преобразован в строку прежде, чем преобразование будет иметь место. Результат NULL если параметр NULL. Строки Base-64 могут быть расшифрованы, используя функцию FROM_BASE64().

    mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc'));
      -> 'JWJj', 'abc'
    

    Существуют различные схемы кодировки Base 64. TO_BASE64() и FROM_BASE64() используют следующие правила:

    • Кодирование для алфавитного значения 62 '+'.

    • Кодирование для алфавитного значения 63 '/'.
    • Закодированный вывод состоит из групп по 4 пригодных для печати символа. Каждый 3 байта входных данных закодированы, используя 4 символа. Если последняя группа является неполной, она дополнена символами '=' до длины 4.
    • Новая строка добавлена после каждого 76 символа закодированного вывода, чтобы делить длинный на много строк.
    • Расшифровка признает и игнорирует новую строку, возврат каретки, табуляцию и пробел.

  • TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr FROM] str)

    Возвращает строку str со всеми удаленными префиксами или суффиксами remstr. Если ни один из спецификаторов BOTH, LEADING или TRAILING не задан, предполагается BOTH. remstr является дополнительной и, если не определена, будут удалены пробелы.

    mysql> SELECT TRIM('  bar   ');
      -> 'bar'
    mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
      -> 'barxxx'
    mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
      -> 'bar'
    mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
      -> 'barx'
    
  • UCASE(str)

    UCASE() синоним для UPPER().

    UCASE(), используемая в пределах представлений переписана как UPPER().

  • UNHEX(str)

    Для строкового параметра str UNHEX(str) интерпретирует каждую пару символов в параметре как шестнадцатеричное число и преобразовывает это в байт, представленный числом. Возвращаемое значение двоичная строка.

    mysql> SELECT UNHEX('4D7953514C');
        -> 'MySQL'
    mysql> SELECT X'4D7953514C';
        -> 'MySQL'
    mysql> SELECT UNHEX(HEX('string'));
        -> 'string'
    mysql> SELECT HEX(UNHEX('1267'));
        -> '1267'
    

    Символы в строке параметра должны быть шестнадцатеричными цифрами: '0' .. '9', 'A' .. 'F', 'a' .. 'f'. Если параметр содержит какие-либо нешестнадцатеричные цифры, результат NULL:

    mysql> SELECT UNHEX('GG');
    +-------------+
    | UNHEX('GG') |
    +-------------+
    | NULL        |
    +-------------+
    

    Результат NULL может произойти, если параметр UNHEX() столбец BINARY, потому что значения дополнены байтами 0x00 когда сохранены, но эти байты при извлечении не удаляются. Например, '41' сохранена в столбце CHAR(3) как '41 ' и получена как '41' (без хвостового пробела, таким образом UNHEX() для значения столбца вернет 'A'. При сохранении '41' в столбец BINARY(3) сохранится и вернется '41\0' (0x00 в конце останется). '\0' не шестнадцатеричная цифра, таким образом, UNHEX() для значения столбца вернет NULL.

    Для числового параметра N, инверсия HEX(N) не выполнена UNHEX() . Используйте CONV(HEX( N), 16, 10).

  • UPPER(str)

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

    mysql> SELECT UPPER('Hej');
      -> 'HEJ'
    

    UCASE(), используемая в пределах представлений, переписана как UPPER().

  • WEIGHT_STRING(str [AS {CHAR|BINARY}(N)] [LEVEL levels] [flags])

    levels: N [ASC|DESC|REVERSE] [, N [ASC|DESC|REVERSE]] ...

    Эта функция возвращает строку веса для строки ввода. Возвращаемое значение двоичная строка, которая представляет сравнение и значение сортировки строки. У нее есть эти свойства:

    WEIGHT_STRING() может использоваться для тестирования и отладки сопоставлений, особенно если Вы добавляете новое сопоставление. См. раздел 11.4.

    Строка ввода str это строковое выражение. Если ввод недвоичная (символьная) строка, такая как CHAR, VARCHAR или TEXT, возвращаемое значение содержит вес сопоставления для строки. Если ввод двоичная строка, такая как BINARY, VARBINARY или BLOB, возвращаемое значение то же самое, как и ввод (вес для каждого байта в двоичной строке это значение байта). Если ввод NULL, WEIGHT_STRING() тоже вернет NULL. Например:

    mysql> SET @s = _latin1 'AB' COLLATE latin1_swedish_ci;
    mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
    +----+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +----+---------+------------------------+
    | AB | 4142    | 4142                   |
    +----+---------+------------------------+
    
    mysql> SET @s = _latin1 'ab' COLLATE latin1_swedish_ci;
    mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
    +----+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +----+---------+------------------------+
    | ab | 6162    | 4142                   |
    +----+---------+------------------------+
    
    mysql> SET @s = CAST('AB' AS BINARY);
    mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
    +----+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +----+---------+------------------------+
    | AB | 4142    | 4142                   |
    +----+---------+------------------------+
    
    mysql> SET @s = CAST('ab' AS BINARY);
    mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
    +----+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +----+---------+------------------------+
    | ab | 6162    | 6162                   |
    +----+---------+------------------------+
    

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

    mysql> SET @s = CONVERT(X'C39F' USING utf8) COLLATE utf8_czech_ci;
    mysql> SELECT HEX(WEIGHT_STRING(@s));
    +------------------------+
    | HEX(WEIGHT_STRING(@s)) |
    +------------------------+
    | 0FEA0FEA               |
    +------------------------+
    

    Для возвращаемых значений не-NULL тип данных значения VARBINARY, если его длина в пределах максимальной длины для VARBINARY, иначе тип данных BLOB.

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

    • AS CHAR(N) приводит строку к недвоичной строке и дополняет справа пробелами до длины N символов. N должен быть по крайней мере 1. Если N меньше, чем длина строки ввода, строка будет усечена до N символов. Никакого предупреждения не происходит для усечения.

    • AS BINARY(N) подобно, но приводит строку к двоичной строке N измерен в байтах (не символах!), и дополнение использует байт 0x00 (не пробелы!).

    mysql> SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4)));
    +-------------------------------------+
    | HEX(WEIGHT_STRING('ab' AS CHAR(4))) |
    +-------------------------------------+
    | 41422020                            |
    +-------------------------------------+
    
    mysql> SELECT HEX(WEIGHT_STRING('ab' AS BINARY(4)));
    +---------------------------------------+
    | HEX(WEIGHT_STRING('ab' AS BINARY(4))) |
    +---------------------------------------+
    | 61620000                              |
    +---------------------------------------+
    

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

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

    Примеры:

    LEVEL 1
    LEVEL 2, 3, 5
    LEVEL 1-3
    

    Любой уровень меньше 1 обработан как 1. Любой уровень больше, чем максимум для сопоставления строки ввода, обработан как максимум для сопоставления. Максимум изменяется в зависимости от сопоставление, но никогда не больше 6.

    В списке уровни должны быть даны в увеличивающемся порядке. В диапазоне уровней, если второе число меньше, чем первое, оно обработано как первое число (например, 4-2 то же самое, что и 4-4).

    Если пропущен LEVEL, MySQL принимает LEVEL 1 - max, где max максимальный уровень для сопоставления.

    Если LEVEL определен, используя синтаксис списка (не диапазон), любое число уровня может сопровождаться этими модификаторами:

    • ASC: Возвратить веса без модификации. Это значение по умолчанию.

    • DESC: Вернуть поразрядно инвертированные веса (например, 0x78f0 DESC = 0x870f).
    • REVERSE: Вернуть веса в обратном порядке (то есть, веса для полностью измененной строки, с первым символом на последнем месте).

    Примеры:

    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1));
    +--------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1)) |
    +--------------------------------------+
    | 007FFF                               |
    +--------------------------------------+
    
    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC));
    +-------------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC)) |
    +-------------------------------------------+
    | FF8000                                    |
    +-------------------------------------------+
    
    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1 REVERSE));
    +----------------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1 REVERSE)) |
    +----------------------------------------------+
    | FF7F00                                       |
    +----------------------------------------------+
    
    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC REVERSE));
    +---------------------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC REVERSE)) |
    +---------------------------------------------------+
    | 0080FF                                            |
    +---------------------------------------------------+
    

    flags в настоящее время не используется.

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

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

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

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

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

  • expr LIKE pat [ESCAPE 'escape_char ']

    Соответствие образца, используя образец SQL. Возвращает 1 (TRUE) или 0 (FALSE). Если expr или pat NULL, результат NULL.

    Образец не должен быть буквальной строкой. Например, это может быть определено как строковое выражение или столбец таблицы.

    По стандарту SQL LIKE выполняет соответствие на посимвольном основании, таким образом это может привести к результатам, отличающимся от оператора сравнения =:

    mysql> SELECT 'ц╓' LIKE 'ae' COLLATE latin1_german2_ci;
    +-----------------------------------------+
    | 'ц╓' LIKE 'ae' COLLATE latin1_german2_ci |
    +-----------------------------------------+
    |   0                                     |
    +-----------------------------------------+
    
    mysql> SELECT 'ц╓' = 'ae' COLLATE latin1_german2_ci;
    +--------------------------------------+
    | 'ц╓' = 'ae' COLLATE latin1_german2_ci |
    +--------------------------------------+
    | 1                                    |
    +--------------------------------------+
    

    В частности конечные пробелы являются существенными, что неверно для сравнения CHAR или VARCHAR с помощью =:

    mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';
    +------------+---------------+
    | 'a' = 'a ' | 'a' LIKE 'a ' |
    +------------+---------------+
    | 1          |   0           |
    +------------+---------------+
    1 row in set (0.00 sec)
    

    С LIKE Вы можете использовать следующие два подстановочных символа в образце:

    • % соответствует любому числу символов, даже нулевых.

    • _ соответствует точно одному символу.

    mysql> SELECT 'David!' LIKE 'David_';
      -> 1
    mysql> SELECT 'David!' LIKE '%D%v%';
      -> 1
    

    Чтобы проверить на буквальные случаи подстановочного символа, поставьте перед ним символ экранирования. Если Вы не определяете символ ESCAPE, по умолчанию используется \.

    • \% соответствует одному символу %.

    • \_ соответствует одному символу _.

    mysql> SELECT 'David!' LIKE 'David\_';
      -> 0
    mysql> SELECT 'David_' LIKE 'David\_';
      -> 1
    

    Чтобы определить иной символ ESC, используйте определение ESCAPE:

    mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
      -> 1
    

    Escape-последовательность должна быть пустой или одним символом. Выражение должно оцениваться как константа во время выполнения. Если режим SQL NO_BACKSLASH_ESCAPES включен, последовательность не может быть пустой.

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

    mysql> SELECT 'abc' LIKE 'ABC';
      -> 1
    mysql> SELECT 'abc' LIKE _latin1 'ABC' COLLATE latin1_general_cs;
      -> 0
    mysql> SELECT 'abc' LIKE _latin1 'ABC' COLLATE latin1_bin;
      -> 0
    mysql> SELECT 'abc' LIKE BINARY 'ABC';
      -> 0
    

    Как расширение к стандартному SQL, MySQL допускает LIKE по числовым выражениям.

    mysql> SELECT 10 LIKE '1%';
        -> 1
    

    Поскольку MySQL использует синтаксис escape C в строках (например, \n кодирует символ новой строки), Вы должны удвоить любой \, который используете в строке LIKE. Например, чтобы искать \n, укажите \\n. Чтобы искать \, определите это как \\\\, это потому что наклонные черты влево обрезаны сначала анализатором, а потом когда соответствие образца сделано, оставляя единственную наклонную черту влево, которая будет соответствующей.

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

    mysql> SELECT filename FROM t1;
    +--------------+
    | filename     |
    +--------------+
    | C:           |
    | C:\          |
    | C:\Programs  |
    | C:\Programs\ |
    +--------------+
    

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

    mysql> SELECT filename, filename LIKE '%\\' FROM t1;
    +--------------+---------------------+
    | filename     | filename LIKE '%\\' |
    +--------------+---------------------+
    | C:           |   0                 |
    | C:\          |   1                 |
    | C:\Programs  |   0                 |
    | C:\Programs\ |   1                 |
    +--------------+---------------------+
    
    mysql> SELECT filename, filename LIKE '%\\\\' FROM t1;
    +--------------+-----------------------+
    | filename     | filename LIKE '%\\\\' |
    +--------------+-----------------------+
    | C:           | 0                     |
    | C:\          | 1                     |
    | C:\Programs  | 0                     |
    | C:\Programs\ | 1                     |
    +--------------+-----------------------+
    
  • expr NOT LIKE pat [ESCAPE 'escape_char']

    Это аналогично NOT (expr LIKE pat [ESCAPE 'escape_char']) .

    Совокупное вовлечение запросов NOT LIKE сравнения со столбцами, содержащими NULL может привести к неожиданным результатам. Например, рассмотрите следующую таблицу и данные:

    CREATE TABLE foo (bar VARCHAR(10));
    INSERT INTO foo VALUES (NULL), (NULL);
    

    Запрос SELECT COUNT(*) FROM foo WHERE bar LIKE '%baz%'; вернет 0. Вы могли бы принять, что SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%'; должен вернуть 2. Однако, дело обстоит не так: второй запрос вернет 0. Это потому, что NULL NOT LIKE expr всегда возвращает NULL, независимо от значения expr. То же самое истина для совокупного вовлечения запросов NULL и использования сравнений NOT RLIKE или NOT REGEXP. В таких случаях Вы должны проверить явно на NOT NULL с помощью OR (но не AND):

    SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%' OR bar IS NULL;
    
  • STRCMP(expr1, expr2)

    STRCMP() вернет 0, если строки одинаковы, -1, если первый параметр меньше второго, согласно текущему порядку сортировки, иначе 1.

    mysql> SELECT STRCMP('text', 'text2');
      -> -1
    mysql> SELECT STRCMP('text2', 'text');
      -> 1
    mysql> SELECT STRCMP('text', 'text');
      -> 0
    

    STRCMP() выполняет сравнение, используя сопоставление параметров.

    mysql> SET @s1 = _latin1 'x' COLLATE latin1_general_ci;
    mysql> SET @s2 = _latin1 'X' COLLATE latin1_general_ci;
    mysql> SET @s3 = _latin1 'x' COLLATE latin1_general_cs;
    mysql> SET @s4 = _latin1 'X' COLLATE latin1_general_cs;
    mysql> SELECT STRCMP(@s1, @s2), STRCMP(@s3, @s4);
    +------------------+------------------+
    | STRCMP(@s1, @s2) | STRCMP(@s3, @s4) |
    +------------------+------------------+
    | 0                |     1            |
    +------------------+------------------+
    

    Если сопоставления являются несовместимыми, один из параметров должен быть преобразован, чтобы быть совместимым с другим. См. раздел 11.1.8.4.

    
    mysql> SELECT STRCMP(@s1, @s3);
    ERROR 1267 (HY000): Illegal mix of collations (latin1_general_ci,IMPLICIT)
    and (latin1_general_cs,IMPLICIT) for operation 'strcmp'
    mysql> SELECT STRCMP(@s1, @s3 COLLATE latin1_general_ci);
    +--------------------------------------------+
    | STRCMP(@s1, @s3 COLLATE latin1_general_ci) |
    +--------------------------------------------+
    |  0                                         |
    +--------------------------------------------+
    

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.

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

  • expr NOT REGEXP pat, expr NOT RLIKE pat

    Аналог NOT (expr REGEXP pat).

  • expr REGEXP pat, expr RLIKE pat

    Выполняет соответствие образца строкового выражения expr шаблону pat. Образец может быть расширенным регулярным выражением, синтаксис для которого рассмотрен позже в этом разделе. Возвращает 1, если expr соответствует pat, иначе 0. Если expr или pat NULL, результат NULL. RLIKE синоним для REGEXP для совместимости с mSQL.

    Образец не должен быть буквальной строкой. Например, это может быть определено как строковое выражение или столбец таблицы.

    Поскольку MySQL использует синтаксис escape C в строках (например, \n означает новую строку), Вы должны удвоить любой \, который Вы используете в Вашей строке REGEXP.

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

    mysql> SELECT 'Monty!' REGEXP '.*';
      -> 1
    mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
      -> 1
    mysql> SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';
      -> 1  0
    mysql> SELECT 'a' REGEXP '^[a-d]';
      -> 1
    

    REGEXP и RLIKE используют набор символов и сопоставления параметров, определяя тип символа и выполняя сравнение. Если у параметров есть различные наборы символов или сопоставления, правила применяются как описано в разделе 11.1.8.4.

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

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

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

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

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

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

  • ^

    Соответствует началу строки.

    mysql> SELECT 'fo\nfo' REGEXP '^fo$';
      -> 0
    mysql> SELECT 'fofo' REGEXP '^fo';
      -> 1
    
  • $

    Конец строки.

    mysql> SELECT 'fo\no' REGEXP '^fo\no$';
      -> 1
    mysql> SELECT 'fo\no' REGEXP '^fo$';
      -> 0
    
  • .

    Соответствует любому символу (включая возврат каретки и новую строку).

    mysql> SELECT 'fofo' REGEXP '^f.*$';
      -> 1
    mysql> SELECT 'fo\r\nfo' REGEXP '^f.*$';
      -> 1
    
  • a*

    Соответствует любой последовательности из ноля или больше символов a.

    mysql> SELECT 'Ban' REGEXP '^Ba*n';
      -> 1
    mysql> SELECT 'Baaan' REGEXP '^Ba*n';
      -> 1
    mysql> SELECT 'Bn' REGEXP '^Ba*n';
      -> 1
    
  • a+

    Соответствует любой последовательности из одного или больше символов a.

    mysql> SELECT 'Ban' REGEXP '^Ba+n';
      -> 1
    mysql> SELECT 'Bn' REGEXP '^Ba+n';
      -> 0
    
  • a?

    Соответствует нолю или одному символу a.

    mysql> SELECT 'Bn' REGEXP '^Ba?n';
      -> 1
    mysql> SELECT 'Ban' REGEXP '^Ba?n';
      -> 1
    mysql> SELECT 'Baan' REGEXP '^Ba?n';-> 0
    
  • de|abc

    Соответствует любой из последовательностей de или abc.

    mysql> SELECT 'pi' REGEXP 'pi|apa';
      -> 1
    mysql> SELECT 'axe' REGEXP 'pi|apa';
      -> 0
    mysql> SELECT 'apa' REGEXP 'pi|apa';
      -> 1
    mysql> SELECT 'apa' REGEXP '^(pi|apa)$';
      -> 1
    mysql> SELECT 'pi' REGEXP '^(pi|apa)$';
      -> 1
    mysql> SELECT 'pix' REGEXP '^(pi|apa)$';
      -> 0
    
  • (abc)*

    Соответствует нолю или больше экземпляров последовательности abc.

    mysql> SELECT 'pi' REGEXP '^(pi)*$';
      -> 1
    mysql> SELECT 'pip' REGEXP '^(pi)*$';
      -> 0
    mysql> SELECT 'pipi' REGEXP '^(pi)*$';
      -> 1
    
  • {1}, {2,3}

    Нотация {n} или {m,n} обеспечивает более общий способ написать регулярные выражения, которые соответствуют нескольким возникновениям предыдущего атома (или куска) шаблона. m и n целые числа.

    • a*

      Может быть написан как a{0,}.

    • a+

      Может быть написан как a{1,}.

    • a?

      Может быть написан как a{0,1}.

    Более точно a{n} соответствует n экземплярам a. a{n,} соответствует n или больше экземплярам a. a{m,n} соответствует от m до n экземплярам a, включительно.

    m и n должны быть в диапазоне от 0 до RE_DUP_MAX (значение по умолчанию 255), включительно. Если оба m и n заданы, m должно быть меньше или равным n.

    mysql> SELECT 'abcde' REGEXP 'a[bcd]{2}e';
      -> 0
    mysql> SELECT 'abcde' REGEXP 'a[bcd]{3}e';
      -> 1
    mysql> SELECT 'abcde' REGEXP 'a[bcd]{1,10}e';
      -> 1
    
  • [a-dX], [^a-dX]

    Соответствует любому символу, который является (или нет, если ^ используется), a, b, c, d или X. Символ - между двумя другими символами формирует диапазон, который соответствует всем символам от первого до второго. Например, [0-9] соответствует любой десятичной цифре. Чтобы включить символ ], он должен немедленно следовать за вводной скобкой [. Чтобы включить символ -, он должен быть написан сначала или последним. Любой символ, у которого нет определенного особого значения внутри пары [] соответствует только себе самому.

    mysql> SELECT 'aXbc' REGEXP '[a-dXYZ]';
      -> 1
    mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]$';
      -> 0
    mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]+$';
      -> 1
    mysql> SELECT 'aXbc' REGEXP '^[^a-dXYZ]+$';
      -> 0
    mysql> SELECT 'gheis' REGEXP '^[^a-dXYZ]+$';
      -> 1
    mysql> SELECT 'gheisa' REGEXP '^[^a-dXYZ]+$';
      -> 0
    
  • [.characters.]

    В пределах выражения скобки ([ и ]) соответствует последовательности символов того элемента сопоставления. characters единственный символ или имя символа, например, newline. Следующая таблица приводит допустимые имена.

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

    ИмяСимвол ИмяСимвол
    NUL0 SOH001
    STX002 ETX003
    EOT004 ENQ005
    ACK006 BEL007
    alert007 BS010
    backspace'\b' HT011
    tab'\t' LF012
    newline'\n' VT013
    vertical-tab'\v' FF014
    form-feed'\f' CR015
    carriage-return '\r'SO 016
    SI017 DLE020
    DC1021 DC2022
    DC3023 DC4024
    NAK025 SYN026
    ETB027 CAN030
    EM031 SUB032
    ESC033 IS4034
    FS034 IS3035
    GS035 IS2036
    RS036 IS1037
    US037 space' '
    exclamation-mark '!'quotation-mark '"'
    number-sign'#' dollar-sign'$'
    percent-sign'%' ampersand'&'
    apostrophe'\'' left-parenthesis'('
    right-parenthesis ')'asterisk '*'
    plus-sign'+' comma','
    hyphen'-' hyphen-minus'-'
    period'.' full-stop'.'
    slash'/' solidus'/'
    zero'0' one'1'
    two'2' three'3'
    four'4' five'5'
    six'6' seven'7'
    eight'8' nine'9'
    colon':' semicolon';'
    less-than-sign '<'equals-sign '='
    greater-than-sign '>'question-mark '?'
    commercial-at'@' left-square-bracket'['
    backslash'\\' reverse-solidus'\\'
    right-square-bracket ']'circumflex '^'
    circumflex-accent '^'underscore '_'
    low-line'_' grave-accent'`'
    left-brace'{' left-curly-bracket'{'
    vertical-line'|' right-brace'}'
    right-curly-bracket '}'tilde'~'
    DEL177
    mysql> SELECT '~' REGEXP '[[.~.]]';
        -> 1
    mysql> SELECT '~' REGEXP '[[.tilde.]]';
        -> 1
    
  • [=character_class=]

    В пределах выражения скобки ([ и ]) [=character_class=] представляет класс эквивалентности. Это соответствует все символы с тем же самым значением сопоставления, включая себя. Например, если o и (+) члены класса эквивалентности, [[=o=]], [[=(+)=]] и [o(+)] синонимы. Класс эквивалентности не может использоваться в качестве конечной точки диапазона.

  • [:character_class:]

    В пределах выражения скобки ([ и ]) [:character_class:] представляет символьный класс, который соответствует всем символам, принадлежащим этому классу. Следующая таблица приводит стандартные названия классов. Эти имена обозначают символьные классы, определенные в ctype(3). Особое место действия может обеспечить другие названия классов. Символьный класс не может использоваться в качестве конечной точки диапазона.

    Имя класса символовСмысл
    alnumАлфавитно-цифровые символы
    alphaБуквенные символы
    blankПробелы
    cntrlСимволы управления
    digitЦифры
    graphГрафические символы
    lowerСтрочные буквенные символы
    printГрафические символы или пробелы
    punctСимволы пунктуации
    spaceПробел, табуляция, новая строка и возврат каретки
    upper Буквенные символы верхнего регистра
    xdigitШестнадцатеричные цифры
    mysql> SELECT 'justalnums' REGEXP '[[:alnum:]]+'; -> 1
    mysql> SELECT '!!' REGEXP '[[:alnum:]]+'; -> 0
    
  • [[:<:]], [[:>:]]

    Эти маркеры обозначают границы слова. Они соответствуют началу и концу слов, соответственно. Слово последовательность символов слова, которой не предшествуют или сопровождается символами слова. Символ слова буквенно-цифровой знак в классе alnum или подчеркивание (_).

    mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]';
        -> 1
    mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]';
        -> 0
    

Чтобы использовать буквальный случай специального символа в регулярном выражении, предварите его двумя наклонными чертами влево (\\). Анализатор 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 для определения сопоставления результата:

  • Если есть явное COLLATE Y, использовать Y.

  • Если есть явное COLLATE Y и COLLATE Z, выдать ошибку.
  • Иначе, если все сопоставления Y, использовать Y.
  • Иначе у результата нет никакого сопоставления.

Например, с 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Модуль
+ Оператор "+"
* Умножение
- Меняет знак аргумента

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

  • В случае -, + и *, результат вычислен с точностью BIGINT (64-bit), если оба операнда целые числа.

  • Если оба операнда целые числа и любой из них без знака результат целое число без знака. Для вычитания если включен режим SQL NO_UNSIGNED_SUBTRACTION, результат со знаком, даже если какой-либо операнд без знака.
  • Если любой из операндов +, -, /, *, % реальное число или строковое значение, точность результата это точность операнда с максимальной точностью.
  • В делении, выполненном /, масштаб результата, когда использованы два операнда точного значения является масштабом первого операнда плюс значение системной переменной div_precision_increment (по умолчанию 4). Например, результат выражения 5.05/0.014 имеет масштаб шести десятичных разрядов (360.714286).

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

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

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

  • +

    Сложение:

    mysql> SELECT 3+5;
      -> 8
    
  • -

    Вычитание:

    mysql> SELECT 3-5;
      -> -2
    
  • -

    Одноместный минус. Этот оператор изменяет знак операнда.

    mysql> SELECT - 2;
      -> -2
    

    Если этот оператор используется с BIGINT, возвращаемое значение также BIGINT . Это означает, что Вы должны избегать использования - на целых числах, у которых может быть значение 263.

  • *

    Умножение:

    mysql> SELECT 3*5;
      -> 15
    mysql> SELECT 18014398509481984*18014398509481984.0;
      -> 324518553658426726783156020576256.0
    mysql> SELECT 18014398509481984*18014398509481984;
      -> out-of-range error
    

    Последнее выражение производит ошибку, потому что результат умножения целого числа превышает 64-битный диапазон BIGINT. См. раздел 12.2.

  • /

    Деление:

    mysql> SELECT 3/5;
      -> 0.60
    

    Деление на ноль вернет NULL:

    mysql> SELECT 102/(1-1);
      -> NULL
    

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

  • DIV

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

    Если у любого операнда есть тип нецелого числа, операнды преобразованы в DECIMAL и делятся с использованием арифметики DECIMAL прежде, чем преобразовать результат в BIGINT. Если результат превышает диапазон BIGINT, будет ошибка.

    mysql> SELECT 5 DIV 2, -5 DIV 2, 5 DIV -2, -5 DIV -2;
      -> 2, -2, -2, 2
    
  • N % M, N MOD M

    Остаток. Возвращает остаток от деления N на M.

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 в случае ошибки.

  • ABS(X)

    Возвращает абсолютное значение X.

    mysql> SELECT ABS(2);
        -> 2
    mysql> SELECT ABS(-32);
        -> 32
    

    Эту функцию безопасно использовать с BIGINT.

  • ACOS(X)

    Возвращает арккосинус X то есть, значение, косинус которого X. Вернет NULL, если X не находится в диапазоне от -1 до 1.

    mysql> SELECT ACOS(1);
        -> 0
    mysql> SELECT ACOS(1.0001);
        -> NULL
    mysql> SELECT ACOS(0);
        -> 1.5707963267949
    
  • ASIN(X)

    Возвращает арксинус X то есть, значение, синус которого X. Вернет NULL, если X не находится в диапазоне от -1 до 1.

    mysql> SELECT ASIN(0.2);
        -> 0.20135792079033
    mysql> SELECT ASIN('foo');
    +-------------+
    | ASIN('foo') |
    +-------------+
    | 0           |
    +-------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS;
    +---------+------+-----------------------------------------+
    | Level   | Code | Message                                 |
    +---------+------+-----------------------------------------+
    | Warning | 1292 | Truncated incorrect DOUBLE value: 'foo' |
    +---------+------+-----------------------------------------+
    
  • ATAN(X)

    Возвращает арктангенс X, то есть, значение, тангенс которого X.

    mysql> SELECT ATAN(2);
        -> 1.1071487177941
    mysql> SELECT ATAN(-2);
        -> -1.1071487177941
    
  • ATAN(Y, X), ATAN2(Y, X)

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

    mysql> SELECT ATAN(-2,2);
        -> -0.78539816339745
    mysql> SELECT ATAN2(PI(),0);
        -> 1.5707963267949
    
  • CEIL(X)

    CEIL() синоним для CEILING().

  • CEILING(X)

    Возвращает самое маленькое целочисленное значение не меньше X.

    mysql> SELECT CEILING(1.23);
      -> 2
    mysql> SELECT CEILING(-1.23);
      -> -1
    

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

  • CONV(N, from_base,to_base)

    Конвертирует между различными основаниями системы счисления. Возвращает строковое представление числа N, преобразованного из основы from_base в to_base. Возвращает NULL, если какой-либо параметр NULL. Параметр N интерпретируется как целое число, но может быть определен как целое число или строка. Минимальная основа 2 максимальная 36. Если from_base отрицательное число, N расценено как число со знаком. Иначе N как без знака. CONV() работает с 64-битной точностью.

    mysql> SELECT CONV('a',16,2);
        -> '1010'
    mysql> SELECT CONV('6E',18,8);
        -> '172'
    mysql> SELECT CONV(-17,10,-18);
        -> '-H'
    mysql> SELECT CONV(10+'10'+'10'+X'0a',10,10);
        -> '40'
    
  • COS(X)

    Возвращает косинус X, где X задан в радианах.

    mysql> SELECT COS(PI());
        -> -1
    
  • COT(X)

    Возвращает котангенс X.

    mysql> SELECT COT(12);
        -> -1.5726734063977
    mysql> SELECT COT(0);
        -> NULL
    
  • CRC32(expr)

    Вычисляет значение циклического контроля по избыточности и возвращает 32-битное значение без знака. Результат NULL, если параметр NULL. Параметром, как ожидают, будет строка.

    mysql> SELECT CRC32('MySQL');
        -> 3259397556
    mysql> SELECT CRC32('mysql');
        -> 2501908538
    
  • DEGREES(X)

    Возвращает параметр X, преобразованный из радиан в градусы.

    mysql> SELECT DEGREES(PI());
      -> 180
    mysql> SELECT DEGREES(PI() / 2);
      -> 90
    
  • EXP(X)

    Возвращает значение e (основание натуральных логарифмов), возведенное в степень X. Инверсия этой функции LOG() (с использованием единственного параметра) или LN().

    mysql> SELECT EXP(2);
      -> 7.3890560989307
    mysql> SELECT EXP(-2);
      -> 0.13533528323661
    mysql> SELECT EXP(0);
      -> 1
    
  • FLOOR(X)

    Возвращает самое большое целочисленное значение, не больше X.

    mysql> SELECT FLOOR(1.23), FLOOR(-1.23);
      -> 1, -2
    

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

  • FORMAT(X, D)

    Форматирует число X как '#,###,###.##', округляя до D десятичных разрядов и возвращая результат как строку. Для деталей см. раздел 13.5 .

  • HEX(N_or_S)

    Эта функция может использоваться, чтобы получить шестнадцатеричное представление десятичного числа или строки. Алгоритм изменяется, согласно типу параметра. См. описание этой функции в разделе 13.5.

  • LN(X)

    Возвращает натуральный логарифм X, то есть логарифм X по основанию e. Если X меньше или равно 0.0E0, функция вернет NULL и выдаст предупреждение Invalid argument for logarithm.

    mysql> SELECT LN(2);
      -> 0.69314718055995
    mysql> SELECT LN(-2);
      -> NULL
    

    Эта функция синонимична LOG(X) . Инверсия этой функции EXP() .

  • LOG(X) , LOG(B, X)

    Если вызвана с одним параметром, эта функция возвращает натуральный логарифм X. Если X меньше или равно 0.0E0, функция вернет NULL и выдаст предупреждение Invalid argument for logarithm.

    Инверсия этой функции (когда вызвана с единственным параметром) EXP().

    mysql> SELECT LOG(2);
      -> 0.69314718055995
    mysql> SELECT LOG(-2);
      -> NULL
    

    Если вызвана с двумя параметрами, эта функция возвращает логарифм X по основанию B. Если X меньше или равно 0 или B меньше или равно 1, вернется NULL.

    mysql> SELECT LOG(2,65536);
      -> 16
    mysql> SELECT LOG(10,100);
      -> 2
    mysql> SELECT LOG(1,100);
      -> NULL
    

    LOG(B, X) эквивалентна LOG(X) / LOG(B).

  • LOG2(X)

    Возвращает логарифм X по основанию 2. Если X меньше или равно 0.0E0, функция вернет NULL и выдаст предупреждение Invalid argument for logarithm.

    mysql> SELECT LOG2(65536);
      -> 16
    mysql> SELECT LOG2(-100);
      -> NULL
    

    LOG2() полезна для обнаружения, какое количество битов число требует для хранения. Эта функция эквивалентна выражению LOG(X) / LOG(2).

  • LOG10(X)

    Возвращает логарифм X по основанию 10. Если X меньше или равно 0.0E0, функция вернет NULL и выдаст предупреждение Invalid argument for logarithm.

    mysql> SELECT LOG10(2);
        -> 0.30102999566398
    mysql> SELECT LOG10(100);
        -> 2
    mysql> SELECT LOG10(-100);
        -> NULL
    

    LOG10(X) эквивалентна LOG(10, X).

  • MOD(N, M), N % M, N MOD M

    Возвращает остаток от деления N на M.

    mysql> SELECT MOD(234, 10);
      -> 4
    mysql> SELECT 253 % 7;
      -> 1
    mysql> SELECT MOD(29,9);
      -> 2
    mysql> SELECT 29 MOD 9;
      -> 2
    

    Эту функцию безопасно использовать с BIGINT.

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

    mysql> SELECT MOD(34.5,3);
        -> 1.5
    

    MOD(N,0) вернет NULL.

  • PI()

    Возвращает значение pi. По умолчанию количество выведенных десятичных разрядов семь, но MySQL использует полное значение точности double внутренне.

    mysql> SELECT PI();
      -> 3.141593
    mysql> SELECT PI()+0.000000000000000000;
      -> 3.141592653589793116
    
  • POW(X, Y)

    Возвращает значение X возведенное в степень Y.

    mysql> SELECT POW(2,2);
      -> 4
    mysql> SELECT POW(2,-2);
      -> 0.25
    
  • POWER(X, Y)

    Синоним для POW().

  • RADIANS(X)

    Возвращает параметр X, преобразованный из градусов в радианы. Отметьте, что 0 радиан равняется 180 градусов.

    mysql> SELECT RADIANS(90);
      -> 1.5707963267949
    
  • RAND(), RAND(N)

    Возвращает случайное значение с плавающей запятой v в диапазоне 0 <= v < 1.0. Если постоянный параметр целого числа N указан, это используется в качестве стартового значения, которое производит повторимую последовательность значений столбцов. В следующем примере отметьте, что последовательности значений, произведенных RAND(3) те же самые.

    mysql> CREATE TABLE t (i INT);
    Query OK, 0 rows affected (0.42 sec)
    
    mysql> INSERT INTO t VALUES(1),(2),(3);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SELECT i, RAND() FROM t;
    +---+------------------+
    | i | RAND()           |
    +---+------------------+
    | 1 | 0.61914388706828 |
    | 2 | 0.93845168309142 |
    | 3 | 0.83482678498591 |
    +---+------------------+
    3 rows in set (0.00 sec)
    
    mysql> SELECT i, RAND(3) FROM t;
    +---+------------------+
    | i | RAND(3)          |
    +---+------------------+
    | 1 | 0.90576975597606 |
    | 2 | 0.37307905813035 |
    | 3 | 0.14808605345719 |
    +---+------------------+
    3 rows in set (0.00 sec)
    
    mysql> SELECT i, RAND() FROM t;
    +---+------------------+
    | i | RAND()           |
    +---+------------------+
    | 1 | 0.35877890638893 |
    | 2 | 0.28941420772058 |
    | 3 | 0.37073435016976 |
    +---+------------------+
    3 rows in set (0.00 sec)
    
    mysql> SELECT i, RAND(3) FROM t;
    +---+------------------+
    | i | RAND(3)          |
    +---+------------------+
    | 1 | 0.90576975597606 |
    | 2 | 0.37307905813035 |
    | 3 | 0.14808605345719 |
    +---+------------------+
    3 rows in set (0.01 sec)
    

    С постоянным инициализатором, настройка происходит однократно, до выполнения запроса. Если непостоянный инициализатор (такой, как имя столбца) используется в качестве параметра, настройка происходит со значением для каждого вызова RAND(). Одно значение этого то, что для равных значений параметра RAND() возвратит то же самое значение каждый раз.

    Получить случайное целое число R в диапазоне i <= R < j можно, используя выражение FLOOR(i + RAND() * (j i)). Например, чтобы получить случайное целое число в диапазоне 7 <= R < 12, Вы можете использовать следующий запрос:

    SELECT FLOOR(7 + (RAND() * 5));
    

    RAND() в предложении WHERE переоценено каждый раз, когда выполняется WHERE.

    Использование столбца с RAND() в предложении ORDER BY или GROUP BY может привести к неожиданным результатам потому что для любого запроса RAND() может быть оценено несколько раз для той же самой строки, каждый раз возвращая различный результат. Однако, Вы можете получить строки в случайном порядке:

    mysql> SELECT * FROM tbl_name ORDER BY RAND();
    

    ORDER BY RAND() объединенный с LIMIT полезен для случайной выборки из ряда строк:

    mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d
                       ORDER BY RAND() LIMIT 1000;
    

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

    Эта функция опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format установлено в STATEMENT (Bug #49222).

  • ROUND(X) , ROUND(X , D)

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

    mysql> SELECT ROUND(-1.23);
      -> -1
    mysql> SELECT ROUND(-1.58);
      -> -2
    mysql> SELECT ROUND(1.58);
      -> 2
    mysql> SELECT ROUND(1.298, 1);
      -> 1.3
    mysql> SELECT ROUND(1.298, 0);
      -> 1
    mysql> SELECT ROUND(23.298, -1);
      -> 20
    

    Тип возврата тот же самый тип как у первого параметра (предполагается, что это целое число, double или decimal). Это означает, что для параметра целого числа, результат целое число:

    mysql> SELECT ROUND(150.000,2), ROUND(150,2);
    +------------------+--------------+
    | ROUND(150.000,2) | ROUND(150,2) |
    +------------------+--------------+
    | 150.00           | 150          |
    +------------------+--------------+
    

    ROUND() использует следующие правила в зависимости от типа первого параметра:

    • Для чисел точного значения ROUND() использует правило round half away from zero или round toward nearest: значение с дробной частью .5 или больше округлено к следующему целому числу, если положительное, или вниз к следующему целому числу, если отрицательное. Другими словами, это округлено дальше от ноля. Значение с дробной частью меньше .5 округлено в меньшую сторону к следующему целому числу, если положительное, или до следующего целого числа, если отрицательное.

    • Для чисел приблизительной точности результат зависит от библиотеки C. На многих системах это означает, что ROUND() использует правило "round to nearest even": значение с любой дробной частью округлено к самому близкому целому числу.

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

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

    Возвращает знак параметра как -1, 0 или 1, в зависимости от того, каким является X : отрицательным, нулем или положительным.

    mysql> SELECT SIGN(-32);
      -> -1
    mysql> SELECT SIGN(0);
      -> 0
    mysql> SELECT SIGN(234);
      -> 1
    
  • SIN(X)

    Возвращает синус X, где X дан в радианах.

    mysql> SELECT SIN(PI());
      -> 1.2246063538224e-16
    mysql> SELECT ROUND(SIN(PI()));
      -> 0
    
  • SQRT(X)

    Возвращает квадратный корень неотрицательного числа X.

    mysql> SELECT SQRT(4);
      -> 2
    mysql> SELECT SQRT(20);
      -> 4.4721359549996
    mysql> SELECT SQRT(-16);
      -> NULL
    
  • TAN(X)

    Возвращает тангенс X, где X дан в радианах.

    mysql> SELECT TAN(PI());
      -> -1.2246063538224e-16
    mysql> SELECT TAN(PI()+1);
      -> 1.5574077246549
    
  • TRUNCATE(X, D)

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

    mysql> SELECT TRUNCATE(1.223,1);
      -> 1.2
    mysql> SELECT TRUNCATE(1.999,1);
      -> 1.9
    mysql> SELECT TRUNCATE(1.999,0);
      -> 1
    mysql> SELECT TRUNCATE(-1.999,1);
      -> -1.9
    mysql> SELECT TRUNCATE(122,-2);
     -> 100
    mysql> SELECT TRUNCATE(10.28*100,0);
     -> 1028
    

    Все числа округлены к нолю.

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 поддержаны до точности микросекунды. Функции, которые берут временные параметры, принимают значения с дробными секундами. Возвращаемые значения от временных функций включают дробные секунды.

  • ADDDATE(date , INTERVALexpr unit), ADDDATE(expr , days)

    Когда вызвано с формой INTERVAL второго параметра, ADDDATE() синоним для DATE_ADD() . Связанная функция SUBDATE() синоним для DATE_SUB(). Для информации о параметре INTERVAL unit см. функцию DATE_ADD().

    mysql> SELECT DATE_ADD('2008-01-02', INTERVAL 31 DAY);
      -> '2008-02-02'
    mysql> SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY);
      -> '2008-02-02'
    

    Когда вызвано с формой days второго параметра, MySQL обрабатывает это как целое число дней, которые будут добавлены к expr.

    mysql> SELECT ADDDATE('2008-01-02', 31);
      -> '2008-02-02'
    
  • ADDTIME(expr1 ,expr2)

    ADDTIME() добавляет expr2 к expr1 и возвращает результат. expr1 выражение time или datetime, а expr2 выражение time.

    mysql> SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002');
      -> '2008-01-02 01:01:01.000001'
    mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998');
      -> '03:00:01.999997'
    
  • CONVERT_TZ(dt , from_tz,to_tz)

    CONVERT_TZ() конвертирует значение datetime dt из часового пояса, данного from_tz к часовому поясу, данному to_tz и возвращает получающееся значение. Часовые пояса определены как описано в разделе 11.6 . Эта функция возвращает NULL, если параметры недопустимы.

    Если значение выходит из поддержанного диапазона TIMESTAMP, когда преобразовано из from_tz в UTC, не происходит никакого преобразования. Диапазон TIMESTAMP описан в разделе 12.1.2 .

    mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
        -> '2004-01-01 13:00:00'
    mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');
        -> '2004-01-01 22:00:00'
    

    Чтобы использовать названный часовыми пояс, например, 'MET' или 'Europe/Moscow', таблицы часового пояса должны быть должным образом настроены. См. раздел 11.6 .

  • CURDATE()

    Возвращает текущую дату как значение в формате 'YYYY-MM-DD' или YYYYMMDD, в зависимости от того, используется ли функция в строковом или числовом контексте.

    mysql> SELECT CURDATE();
        -> '2008-06-13'
    mysql> SELECT CURDATE() + 0;
        -> 20080613
    
  • CURRENT_DATE, CURRENT_DATE()

    CURRENT_DATE и CURRENT_DATE() синонимы для CURDATE().

  • CURRENT_TIME, CURRENT_TIME([fsp ])

    CURRENT_TIME и CURRENT_TIME() синонимы для CURTIME().

  • CURRENT_TIMESTAMP , CURRENT_TIMESTAMP([fsp])

    CURRENT_TIMESTAMP и CURRENT_TIMESTAMP() синонимы для NOW().

  • CURTIME([fsp ])

    Возвращает текущее время как значение в формате 'HH:MM:SS' или HHMMSS, в зависимости от того, используется ли функция в строковом или числовом контексте. Значение выражено в зоне текущего времени.

    Если параметр fsp дан, чтобы определить дробную точность секунд от 0 до 6, возвращаемое значение включает дробную часть секунд.

    mysql> SELECT CURTIME();
        -> '23:50:26'
    mysql> SELECT CURTIME() + 0;
        -> 235026.000000
    
  • DATE(expr)

    Извлекает часть даты из выражения expr типа date или datetime.

    mysql> SELECT DATE('2003-12-31 01:02:03');
        -> '2003-12-31'
    
  • DATEDIFF(expr1 ,expr2)

    DATEDIFF() возвращает expr1 - expr2, выраженное как значение в днях от одной даты до другой. expr1 и expr2 выражения дата или "дата и время". Только части даты значений используются в вычислении.

    mysql> SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30');
        -> 1
    mysql> SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31');
        -> -31
    
  • DATE_ADD(date , INTERVAL expr unit) , DATE_SUB(date , INTERVAL expr unit)

    Эти функции выполняют арифметику даты. Параметр date определяет стартовую дату или значение datetime. expr выражение, определяющее значение интервала, которое будет добавлено или вычтено из даты. expr строка, она может начинаться с - для отрицательных интервалов. unit ключевое слово, указывающее на величину, в которой должно интерпретироваться выражение.

    Ключевое слово INTERVAL и спецификатор unit не является чувствительными к регистру.

    Следующая таблица показывает ожидаемую форму параметра expr для каждого значения unit.

    Значение unit Ожидаемый формат expr
    MICROSECOND MICROSECONDS
    SECONDSECONDS
    MINUTEMINUTES
    HOURHOURS
    DAYDAYS
    WEEKWEEKS
    MONTHMONTHS
    QUARTERQUARTERS
    YEARYEARS
    SECOND_MICROSECOND 'SECONDS.MICROSECONDS'
    MINUTE_MICROSECOND 'MINUTES:SECONDS.MICROSECONDS'
    MINUTE_SECOND 'MINUTES:SECONDS'
    HOUR_MICROSECOND 'HOURS:MINUTES:SECONDS.MICROSECONDS'
    HOUR_SECOND 'HOURS:MINUTES:SECONDS'
    HOUR_MINUTE'HOURS:MINUTES'
    DAY_MICROSECOND 'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS'
    DAY_SECOND 'DAYS HOURS:MINUTES:SECONDS'
    DAY_MINUTE 'DAYS HOURS:MINUTES'
    DAY_HOUR'DAYS HOURS'
    YEAR_MONTH'YEARS-MONTHS'

    Возвращаемое значение зависит от параметров:

    • DATETIME, если первый параметр DATETIME (или TIMESTAMP), или если первый параметр DATE и значение unit использует HOURS, MINUTES или SECONDS.

    • Строка иначе.

    Чтобы гарантировать, что результат будет DATETIME, Вы можете использовать CAST(), чтобы преобразовать первый параметр в DATETIME.

    MySQL разрешает любой разделитель пунктуации в формате expr. Показанные в таблице являются предложенными разделителями. Если параметр date типа DATE и Ваши вычисления вовлекают только части YEAR, MONTH и DAY (без частей времени), результат будет типа DATE. Иначе типа DATETIME.

    Арифметика даты также может быть выполнена, используя INTERVAL вместе с оператором + -:

    date + INTERVAL expr unit
    date - INTERVAL expr unit
    

    INTERVAL expr unit разрешен по обе стороны от оператора +, если выражение с другой стороны значение datetime или дата. Для оператора - INTERVAL expr unit разрешен только на правой стороне, потому что не имеет никакого смысла вычитать дату или значение datetime из интервала.

    mysql> SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;
        -> '2009-01-01 00:00:00'
    mysql> SELECT INTERVAL 1 DAY + '2008-12-31';
        -> '2009-01-01'
    mysql> SELECT '2005-01-01' - INTERVAL 1 SECOND;
        -> '2004-12-31 23:59:59'
    mysql> SELECT DATE_ADD('2000-12-31 23:59:59',
        -> INTERVAL 1 SECOND);
        -> '2001-01-01 00:00:00'
    mysql> SELECT DATE_ADD('2010-12-31 23:59:59',
        -> INTERVAL 1 DAY);
        -> '2011-01-01 23:59:59'
    mysql> SELECT DATE_ADD('2100-12-31 23:59:59',
        -> INTERVAL '1:1' MINUTE_SECOND);
        -> '2101-01-01 00:01:00'
    mysql> SELECT DATE_SUB('2005-01-01 00:00:00',
        -> INTERVAL '1 1:1:1' DAY_SECOND);
        -> '2004-12-30 22:58:59'
    mysql> SELECT DATE_ADD('1900-01-01 00:00:00',
        -> INTERVAL '-1 10' DAY_HOUR);
        -> '1899-12-30 14:00:00'
    mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
    mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
        ->  INTERVAL '1.999999' SECOND_MICROSECOND);
        -> '1993-01-01 00:00:01.000001'
    

    Если Вы определяете значение интервала, которое слишком коротко (не включает все части интервала, которые ожидались бы от unit), MySQL предполагает, что Вы не учли крайние левые части значения интервала. Например, если Вы определяете unit DAY_SECOND, значение expr будет иметь дни, часы, минуты и части секунд. Если Вы определяете значение как '1:10', MySQL предполагает, что дни и часы отсутствуют, а значение представляет минуты и секунды. Другими словами, '1:10' DAY_SECOND интерпретируется таким способом, по которому это эквивалентно '1:10' MINUTE_SECOND. Это походит на способ, которым MySQL интерпретирует значения TIME как представляющие прошедшее время, а не как время суток.

    Поскольку expr обработан как строка, надо быть осторожным, если Вы определяете нестроковое значение с INTERVAL. Например, со спецификатором интервала HOUR_MINUTE, 6/4 оценивается как 1.5000 и будет обработано как 1 час 5000 минут:

    mysql> SELECT 6/4;
        -> 1.5000
    mysql> SELECT DATE_ADD('2009-01-01', INTERVAL 6/4 HOUR_MINUTE);
        -> '2009-01-04 12:20:00'
    

    Чтобы гарантировать интерпретацию интервала как Вы ожидаете, используйте CAST(). Чтобы 6/4 было понято как 1 час 5 минут, приведите это к типу DECIMAL с единственной дробной цифрой:

    mysql> SELECT CAST(6/4 AS DECIMAL(3,1));
      -> 1.5
    mysql> SELECT DATE_ADD('1970-01-01 12:00:00',
      -> INTERVAL CAST(6/4 AS DECIMAL(3,1)) HOUR_MINUTE);
      -> '1970-01-01 13:05:00'
    

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

    mysql> SELECT DATE_ADD('2013-01-01', INTERVAL 1 DAY);
        -> '2013-01-02'
    mysql> SELECT DATE_ADD('2013-01-01', INTERVAL 1 HOUR);
        -> '2013-01-01 01:00:00'
    

    Если Вы добавляете MONTH, YEAR_MONTH или YEAR и у получающейся даты есть день, который больше, чем максимальный день в новом месяце, день скорректирован к максимальному дню в новом месяце:

    mysql> SELECT DATE_ADD('2009-01-30', INTERVAL 1 MONTH);
        -> '2009-02-28'
    

    Операции арифметики даты требуют полных дат и не работают с неполными датами вроде '2006-07-00' или ужасно уродливыми датами:

    mysql> SELECT DATE_ADD('2006-07-00', INTERVAL 1 DAY);
      -> NULL
    mysql> SELECT '2005-03-32' + INTERVAL 1 MONTH;
      -> NULL
    
  • DATE_FORMAT(date ,format)

    Форматирует значение date согласно строке format.

    Следующие спецификаторы могут использоваться в строке format. Символ % требуется перед символами спецификатора формата.

    СпецификаторОписание
    %a Сокращенное имя дня (Sun..Sat)
    %bСокращенное имя месяца (Jan..Dec)
    %cМесяц, числовое представление (0..12)
    %DДень месяца с английским суффиксом (0th, 1st, 2nd, 3rd, ...)
    %dДень месяца, числовой вид (00..31)
    %eДень месяца, числовой вид (0..31)
    %fМикросекунды (000000..999999)
    %HЧас (00..23 )
    %hЧас (01..12 )
    %IЧас (01..12 )
    %iМинуты, числовой вид (00..59)
    %jДень года (001..366)
    %kЧас (0..23)
    %lЧас (1..12)
    %MИмя месяца Month name (January..December)
    %mМесяц, числовой вид (00..12)
    %pAM или PM
    %rВремя, 12-часовой формат (hh:mm:ss, сопровождаемый AM или PM)
    %SСекунды (00.. 59)
    %sСекунды (00.. 59)
    %TВремя, 24-часовой формат (hh:mm:ss)
    %UНедели (00.. 53), где Sunday первый день недели, WEEK() режим 0
    %uНедели (00.. 53), Monday первый день недели, WEEK() режим 1
    %VНедели (01.. 53), Sunday первый день недели, WEEK() режим 2, используется с %X
    %vНедели (01..53 ), Monday первый день недели, WEEK() режим 3, используется с %x
    %WИмя дня (Sunday..Saturday)
    %wДень недели (0=Sunday..6=Saturday)
    %XГод для недели, где воскресенье первый день недели, числовой вид, четыре цифры, применяется с %V
    %xГод для недели, где понедельник первый день недели, числовой вид, четыре цифры, применяется с %v
    %YГод, числовой тип, четыре цифры
    %yГод, числовой тип, две цифры
    %%Символ %
    %x x для любого x не упомянутого выше

    Диапазоны для спецификаторов месяца и дня начинаются с ноля вследствие того, что MySQL разрешает хранение неполных дат вроде '2014-00-00'.

    Языком, используемым для имен дня и месяца и сокращений, управляет значение системной переменной lc_time_names (раздел 11.7).

    Для %U, %u, %V и %v см. описание функции WEEK() для информации о значениях режима. Режим затрагивает нумерацию недели.

    DATE_FORMAT() возвращает строку с набором символов и сопоставлением, данным character_set_connection и collation_connection так, чтобы это могло возвратить имена месяца и дня, содержащие символы не-ASCII.

    mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');
      -> 'Sunday October 2009'
    mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s');
      -> '22:23:00'
    mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00',
      -> '%D %y %a %d %m %b %j');
      -> '4th 00 Thu 04 10 Oct 277'
    mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
      -> '%H %k %I %r %T %S %w');
      -> '22 22 10 10:23:00 PM 22:23:00 00 6'
    mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
      -> '1998 52'
    mysql> SELECT DATE_FORMAT('2006-06-00', '%d');
      -> '00'
    
  • DATE_SUB(date , INTERVAL expr unit)

    См. описание для DATE_ADD() .

  • DAY(date)

    DAY() синоним для DAYOFMONTH().

  • DAYNAME(date )

    Возвращает название дня для date. Языком, используемым для имени, управляет значение lc_time_names (раздел 11.7).

    mysql> SELECT DAYNAME('2007-02-03');
      -> 'Saturday'
    
  • DAYOFMONTH(date )

    Возвращает день месяца для date в диапазоне от 1 до 31 или 0 для дат вроде '0000-00-00' или '2008-00-00', в которых есть часть нулевого дня.

    mysql> SELECT DAYOFMONTH('2007-02-03');
      -> 3
    
  • DAYOFWEEK(date )

    Возвращается индекс дня date (1 = Sunday, 2 = Monday, ..., 7 = Saturday). Значения соответствуют стандарту ODBC.

    mysql> SELECT DAYOFWEEK('2007-02-03');
      -> 7
    
  • DAYOFYEAR(date )

    Возвращает день года для date в диапазоне от 1 до 366.

    mysql> SELECT DAYOFYEAR('2007-02-03');
      -> 34
    
  • EXTRACT(unit FROM date)

    Функция EXTRACT() использует те же самые виды спецификаторов, что и DATE_ADD() или DATE_SUB(), но извлекает части из даты.

    mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
      -> 2009
    mysql> SELECT EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03');
      -> 200907
    mysql> SELECT EXTRACT(DAY_MINUTE FROM '2009-07-02 01:02:03');
      -> 20102
    mysql> SELECT EXTRACT(MICROSECOND FROM '2003-01-02 10:30:00.000123');
      -> 123
    
  • FROM_DAYS(N )

    Учитывая номер дня N, вернет значение DATE.

    mysql> SELECT FROM_DAYS(730669);
      -> '2007-07-03'
    

    Используйте FROM_DAYS() с осторожностью для старых дат. Это не предназначено для использования со значениями, которые предшествуют появлению Григорианского календаря (1582 г.). См. раздел 13.8.

  • FROM_UNIXTIME( unix_timestamp), FROM_UNIXTIME( unix_timestamp,format)

    Возвращает представление unix_timestamp как значение в виде in 'YYYY-MM-DD HH:MM:SS' или YYYYMMDDHHMMSS в зависимости от того, используется ли функция в строковом или числовом контексте. Значение выражено в зоне текущего времени. unix_timestamp внутреннее значение, которое произведено функцией UNIX_TIMESTAMP() .

    Если задан format, результат отформатирован согласно строке format, которая используется как в функции DATE_FORMAT().

    mysql> SELECT FROM_UNIXTIME(1447430881);
        -> '2015-11-13 10:08:01'
    mysql> SELECT FROM_UNIXTIME(1447430881) + 0;
        -> 20151113100801
    mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x');
        -> '2015 13th November 10:08:01 2015'
    

    Отметьте: Если Вы используете UNIX_TIMESTAMP() и FROM_UNIXTIME() , чтобы преобразовать между значениями TIMESTAMP и Unix timestamp, преобразование будет с потерями, потому что отображение не является непосредственным в обоих направлениях. Для деталей см. описание UNIX_TIMESTAMP().

  • GET_FORMAT({DATE|TIME|DATETIME}, {'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL'})

    Возвращает строку формата. Эта функция полезна в комбинации с функциями DATE_FORMAT() и STR_TO_DATE().

    Возможные значения для первого и второго параметров в нескольких возможных строках формата (для используемых спецификаторов см. таблицу в описании функции DATE_FORMAT() ). Формат ISO обращается к ISO 9075, а не ISO 8601.

    Вызов функцииРезультат
    GET_FORMAT(DATE,'USA')'%m.%d.%Y'
    GET_FORMAT(DATE,'JIS')'%Y-%m-%d'
    GET_FORMAT(DATE,'ISO')'%Y-%m-%d'
    GET_FORMAT(DATE,'EUR')'%d.%m.%Y'
    GET_FORMAT(DATE,'INTERNAL')'%Y%m%d'
    GET_FORMAT(DATETIME,'USA')'%Y-%m-%d %H.%i.%s'
    GET_FORMAT(DATETIME,'JIS')'%Y-%m-%d %H:%i:%s'
    GET_FORMAT(DATETIME,'ISO')'%Y-%m-%d %H:%i:%s'
    GET_FORMAT(DATETIME,'EUR')'%Y-%m-%d %H.%i.%s'
    GET_FORMAT(DATETIME,'INTERNAL')'%Y%m%d%H%i%s'
    GET_FORMAT(TIME,'USA')'%h:%i:%s %p'
    GET_FORMAT(TIME,'JIS')'%H:%i:%s'
    GET_FORMAT(TIME,'ISO')'%H:%i:%s'
    GET_FORMAT(TIME,'EUR')'%H.%i.%s'
    GET_FORMAT(TIME,'INTERNAL')'%H%i%s'

    TIMESTAMP может также использоваться в качестве первого параметра GET_FORMAT(), когда функция возвращает те же самые значения, что DATETIME.

    mysql> SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR'));
      -> '03.10.2003'
    mysql> SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA'));
      -> '2003-10-31'
    
  • HOUR(time)

    Возвращает час для time. Диапазон возвращаемого значения от 0 до 23 для значений времени суток. Однако, диапазон значений TIME фактически намного больше, таким образом, HOUR может возвращать значения больше, чем 23.

    mysql> SELECT HOUR('10:05:03');
      -> 10
    mysql> SELECT HOUR('272:59:59');
      -> 272
    
  • LAST_DAY(date )

    Берет дату или значение datetime и возвращает соответствующее значение для последнего дня месяца. Возвращает NULL, если параметр недопустим.

    mysql> SELECT LAST_DAY('2003-02-05');
      -> '2003-02-28'
    mysql> SELECT LAST_DAY('2004-02-05');
      -> '2004-02-29'
    mysql> SELECT LAST_DAY('2004-01-01 01:01:01');
      -> '2004-01-31'
    mysql> SELECT LAST_DAY('2003-03-32');
      -> NULL
    
  • LOCALTIME, LOCALTIME([fsp ])

    LOCALTIME и LOCALTIME() синонимы для NOW().

  • LOCALTIMESTAMP, LOCALTIMESTAMP([ fsp])

    LOCALTIMESTAMP и LOCALTIMESTAMP() синонимы для NOW() .

  • MAKEDATE(year ,dayofyear)

    Возвращает дату, данную значениями года и дня года. dayofyear должно быть больше 0, или результат NULL.

    mysql> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);
      -> '2011-01-31', '2011-02-01'
    mysql> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);
      -> '2011-12-31', '2014-12-31'
    mysql> SELECT MAKEDATE(2011,0);
      -> NULL
    
  • MAKETIME(hour ,minute,second)

    Возвращает время, вычисленное из параметров hour, minute и second. У параметра second может быть дробная часть.

    mysql> SELECT MAKETIME(12,15,30);
      -> '12:15:30'
    
  • MICROSECOND(expr )

    Возвращает микросекунды из выражения time или datetime expr как число в диапазоне от 0 до 999999.

    mysql> SELECT MICROSECOND('12:00:00.123456');
      -> 123456
    mysql> SELECT MICROSECOND('2009-12-31 23:59:59.000010');
      -> 10
    
  • MINUTE(time)

    Возвращает минуту для time в диапазоне от 0 до 59.

    mysql> SELECT MINUTE('2008-02-03 10:05:03');
      -> 5
    
  • MONTH(date)

    Возвращает месяц для date в диапазоне от 1 до 12 или 0 для дат вроде '0000-00-00' или '2008-00-00' с нулевым значением месяца.

    mysql> SELECT MONTH('2008-02-03');
      -> 2
    
  • MONTHNAME(date )

    Возвращает полное имя месяца для date. Языком, используемым для имени, управляет значение lc_time_names (раздел 11.7).

    mysql> SELECT MONTHNAME('2008-02-03');
      -> 'February'
    
  • NOW([fsp])

    Возвращает текущую дату и время как значение в формате 'YYYY-MM-DD HH:MM:SS' или YYYYMMDDHHMMSS в зависимости от того, используется ли функция в строковом или числовом контексте. Значение выражено в зоне текущего времени.

    Если параметр fsp дан, чтобы определить дробную точность секунд от 0 до 6, возвращаемое значение включает дробную часть секунд.

    mysql> SELECT NOW();
      -> '2007-12-15 23:50:26'
    mysql> SELECT NOW() + 0;
      -> 20071215235026.000000
    

    NOW() возвращает постоянное время, которое указывает время, в которое запрос начал выполняться. В пределах сохраненной функции или триггера NOW() возвращает время, в которое функция или запрос вызова начали выполняться. Это отличается от поведения для SYSDATE(), который возвращает точное время, в которое выполняется.

    mysql> SELECT NOW(), SLEEP(2), NOW();
    +---------------------+----------+---------------------+
    | NOW()               | SLEEP(2) | NOW()               |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:36 |  0       | 2006-04-12 13:47:36 |
    +---------------------+----------+---------------------+
    
    mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();
    +---------------------+----------+---------------------+
    | SYSDATE()           | SLEEP(2) | SYSDATE()           |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:44 |  0       | 2006-04-12 13:47:46 |
    +---------------------+----------+---------------------+
    

    Кроме того, SET TIMESTAMP затрагивает значение, возвращенное NOW(), но не SYSDATE(). Это означает, что настройки timestamp в двоичном журнале не имеют никакого эффекта на вызовы SYSDATE() . Установка timestamp к ненулевому значению предписывает каждому последующему вызову NOW() возвратить то значение. Установка timestamp к нулю отменяет этот эффект, чтобы NOW() возвращал текущую дату и время.

  • PERIOD_ADD(P ,N)

    Добавляет N месяцев к периоду P (в формате YYMM или YYYYMM). Возвращает значение в формате YYYYMM. Отметьте что параметр периода P не значение date.

    mysql> SELECT PERIOD_ADD(200801,2);
      -> 200803
    
  • PERIOD_DIFF(P1 ,P2)

    Возвращает число месяцев между периодами P1 и P2. P1 и P2 должны быть в формате YYMM или YYYYMM. Отметьте, что параметры периода P1 и P2 не значения date.

    mysql> SELECT PERIOD_DIFF(200802,200703);
        -> 11
    
  • QUARTER(date )

    Возвращает четверть (квартал) года для date в диапазоне от 1 до 4.

    mysql> SELECT QUARTER('2008-04-01');
      -> 2
    
  • SECOND(time)

    Возвращает секунды для time в диапазоне от 0 до 59.

    mysql> SELECT SECOND('10:05:03');
      -> 3
    
  • SEC_TO_TIME(seconds )

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

    mysql> SELECT SEC_TO_TIME(2378);
      -> '00:39:38'
    mysql> SELECT SEC_TO_TIME(2378) + 0;
      -> 3938
    
  • STR_TO_DATE(str ,format)

    Это инверсия функции DATE_FORMAT(). Это берет строку str и строку формата format. STR_TO_DATE() возвращает значение DATETIME, если строка формата содержит части даты и времени, значения DATE или TIME, если строка содержит только части даты или времени. Если значение date, time или datetime, извлеченное из str неправильно, STR_TO_DATE() вернет NULL и произведет предупреждение.

    Сервер сканирует str и пытается соответствовать format. Строка формата может содержать буквальные символы и спецификаторы, начинающиеся с %. Буквальные символы в format должны соответствовать буквально str. Спецификаторы формата в format должны соответствовать части даты или времени в str. Для спецификаторов, которые могут использоваться в format, см. описание функции DATE_FORMAT().

    mysql> SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y');
      -> '2013-05-01'
    mysql> SELECT STR_TO_DATE('May 1, 2013','%M %d,%Y');
      -> '2013-05-01'
    

    Просмотр запускается в начале str и терпит неудачу, если format не соответствует. Дополнительные символы в конце str проигнорированы.

    mysql> SELECT STR_TO_DATE('a09:30:17','a%h:%i:%s');
      -> '09:30:17'
    mysql> SELECT STR_TO_DATE('a09:30:17','%h:%i:%s');
      -> NULL
    mysql> SELECT STR_TO_DATE('09:30:17a','%h:%i:%s');
      -> '09:30:17'
    

    У неуказанных частей даты или времени есть значение 0, так что не полностью определенные значения в str приведут к результату с некоторыми или всеми частями, установленными в 0:

    mysql> SELECT STR_TO_DATE('abc','abc');
      -> '0000-00-00'
    mysql> SELECT STR_TO_DATE('9','%m');
      -> '0000-09-00'
    mysql> SELECT STR_TO_DATE('9','%s');
      -> '00:00:09'
    

    Диапазон, проверяющий части значений даты, описан в разделе 12.3.1. Это означает, например, что нулевые или даты со значениями части 0 разрешены, если режим SQL не установлен так, чтобы отвергнуть такие значения.

    mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y');
      -> '0000-00-00'
    mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y');
      -> '2004-04-31'
    

    Если включен режим SQL NO_ZERO_DATE или NO_ZERO_IN_DATE нулевые или частичные даты отвергнуты. В этом случае STR_TO_DATE() вернет NULL с предупреждением:

    mysql> SET sql_mode = '';
    mysql> SELECT STR_TO_DATE('15:35:00', '%H:%i:%s');
    +-------------------------------------+
    | STR_TO_DATE('15:35:00', '%H:%i:%s') |
    +-------------------------------------+
    | 15:35:00                            |
    +-------------------------------------+
    
    mysql> SET sql_mode = 'NO_ZERO_IN_DATE';
    mysql> SELECT STR_TO_DATE('15:35:00', '%h:%i:%s');
    +-------------------------------------+
    | STR_TO_DATE('15:35:00', '%h:%i:%s') |
    +-------------------------------------+
    | NULL                                |
    +-------------------------------------+
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 1411
    Message: Incorrect datetime value: '15:35:00' for function str_to_date
    

    Вы не можете использовать формат "%X%V" для конвертации строки года и недели в дату, потому что комбинация года и недели уникально не идентифицирует год и месяц, если неделя пересекает границу месяца. Чтобы преобразовать такое значение в дату, Вы должны также определить день:

    mysql> SELECT STR_TO_DATE('200442 Monday', '%X%V %W');
      -> '2004-10-18'
    
  • SUBDATE(date , INTERVAL expr unit), SUBDATE(expr , days)

    Когда вызвано с формой INTERVAL второго параметра, SUBDATE() синоним для DATE_SUB().

    mysql> SELECT DATE_SUB('2008-01-02', INTERVAL 31 DAY);
      -> '2007-12-02'
    mysql> SELECT SUBDATE('2008-01-02', INTERVAL 31 DAY);
      -> '2007-12-02'
    

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

    mysql> SELECT SUBDATE('2008-01-02 12:00:00', 31);
        -> '2007-12-02 12:00:00'
    
  • SUBTIME(expr1 ,expr2)

    SUBTIME() вернет expr1 - expr2 выраженное как значение в том же самом формате, что и expr1. expr1 выражение time или datetime, expr2 выражение time.

    mysql> SELECT SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002');
      -> '2007-12-30 22:58:58.999997'
    mysql> SELECT SUBTIME('01:00:00.999999', '02:00:00.999998');
      -> '-00:59:59.999999'
    
  • SYSDATE([fsp ])

    Возвращает текущую дату и время как значение в формате 'YYYY-MM-DD HH:MM:SS' или YYYYMMDDHHMMSS в зависимости от того, используется ли функция в строковом или числовом контексте.

    Если параметр fsp задан, чтобы определить дробную точность секунд от 0 до 6, возвращаемое значение включает дробную часть секунд.

    SYSDATE() возвращает время, в которое выполняется. Это отличается от поведения для NOW(), который возвращает постоянное время, которое указывает на время, в которое запрос начал выполняться. В пределах сохраненной функции или триггера NOW() возвращает время, в которое функция или триггер начали выполняться.

    mysql> SELECT NOW(), SLEEP(2), NOW();
    +---------------------+----------+---------------------+
    | NOW()               | SLEEP(2) | NOW()               |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:36 |  0       | 2006-04-12 13:47:36 |
    +---------------------+----------+---------------------+
    
    mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();
    +---------------------+----------+---------------------+
    | SYSDATE()           | SLEEP(2) | SYSDATE()           |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:44 |  0       | 2006-04-12 13:47:46 |
    +---------------------+----------+---------------------+
    

    Кроме того, SET TIMESTAMP затрагивает значение, возвращенное NOW(), но не SYSDATE(). Это означает, что настройки timestamp в двоичном журнале не имеют никакого эффекта на SYSDATE().

    Поскольку SYSDATE() может возвратить различные значения даже в пределах того же самого запроса и не затронут SET TIMESTAMP, это недетерминировано и поэтому опасно для репликации, если используется основанное на запросах двоичное журналирование. Если это проблема, Вы можете использовать основанное на строке журналирование.

    Альтернативно, Вы можете использовать опцию --sysdate-is-now , чтобы вызвать SYSDATE() как псевдоним для NOW(). Это работает, если опция используется на ведущем и на ведомом устройствах.

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

  • TIME(expr)

    Извлекает часть времени из выражения expr типа time или datetime и возвращает это как строку. Эта функция опасна для основанной на запросах репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format установлена в STATEMENT.

    mysql> SELECT TIME('2003-12-31 01:02:03');
      -> '01:02:03'
    mysql> SELECT TIME('2003-12-31 01:02:03.000123');
      -> '01:02:03.000123'
    
  • TIMEDIFF(expr1 ,expr2)

    TIMEDIFF() вернет expr1 - expr2 как значение time. expr1 и expr2 выражения типа time или date-and-time, но оба должны иметь тот же самый тип.

    Результат, возвращенный TIMEDIFF() ограничен учтенным диапазоном TIME. Альтернативно, Вы можете использовать любую из функций TIMESTAMPDIFF() и UNIX_TIMESTAMP() , они обе возвращают целые числа.

    mysql> SELECT TIMEDIFF('2000:01:01 00:00:00',
      -> '2000:01:01 00:00:00.000001');
      -> '-00:00:00.000001'
    mysql> SELECT TIMEDIFF('2008-12-31 23:59:59.000001',
      -> '2008-12-30 01:01:01.000002');
      -> '46:58:57.999999'
    
  • TIMESTAMP(expr ), TIMESTAMP(expr1 ,expr2)

    С единственным параметром эта функция возвращает выражение expr как значение datetime. С двумя параметрами это добавляет выражение времени expr2 к expr1 и возвращает результат как значение datetime.

    mysql> SELECT TIMESTAMP('2003-12-31');
      -> '2003-12-31 00:00:00'
    mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
      -> '2004-01-01 00:00:00'
    
  • TIMESTAMPADD(unit ,interval,datetime_expr )

    Добавляет выражение целого числа interval к date или datetime datetime_expr. Модуль для interval дан параметром unit, который должен быть одним из следующих значений: MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER или YEAR.

    Значение unit может быть определено, используя одно из ключевых слов как показано, или с приставкой SQL_TSI_. Например, DAY и SQL_TSI_DAY оба допустимы.

    mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');
        -> '2003-01-02 00:01:00'
    mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');
        -> '2003-01-09'
    
  • TIMESTAMPDIFF(unit ,datetime_expr1,datetime_expr2 )

    Вернет datetime_expr2 - datetime_expr1 , где datetime_expr1 и datetime_expr2 выражения date или datetime. Одно выражение может быть датой, другое datetime, значение даты обработано как datetime с частью времени '00:00:00' где необходимо. Модуль для результата (целое число) дан параметром unit. Допустимые значения для unit перечислены в описании TIMESTAMPADD().

    mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');
      -> 3
    mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
      -> -1
    mysql> SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55');
      -> 128885
    

    Порядок параметров date или datetime в этой функции противоположность используемого с TIMESTAMP() , когда она вызвана с 2 параметрами.

  • TIME_FORMAT(time ,format)

    Это используется как функция DATE_FORMAT(), но строка format может содержать спецификаторы формата только для часов, минут, секунд и микросекунд. Другие спецификаторы производят NULL или 0.

    Если time содержит часть часа, которая больше, чем 23, спецификаторы формата часа %H и %k производят значение, больше чем обычный диапазон 0..23. Другие спецификаторы формата часа производят значение часа не более 12.

    mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');
      -> '100 100 04 04 4'
    
  • TIME_TO_SEC(time )

    Вернет параметр time, конвертированный в секунды.

    mysql> SELECT TIME_TO_SEC('22:23:00');
      -> 80580
    mysql> SELECT TIME_TO_SEC('00:39:38');
      -> 2378
    
  • TO_DAYS(date )

    Учитывая дату date, возвращает число дней с года 0.

    mysql> SELECT TO_DAYS(950501);
      -> 728779
    mysql> SELECT TO_DAYS('2007-10-07');
      -> 733321
    

    TO_DAYS() не предназначен для использования со значениями, которые предшествуют появлению Григорианского календаря (1582 г.), потому что это не принимает во внимание дни, которые были потеряны, когда календарь был изменен. Для дат до 1582 г. (и возможно более поздних в других местах действия), следствия этой функции ненадежны. См. раздел 13.8.

    Помните, что MySQL преобразовывает значения года с двумя цифрами в датах к форме с четырьмя цифрами, используя правила в разделе 12.3. Например, '2008-10-07' и '08-10-07' обработаны как идентичные даты:

    mysql> SELECT TO_DAYS('2008-10-07'), TO_DAYS('08-10-07');
      -> 733687, 733687
    

    В MySQL нулевая дата определена как '0000-00-00', даже при том, что эту дату самостоятельно считают недопустимой. Это означает что, для '0000-00-00' и '0000-01-01' TO_DAYS() возвращает значения, показанные здесь:

    mysql> SELECT TO_DAYS('0000-00-00');
    +-----------------------+
    | to_days('0000-00-00') |
    +-----------------------+
    |  NULL                 |
    +-----------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS;
    +---------+------+----------------------------------------+
    | Level   | Code | Message                                |
    +---------+------+----------------------------------------+
    | Warning | 1292 | Incorrect datetime value: '0000-00-00' |
    +---------+------+----------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT TO_DAYS('0000-01-01');
    +-----------------------+
    | to_days('0000-01-01') |
    +-----------------------+
    | 1                     |
    +-----------------------+
    1 row in set (0.00 sec)
    

    Это верно независимо от режима SQL ALLOW_INVALID_DATES .

  • TO_SECONDS(expr )

    Учитывая дату или datetime expr, возвращает число секунд с года 0. Если expr не допустимая дата или значение datetime, возвращет NULL.

    mysql> SELECT TO_SECONDS(950501);
      -> 62966505600
    mysql> SELECT TO_SECONDS('2009-11-29');
      -> 63426672000
    mysql> SELECT TO_SECONDS('2009-11-29 13:43:32');
      -> 63426721412
    mysql> SELECT TO_SECONDS( NOW() );
      -> 63426721458
    

    Подобно TO_DAYS(), TO_SECONDS() не предназначен для использования со значениями, которые предшествуют появлению Григорианского календаря (1582), потому что это не принимает во внимание дни, которые были потеряны, когда календарь был изменен. Для дат до 1582 (и возможно более поздний год в других местах), следствия этой функции ненадежны. См. раздел 13.8.

    Подобно TO_DAYS(), TO_SECONDS() преобразовывает значения года с двумя цифрами в датах к форме с четырьмя цифрами, используя правила в разделе 12.3.

    В MySQL нулевая дата определена как '0000-00-00', даже при том, что эту дату самостоятельно считают недопустимой. Это означает, что для '0000-00-00' и '0000-01-01' TO_SECONDS() возвращает такие значения:

    mysql> SELECT TO_SECONDS('0000-00-00');
    +--------------------------+
    | TO_SECONDS('0000-00-00') |
    +--------------------------+
    | NULL                     |
    +--------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS;
    +---------+------+----------------------------------------+
    | Level   | Code | Message                                |
    +---------+------+----------------------------------------+
    | Warning | 1292 | Incorrect datetime value: '0000-00-00' |
    +---------+------+----------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT TO_SECONDS('0000-01-01');
    +--------------------------+
    | TO_SECONDS('0000-01-01') |
    +--------------------------+
    | 86400                    |
    +--------------------------+
    1 row in set (0.00 sec)
    

    Это верно независимо от режима SQL ALLOW_INVALID_DATES .

  • UNIX_TIMESTAMP() , UNIX_TIMESTAMP( date)

    Если вызвано без параметра, возвращает Unix timestamp (секунды с '1970-01-01 00:00:00' UTC). Возвращаемое значение целое число, если никакой параметр не дан или параметр не включает дробную часть секунд, или DECIMAL, если параметр включает дробную часть секунд.

    Если UNIX_TIMESTAMP() вызвана с параметром date, это возвращает значение параметра как секунды с '1970-01-01 00:00:00' UTC. date может быть строкой DATE, DATETIME, TIMESTAMP или числом в формате YYMMDD или YYYYMMDD, произвольно включая дробную часть секунд. Сервер интерпретирует date как значение в зоне текущего времени и преобразует это к внутреннему значению в UTC. Клиенты могут установить свой часовой пояс как описано в разделе 11.6.

    mysql> SELECT UNIX_TIMESTAMP();
        -> 1447431666
    mysql> SELECT UNIX_TIMESTAMP('2015-11-13 10:20:19');
        -> 1447431619
    mysql> SELECT UNIX_TIMESTAMP('2015-11-13 10:20:19.012');
        -> 1447431619.012
    

    Когда UNIX_TIMESTAMP() используется на столбце TIMESTAMP, функция возвращает внутреннее значение timestamp непосредственно, без неявного преобразования string-to-Unix-timestamp . Если Вы передаете дату не из диапазона UNIX_TIMESTAMP() , это возвращает 0.

    Отметьте: Если Вы используете UNIX_TIMESTAMP() и FROM_UNIXTIME() , чтобы преобразовать между значениями TIMESTAMP и Unix timestamp, преобразование будет с потерями, потому что отображение не является непосредственным в обоих направлениях. Например, из-за соглашений для изменений зоны местного времени, возможно отобразить два значения UNIX_TIMESTAMP() на два TIMESTAMP с одним и тем же временем. FROM_UNIXTIME() отобразит значение назад только на одно из оригинальных значений TIMESTAMP. Вот пример, использования значений TIMESTAMP в часовом поясе CET:

    mysql> SELECT UNIX_TIMESTAMP('2005-03-27 03:00:00');
    +---------------------------------------+
    | UNIX_TIMESTAMP('2005-03-27 03:00:00') |
    +---------------------------------------+
    |  1111885200                           |
    +---------------------------------------+
    
    mysql> SELECT UNIX_TIMESTAMP('2005-03-27 02:00:00');
    +---------------------------------------+
    | UNIX_TIMESTAMP('2005-03-27 02:00:00') |
    +---------------------------------------+
    |  1111885200                           |
    +---------------------------------------+
    
    mysql> SELECT FROM_UNIXTIME(1111885200);
    +---------------------------+
    | FROM_UNIXTIME(1111885200) |
    +---------------------------+
    | 2005-03-27 03:00:00       |
    +---------------------------+
    
  • UTC_DATE, UTC_DATE()

    Возвращает текущую дату UTC как значение в формате 'YYYY-MM-DD' или YYYYMMDD в зависимости от того, используется ли функция в строковом или числовом контексте.

    mysql> SELECT UTC_DATE(), UTC_DATE() + 0;
        -> '2003-08-14', 20030814
    
  • UTC_TIME, UTC_TIME([fsp ])

    Возвращает текущее время UTC как значение в формате 'HH:MM:SS' или HHMMSS в зависимости от того, используется ли функция в строковом или числовом контексте.

    Если параметр fsp задан, чтобы определить дробную точность секунд от 0 до 6, возвращаемое значение включает дробную часть секунд.

    mysql> SELECT UTC_TIME(), UTC_TIME() + 0;
        -> '18:07:53', 180753.000000
    
  • UTC_TIMESTAMP, UTC_TIMESTAMP([ fsp])

    Возвращает текущую дату UTC и время как значение в формате 'YYYY-MM-DD HH:MM:SS' или YYYYMMDDHHMMSS в зависимости от того, используется ли функция в строковом или числовом контексте.

    Если параметр fsp задан, чтобы определить дробную точность секунд от 0 до 6, возвращаемое значение включает дробную часть секунд.

    mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;
        -> '2003-08-14 18:08:04', 20030814180804.000000
    
  • WEEK(date[, mode])

    Эта функция возвращает номер недели для date. Двухаргументная форма WEEK() позволяет Вам определить, запускается ли неделя в воскресенье или в понедельник и должно ли возвращаемое значение быть в диапазоне от 0 до 53 или от 1 до 53. Если параметр mode опущен, значение используется значение из системной переменной default_week_format. См. раздел 6.1.5.

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

    РежимПервый день недели ДиапазонНеделя 1 является первой неделей
    0Sunday0-53 с Sunday в этом году
    1Monday0-53 с 4 или больше днями в этом году
    2Sunday1-53 с Sunday в этом году
    3Monday1-53 с 4 или больше днями в этом году
    4Sunday0-53 с 4 или больше днями в этом году
    5Monday0-53 с Monday в этом году
    6Sunday1-53 с 4 или больше днями в этом году
    7Monday1-53 с Monday в этом году

    Для значений mode со смыслом "с 4 или больше днями в этом году" недели пронумерованы согласно ISO 8601:1988.

    • Если у недели, содержащей 1 января, есть 4 или больше дня в новом году, это неделя 1.

    • Иначе, это прошлая неделя предыдущего года, а следующая неделя как раз и есть неделя 1.

    mysql> SELECT WEEK('2008-02-20');
        -> 7
    mysql> SELECT WEEK('2008-02-20',0);
        -> 7
    mysql> SELECT WEEK('2008-02-20',1);
        -> 8
    mysql> SELECT WEEK('2008-12-31',1);
        -> 53
    

    Отметьте что, если дата на прошлой неделе предыдущего года, MySQL возвращает 0, если Вы не используете 2, 3, 6 или 7 как параметр mode:

    mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
        -> 2000, 0
    

    Можно было бы обсудить, что WEEK() должна возвратить 52, потому что данная дата фактически происходит на 52-ой неделе 1999. WEEK() вместо этого вернет 0 так, чтобы возвращаемое значение было номером недели в данном году. Это делает функцию WEEK() надежной, когда она объединена с другими функциями, которые извлекают часть даты.

    Если Вы предпочитаете результат, оцененный относительно года, который содержит первый день недели для данной даты, надо использовать 0, 2, 5 или 7 для параметра mode.

    mysql> SELECT WEEK('2000-01-01',2);
        -> 52
    

    Альтернативно, используйте функцию YEARWEEK():

    mysql> SELECT YEARWEEK('2000-01-01');
        -> 199952
    mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
        -> '52'
    
  • WEEKDAY(date )

    Возвращается индекс дня для date (0 = Monday, 1 = Tuesday, ..., 6 = Sunday).

    mysql> SELECT WEEKDAY('2008-02-03 22:23:00');
        -> 6
    mysql> SELECT WEEKDAY('2007-11-06');
        -> 1
    
  • WEEKOFYEAR(date )

    Возвращает календарную неделю даты как число в диапазоне от 1 до 53. WEEKOFYEAR() функция совместимости, которая эквивалентна WEEK(date,3) .

    mysql> SELECT WEEKOFYEAR('2008-02-20');
      -> 8
    
  • YEAR(date)

    Возвращает год для date в диапазоне от 1000 до 9999 или 0 для нулевой даты.

    mysql> SELECT YEAR('1987-01-01');
        -> 1987
    
  • YEARWEEK(date ), YEARWEEK(date ,mode)

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

    Параметр mode работает точно как в функции WEEK(). Для синтаксиса единственного параметра используется значение mode 0. В отличие от WEEK(), значение default_week_format не влияет на YEARWEEK().

    mysql> SELECT YEARWEEK('1987-01-01');
      -> 198652
    

    Отметьте, что номер недели отличается от номера из функции WEEK() (0) для дополнительных параметров 0 или 1, поскольку WEEK() тогда возвращает неделю в контексте данного года.

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 есть поддержка полнотекстовой индексации и поиска:

  • Полнотекстовое индексирование в MySQL это индекс типа FULLTEXT.

  • Полнотекстовый индекс может использоваться только с таблицами InnoDB или MyISAM и может быть составлен только для столбцов CHAR, VARCHAR или TEXT.
  • MySQL обеспечивает встроенный полнотекстовый анализатор ngram, который поддерживает китайский, японский и корейский (CJK) языки, а также устанавливаемый полнотекстовый плагин анализатора MeCab для японского языка. Различия обрисованы в общих чертах в разделах 13.9.8 и 13.9.9.
  • Индекс FULLTEXT может быть определен в CREATE TABLE, когда таблица составлена, или добавлен позднее, используя ALTER TABLE или CREATE INDEX.
  • Для больших наборов данных это намного быстрее, чтобы загрузить Ваши данные в таблицу, которая не имеет индекса FULLTEXT и создать индекс после этого, чем загрузить данные в таблицу, у которой он уже есть.

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

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

  • Поиск естественного языка интерпретирует строку поиска как фразу на естественном языке (фраза в свободном тексте). Нет никаких специальных операторов. Список стоп-слов применяется. Для получения дополнительной информации о списках стоп-слов см. раздел 13.9.4.

    Полнотекстовые поискы естественного языка, если модификатор дан IN NATURAL LANGUAGE MODE или если никакой модификатор не дан. Для получения дополнительной информации см. раздел 13.9.1.

  • Булев поиск интерпретирует строку поиска, используя правила специального языка запроса. Строка содержит слова для поиска. Это может также содержать операторы, которые определяют требования, таким образом, что слово должно присутствовать или отсутствовать в соответствующих строках, или что это должно иметь больший или меньший вес, чем обычно. Определенные общие слова (стоп-слов) опущены во время поиска по индексу и не соответствуют, если существуют в строке поиска. Модификатор IN BOOLEAN MODE определяет булев поиск.
  • Поиск расширения запроса модификация поиска естественного языка. Строка поиска используется, чтобы выполнить поиск естественного языка. Тогда слова самых соответствующих строк, возвращенных поиском, добавлены к строке поиска, и поиск сделан снова. Запрос возвращает строки из второго поиска. Модификатор IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION или WITH QUERY EXPANSION определяет поиск расширения запроса.

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.

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

  • Любое слово, которое слишком коротко, проигнорировано. Длина минимума значения по умолчанию слов, которые найдены полнотекстовыми поисками, является тремя символами для InnoDB и четыремя символами для MyISAM. Вы можете управлять сокращением, устанавливая параметр конфигурации прежде, чем создать индекс: параметр конфигурации для InnoDB innodb_ft_min_token_size или ft_min_word_len для MyISAM.

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

  • Слова в списке стоп-слов проигнорированы. Стоп-слово такое слово, как the или some, которое настолько распространено, что у него, как полагают, есть нулевое семантическое значение. Есть встроенный список стоп-слов, но он может быть перекрыт определяемым пользователем списком. Списки стоп-слов и связанные параметры конфигурации отличаются для InnoDB и MyISAM. Обработкой стоп-слов управляют параметры конфигурации innodb_ft_enable_stopword, innodb_ft_server_stopword_table и innodb_ft_user_stopword_table для for InnoDB и ft_stopword_file для MyISAM.

См. раздел 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 использует то, что иногда упоминается как подразумеваемая Булева логика, в которой:

  • + означает AND.

  • - означает NOT.
  • [отсутствие оператора] означает OR.

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

  • Они автоматически не сортируют строки в порядке уменьшающейся уместности.

  • Таблицы InnoDB требуют индекс FULLTEXT на всех столбцах выражения MATCH() , чтобы выполнить булевы запросы. Булевы запросы на поисковых индексах MyISAM могут работать даже без индекса FULLTEXT, хотя поиск, выполненный этим способом, был бы довольно медленным.
  • Минимальная и максимальная длина слова полнотекстовых параметров относится к индексам FULLTEXT, создаваемым с использованием встроенного анализатора FULLTEXT и плагина анализатора MeCab. innodb_ft_min_token_size и innodb_ft_max_token_size используются для поисковых индексов InnoDB. ft_min_word_len и ft_max_word_len используются для поисковых индексов MyISAM.

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

  • Список стоп-слов применяется, управляемый innodb_ft_enable_stopword, innodb_ft_server_stopword_table и innodb_ft_user_stopword_table для InnoDB или ft_stopword_file для MyISAM.
  • Полнотекстовый поиск InnoDB не поддерживает использование нескольких операторов на единственном слове поиска, как в этом примере: '++apple'. Использование нескольких операторов на единственном слове поиска возвращает синтаксическую ошибку. Полнотекстовый поиск MyISAM успешно обработает тот же самый поиск, игнорируя все операторы за исключением оператора, смежного со словом поиска.
  • Полнотекстовый поиск InnoDB поддерживает только символы плюс или минус. Например, InnoDB поддерживает '+apple', но не 'apple+'. Определение плюса или минуса в конце приводит к синтаксической ошибке.
  • Полнотекстовый поиск InnoDB не поддерживает использование ведущего знака плюс с подстановочным знаком ('+*') и комбинацию знак плюс и минус ('+-'). Эти недопустимые запросы возвращают синтаксическую ошибку.
  • Полнотекстовый поиск InnoDB не поддерживает использование символа @ в булевых полнотекстовых поисках. Символ @ зарезервирован для использования в операторе поиска близости @distance.
  • Они не используют 50% порог, который относится к поисковым индексам MyISAM.

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

  • +

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

  • -

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

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

  • (no operator)

    По умолчанию (когда ни + ни - не заданы), слово является дополнительным, но строки, которые содержат его, оценены выше. Это подражает поведению MATCH() ... AGAINST() без модификатора IN BOOLEAN MODE.

  • @distance

    Этот оператор работает только на таблицах InnoDB. Это проверяет, начинаются ли два или больше слов в пределах указанного расстояния друг от друга, измеренного в словах. Определите слова поиска в двойных кавычках немедленно перед оператором @distance , например, MATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE).

  • > <

    Эти два оператора используются, чтобы изменить вклад слова в значение уместности, которое назначено строке. Оператор > увеличивает вклад, а < уменьшает.

  • ( )

    Слова в круглых скобках группируются в подвыражения. Могут быть вложены.

  • ~

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

  • *

    Звездочка служит усечением (или подстановочным знаком). В отличие от других операторов, это добавлено к слову, которое будет затронуто. Слова соответствуют, если они начинаются со слова, предшествующего *.

    Если слово определено с оператором усечения, он не обрезается от булева запроса, даже если это слишком коротко или стоп-слово. Слишком короткое слово, определено в innodb_ft_min_token_size для InnoDB или ft_min_word_len для MyISAM. Эти опции неприменимы к индексам FULLTEXT, использующим анализатор ngram.

    Слово со звездочкой рассматривают как приставку, которая должна присутствовать в начале одного или более слов. Если минимальная длина слова 4, поиск '+слово +the*' может возвратить меньше строк, чем поиск '+слово +the', потому что второй запрос игнорирует также короткий критерий поиска the.

  • "

    Фразе, которая указана в пределах двоичной кавычки (") соответствуют только строки, которые содержат фразу как она написана. Полнотекстовый механизм разделяет фразу на слова и выполняет поиск в индексах FULLTEXT для всех слов. Символы, не являющиеся словами, не должны быть соответствующими точно: поиск фразы требует, чтобы соответствия содержали точно те же самые слова, что и фраза, и в том же самом порядке. Например, "test phrase" соответствует "test, phrase".

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

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

  • 'apple banana'

    Найдет строки, которые содержат по крайней мере одно из этих двух слов.

  • '+apple +juice'

    Найдет строки, которые содержат оба слова.

  • '+apple macintosh'

    Найдет строки, которые содержат слово apple, но вес строк выше, если они также содержат macintosh.

  • '+apple -macintosh'

    Найдет строки, которые содержат слово apple, но не macintosh.

  • '+apple ~macintosh'

    Найдет строки, которые содержат слово apple, но если строка также содержит macintosh, ее вес ниже, чем если бы строка его не включала. Это мягче, чем поиск '+apple -macintosh', для которого присутствие macintosh не вернет строку вообще.

  • '+apple +(>turnover <strudel)'

    Найдет строки, которые содержат слова apple и turnover, или apple и strudel (в любом порядке), но вес apple turnover выше, чем apple strudel .

  • 'apple*'

    Найдет строки, которые содержат слова, такие как apple, apples, applesauce или applet.

  • '"some words"'

    Найдет строки, которые содержат точную фразу some words (например, строки, которые содержат some words of wisdom, но не some noise words). Отметьте, что символы " являются символами оператора, которые разграничивают фразу. Они не кавычки, которые прилагают строку поиска непосредственно.

Ранжирование уместности для режима 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. Полнотекстовые ограничения

  • Полнотекстовые поиски поддержаны только для таблиц типов InnoDB и MyISAM.

  • Полнотекстовые поиски не поддержаны для разделенных таблиц. См. раздел 20.6.
  • Полнотекстовые поиски могут использоваться с большинством многобайтовых наборов символов. Исключение то, что для Unicode может использоваться набор символов utf8, но не ucs2. Хотя индексы FULLTEXT на столбцах ucs2 не могут использоваться, Вы можете применить поиск IN BOOLEAN MODE на столбцах ucs2 без индекса.

    Замечания для utf8 также касаются utf8mb4, а для ucs2 применимы к utf16, utf16le и utf32.

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

    Символьно-ориентированный полнотекстовый анализатор ngram, который поддерживает китайский, японский и корейский (CJK) язык, и основанный на слове плагин анализатора MeCab, который поддерживает японский язык, обеспечены для использования с таблицами InnoDBи MyISAM.

  • Хотя использование нескольких наборов символов в пределах единственной таблицы поддержано, все столбцы в индексе FULLTEXT должны использовать тот же самый набор символов и сопоставление.
  • Список столбцов в MATCH() должен точно соответствовать списку столбцов в некоторых индексах FULLTEXT определенных для таблицы, если это MATCH() в IN BOOLEAN MODE на таблице MyISAM. Для таблиц MyISAM поиски в режиме boolean могут быть сделаны на неиндексированных столбцах, хотя они, вероятно, будут медленными.
  • Параметром AGAINST() должно быть строковое значение, которое является постоянным во время оценки запроса. Это исключает, например, столбец таблицы, потому что это может отличаться для каждой строки.
  • Индексные подсказки более ограничены для поисков FULLTEXT, чем для не-FULLTEXT. См. раздел 9.9.4.
  • Для InnoDB все операции DML (INSERT, UPDATE, DELETE) с вовлечением столбцов с полнотекстовым индексом обработаны в момент закрытия транзакции. Например, для INSERT вставленная строка размечена на отдельные слова и анализируется. Отдельные слова добавлены к полнотекстовому индексу таблицы, когда транзакция закрыта. В результате полнотекстовые поиски возвращают только переданные данные.
  • Символ '%' не поддержан для полнотекстовых поисков.

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. Предположите, что Вы хотите обработать символ дефиса ('-') как символ слова. Используйте один из этих методов:

  • Модификация исходных текстов MySQL: в storage/innobase/handler/ha_innodb.cc (для InnoDB) или в storage/myisam/ftdefs.h (для MyISAM) найдите макросы true_word_char() и misc_word_char(). Добавьте '-' к одному из них и пересоберите MySQL.

  • Измените файл набора символов: это не требует никакой перекомпиляции. Макрос true_word_char() использует таблицу character type, чтобы отличить буквы и цифры от других символов. Вы может отредактировать содержание массива <ctype><map> в одном из XML-файлов набора символов, чтобы определить '-' как букву. Тогда используйте данный набор символов для Вашего индекса FULLTEXT. Для информации о формате массива <ctype><map> см. раздел 11.3.1.
  • Добавьте новое сопоставление для набора символов, используемого индексированными столбцами, и измените столбцы, чтобы использовать это сопоставление. Для общей информации о добавлении сопоставлений см. раздел 11.4. Для примера, определенного для полнотекстовой индексации, см. раздел 13.9.7.

Пересоздание полнотекстового индекса 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 может быть установлена как часть строки запуска или в конфигурационном файле:

  • Строка запуска:

    mysqld --ngram_token_size=2
    
  • Конфигурационный файл:
    [mysqld]
    ngram_token_size=2
    

Следующие параметры конфигурации длины слова проигнорированы для индексов 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 устраняет пробелы, разбирая текст. Например:

  • ab cd разобрано как ab, cd.

  • a bc разобрано как bc.

Обработка стоп-слов в 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, начинающиеся с термина приставки. Например, при ngram_token_size=2 поиск a* возвращает все строки, начинающиеся с a.

  • Если понятие приставки подстановочного поиска более длинно чем маркерный размер, термин приставки преобразован в ngram-фразу, а подстановочный оператор проигнорирован. Например, при ngram_token_size=2 abc* превратится в ab bc.

Поиск фразы в 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, поддерживают следующие наборы символов.

    • Словарь ipadic_euc-jp поддерживает наборы символов ujis и eucjpms.

    • Словарь ipadic_sjis поддерживает наборы символов sjis и cp932.
    • Словарь ipadic_utf-8 поддерживает наборы символов utf8 и utf8mb4.

    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). Например:

  • Если Вы преобразовываете нулевую строку даты к дате, CONVERT() и CAST() возвратят NULL с предупреждением, когда включен режим SQL NO_ZERO_DATE.

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

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

  • BINARY expr

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

    mysql> SELECT 'a' = 'A';
      -> 1
    mysql> SELECT BINARY 'a' = 'A';
      -> 0
    mysql> SELECT 'a' = 'a ';
      -> 1
    mysql> SELECT BINARY 'a' = 'a ';
      -> 0
    

    В сравнении BINARY затрагивает всю работу: это может быть задано перед любым операндом с тем же самым результатом.

    В целях преобразования строковое выражение в двоичную строку, эти конструкции эквивалентны:

    BINARY expr
    CAST(expr AS BINARY)
    CONVERT(expr USING BINARY)
    

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

    mysql> SELECT 'a' = 'A';
      -> 1
    mysql> SELECT _binary 'a' = 'A';
      -> 0
    

    Оператор BINARY в выражениях отличается в действительности от признака BINARY в символьных определениях столбца. Символьный столбец, определенный с признаком BINARY имеет назначенный табличный набор символов по умолчанию и двоичное (_bin) сопоставление для того набора символов. У каждого недвоичного набора символов есть сопоставление _bin. Например, двоичное сопоставление для набора символов utf8 utf8_bin, так, если табличный набор символов по умолчанию utf8, эти определения двух столбцов эквивалентны:

    CHAR(10) BINARY
    CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
    

    Использование CHARACTER SET binary в определении CHAR, VARCHAR или TEXT заставляет столбец быть обработанным как соответствующий двоичной строковый тип данных. Например, следующие пары определений эквивалентны:

    CHAR(10) CHARACTER SET binary
    BINARY(10)
    
    VARCHAR(10) CHARACTER SET binary
    VARBINARY(10)
    
    TEXT CHARACTER SET binary
    BLOB
    
  • CAST(expr AS type)

    Функция CAST() берет выражение любого типа и производит значение результата указанного типа, подобно CONVERT().

    CAST() стандартный синтаксис SQL.

  • CONVERT(expr, type), CONVERT(expr USING transcoding_name)

    Функция CONVERT() берет выражение любого типа и производит значение результата указанного типа.

    Обсуждение синтаксиса CONVERT(expr, type) также относится к CAST(expr AS type), которая эквивалентна.

    CONVERT(... USING ...) стандартный синтаксис SQL. Форма CONVERT() без USING синтаксис ODBC.

    CONVERT() с USING переводит между различными наборами символов. В MySQL транскодирующие имена то же самое, что и соответствующие имена набора символов. Например, этот запрос преобразовывает строку 'abc' в наборе символов по умолчанию к соответствующей строке в наборе символов utf8:

    SELECT CONVERT('abc' USING utf8);
    

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

    • BINARY[(N)]

      Производит строку с типом данных BINARY. См. раздел 12.4.2 для описания того, как это затрагивает сравнения. Если длина N задана, BINARY(N) заставляет преобразование использовать не больше, чем N байтов параметра. Значения короче, чем N байтов дополнены with 0x00 до длины N.

    • CHAR[(N)] [charset_info]

      Производит строку типа CHAR. Если длина optional length N задана, CHAR(N) заставляет преобразование использовать не больше, чем N байтов параметра. Никакого дополнения не происходит для значений короче, чем N.

      Без charset_info CHAR производит строку с набором символов по умолчанию. Чтобы определить набор символов явно, значения charset_info разрешены:

      • CHARACTER SET charset_name: Производит строку с данным набором символов.

      • ASCII: Сокращение для CHARACTER SET latin1.
      • UNICODE: Сокращение для CHARACTER SET ucs2.

      Во всех случаях у строки есть сопоставление по умолчанию для набора символов.

    • DATE

      Производит значение DATE.

    • DATETIME

      Производит значение DATETIME .

    • DECIMAL[(M[,D])]

      Производит значение DECIMAL . Если дополнительные параметры M и D заданы, они определяют максимальное количество цифр (точность) и число цифр после десятичной запятой (масштаб).

    • JSON

      Производит значение JSON.

    • NCHAR[(N)]

      Аналогично CHAR, но производит строку с национальным набором символов. См. раздел 11.1.3.7.

      В отличие от CHAR, NCHAR не разрешает сопроводительную информацию о наборе символов, которая будет определена.

    • SIGNED [INTEGER]

      Производит значение signed integer.

    • TIME

      Производит значение TIME.

    • UNSIGNED [INTEGER]

      Производит значение unsigned integer.

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):

  • Пользовательские переменные (слабая проверка). Переменные, использующие синтаксис $@variable_name (то есть, пользовательские переменные), не проверены. Никакие предупреждения или ошибки не созданы сервером, если переменная имеет неправильный тип или не было ранее значение назначено. Это также означает, что пользователь полностью ответственен за любые типографские ошибки, так как никакие предупреждения не будут даны если (например) $@myvariabl используется вместо $@myvariable.

    Пример:

    mysql> SET @xml = '<a><b>X</b><b>Y</b></a>';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET @i =1, @j = 2;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @i, ExtractValue(@xml, '//b[$@i]');
    +----+--------------------------------+
    | @i | ExtractValue(@xml, '//b[$@i]') |
    +----+--------------------------------+
    | 1  | X                              |
    +----+--------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT @j, ExtractValue(@xml, '//b[$@j]');
    +----+--------------------------------+
    | @j | ExtractValue(@xml, '//b[$@j]') |
    +----+--------------------------------+
    | 2  | Y                              |
    +----+--------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT @k, ExtractValue(@xml, '//b[$@k]');
    +------+--------------------------------+
    | @k   | ExtractValue(@xml, '//b[$@k]') |
    +------+--------------------------------+
    | NULL |                                |
    +------+--------------------------------+
    1 row in set (0.00 sec)
    
  • Переменные в сохраненных программах (сильная проверка). Переменные, использующие синтаксис $variable_name могут быть объявлены и использоваться с этими функциями, когда их называют внутренними сохраненными программами. Такие переменные являются локальными к сохраненной программе, в которой они определены, они сильно проверены на тип и значение.

    Пример:

    mysql> DELIMITER |
    mysql> CREATE PROCEDURE myproc ()
        -> BEGIN
        ->   DECLARE i INT DEFAULT 1;
        ->   DECLARE xml VARCHAR(25) DEFAULT '<a>X</a><a>Y</a><a>Z</a>';
        ->
        ->   WHILE i < 4 DO
        -> SELECT xml, i, ExtractValue(xml, '//a[$i]');
        -> SET i = i+1;
        ->   END WHILE;
        -> END |
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> DELIMITER ;
    mysql> CALL myproc();
    +--------------------------+---+------------------------------+
    | xml                      | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 1 | X  |
    +--------------------------+---+------------------------------+
    1 row in set (0.00 sec)
    
    +--------------------------+---+------------------------------+
    | xml                      | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 2 | Y  |
    +--------------------------+---+------------------------------+
    1 row in set (0.01 sec)
    
    +--------------------------+---+------------------------------+
    | xml                      | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 3 | Z  |
    +--------------------------+---+------------------------------+
    1 row in set (0.01 sec)
    

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

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

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

  • ExtractValue( xml_frag, xpath_expr)

    ExtractValue() берет два строковых параметра, фрагмент разметки XML xml_frag и выражение XPath xpath_expr (также именуемое locator). Это возвращает текст (CDATA) из первого текстового узла, который является дочерним элементом или элементом, соответствующим выражениею XPath.

    Использование этой функции эквивалентно выполнению соответствия, используя xpath_expr после добавления /text(). Другими словами, ExtractValue('<a><b>Sakila</b></a>', '/a/b') и ExtractValue('<a><b>Sakila</b></a>', '/a/b/text()') приведут к тому же самому результату.

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

    Если никакой текстовый узел соответствия не найден для выражения (включая неявное /text()) по любой причине, пока xpath_expr верно, а xml_frag состоит из элементов, которые должным образом вложены и закрыты, вернется пустая строка. Никакое различие не сделано между соответствием на пустом элементе и никаким соответствием вообще.

    Если Вы должны определить, не был ли элемент соответствия найден в in xml_frag или такой элемент был найден, но не содержал дочерних текстовых узлов, Вы должны проверить результат выражения, которое использует функция XPath count(). Например, оба эти запроса возвращают пустую строку, как показано:

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

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

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

    ExtractValue() возвращает только CDATA, и не возвращает ни тегов, которые могли бы содержаться в пределах соответствующего тега, ни любого их контента (результат возвратится как val1 в следующем примере).

    mysql> SELECT
      ->   ExtractValue('<a>ccc<b>ddd</b></a>', '/a') AS val1,
      ->   ExtractValue('<a>ccc<b>ddd</b></a>', '/a/b') AS val2,
      ->   ExtractValue('<a>ccc<b>ddd</b></a>', '//b') AS val3,
      ->   ExtractValue('<a>ccc<b>ddd</b></a>', '/b') AS val4,
      ->   ExtractValue('<a>ccc<b>ddd</b><b>eee</b></a>', '//b') AS val5;
    +------+------+------+------+---------+
    | val1 | val2 | val3 | val4 | val5    |
    +------+------+------+------+---------+
    | ccc  | ddd  | ddd  |      | ddd eee |
    +------+------+------+------+---------+
    

    Эта функция использует текущее сопоставление SQL для того, чтобы сделать сравнения с contains(), выполняя тоже самое сопоставление как другие строковые функции (такие, как CONCAT()), принимая во внимание сопоставление их аргументов, см. раздел 11.1.8.4 для объяснения правил, управляющих этим поведением.

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

    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)
    
  • UpdateXML(xml_target , xpath_expr, new_xml)

    Эта функция заменяет единственную часть данного фрагмента XML xml_target на новый new_xml и затем возвращает измененный XML. Часть xml_target соответствует выражению XPath xpath_expr.

    Если никакое соответствие выражения xpath_expr не найдено, или если многократные соответствия найдены, функция возвращает оригинальный фрагмент xml_target. Все три параметра должны быть строками.

    mysql> SELECT
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1,
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2,
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3,
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4,
        ->   UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5
        -> \G
    
    *************************** 1. row ***************************
    val1: <e>fff</e>
    val2: <a><b>ccc</b><d></d></a>
    val3: <a><e>fff</e><d></d></a>
    val4: <a><b>ccc</b><e>fff</e></a>
    val5: <a><d></d><b>ccc</b><d></d></a>
    

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

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

  • /tag

    Соответствует <tag/>, если и только если <tag/> элемент корня.

    Пример: /a имеет соответствие в <a><b/></a> потому что это соответствует наиболее удаленному (корневому) тегу. Это не соответствует внутреннему элементу a в <b><a/></b> потому что в этом случае это дочерний элемент другого элемента.

  • /tag1/tag2

    Соответствует <tag2/>, если и только если это дочерний элемент <tag1/> и <tag1/> элемент корня.

    Пример: /a/b соответствует элементу b в фрагменте XML <a><b/></a> потому что это дочерний элемент элемента корня a. У этого нет соответствия в <b><a/></b> потому что в этом случае b элемент корня (и следовательно дочерний элемент никакого другого элемента). И при этом у выражения XPath нет соответствия в <a><c><b/></c></a>: здесь b потомок a, но не фактический дочерний элемент a.

    Эта конструкция является растяжимой к трем или больше элементам. Например, выражение XPath /a/b/c соответствует элементу c во фрагменте <a><b><c/></b></a>.

  • //tag

    Соответствует любому экземпляру <tag>.

    Пример: //a соответствует элементу a в любом из: <a><b><c/></b></a>; <c><a><b/></a></b>; <c><b><a/></b></c>.

    // может быть объединен с /. Например, //a/b соответствует элементу b в любом из фрагментов <a><b/></a> или <a><b><c/></b></a>.

    //tag эквивалент /descendant-or-self::*/tag. Распространенная ошибка состоит в том, чтобы перепутать это с /descendant-or-self::tag, хотя последнее выражение может фактически привести к совсем другим результатам:

    mysql> SET @xml = '<a><b><c>w</c><b>x</b><d>y</d>z</b></a>';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @xml;
    +-----------------------------------------+
    | @xml                                    |
    +-----------------------------------------+
    | <a><b><c>w</c><b>x</b><d>y</d>z</b></a> |
    +-----------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '//b[1]');
    +------------------------------+
    | ExtractValue(@xml, '//b[1]') |
    +------------------------------+
    | x z                          |
    +------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '//b[2]');
    +------------------------------+
    | ExtractValue(@xml, '//b[2]') |
    +------------------------------+
    |                              |
    +------------------------------+
    1 row in set (0.01 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[1]');
    +---------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::*/b[1]') |
    +---------------------------------------------------+
    | x z                                               |
    +---------------------------------------------------+
    1 row in set (0.06 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[2]');
    +---------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::*/b[2]') |
    +---------------------------------------------------+
    |                                                   |
    +---------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[1]');
    +-------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::b[1]') |
    +-------------------------------------------------+
    | z                                               |
    +-------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[2]');
    +-------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::b[2]') |
    +-------------------------------------------------+
    | x                                               |
    +-------------------------------------------------+
    1 row in set (0.00 sec)
    
  • Оператор * действует как подстановка, которая соответствует любому элементу. Например, выражение /*/b соответствует элементу b в любом из фрагментов XML <a><b/></a> или <c><b/></c>. Однако, выражение не производит соответствие во фрагменте <b><a/></b> потому что b должен быть дочерним элементом некоторого другого элемента. Подстановочный знак может использоваться в любой позиции: выражение /*/b/* будет соответствовать любому дочернему элементу b, который является самостоятельно не элементом корня.

  • Вы можете соответствовать любому из нескольких локаторов, используя оператор | (UNION). Например, выражение //b|//c соответствует всем элементам b и c в цели XML.
  • Также возможно соответствовать элементу, основываясь на значении одного или больше его признаков. Это сделано через использование синтаксиса tag[@attribute=" value"]. Например, выражение //b[@id="idB"] соответствует второму элементу b во фрагменте <a><b id="idA"/><c/><b id="idB"/></a> . Чтобы соответствовать любому элементу, имеющему attribute="value" , используйте выражение XPath //*[attribute="value"] .

    Чтобы фильтровать многократные значения атрибута, просто используйте многократные пункты сравнения признака по очереди. Например, выражение //b[@c="x"][@d="y"] соответствует элементу <b c="x" d="y"/> где угодно в данном фрагменте XML.

    Чтобы найти элементы, для которых тот же самый признак соответствует любому из нескольких значений, Вы можете использовать много локаторов, к которым присоединяется оператор |. Например, чтобы соответствовать всем элементам b, чей признак c имеет значение 23 или 17, используют выражение //b[@c="23"]|//b[@c="17"]. Вы можете также использовать логический оператор or: //b[@c="23" or @c="17"].

    Различие между or и | в том, что or объединяет условия, а | наборы результатов.

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

  • Сравнение Nodeset-to-nodeset (такое, как '/a/b[@c=@d]') не поддержано.

  • Все стандартные операторы сравнения XPath поддержаны (Bug #22823).
  • Относительные выражения локатора решены в контексте корневого узла. Например, рассмотрите следующий запрос и результат:
    mysql> SELECT ExtractValue(
        ->   '<a><b c="1">X</b><b c="2">Y</b></a>',
        ->'a/b'
        -> ) AS result;
    +--------+
    | result |
    +--------+
    | X Y    |
    +--------+
    1 row in set (0.03 sec)
    

    В этом случае локатор a/b приведет к /a/b.

    Относительные локаторы также поддержаны в пределах предикатов. В следующем примере d[../@c="1"] решен как /a/b[@c="1"]/d:

    mysql> SELECT ExtractValue(
        ->'<a>
        ->  <b c="1"><d>X</d></b>
        ->  <b c="2"><d>X</d></b>
        -></a>',
        ->'a/b/d[../@c="1"]')
        -> AS result;
    +--------+
    | result |
    +--------+
    | X      |
    +--------+
    1 row in set (0.00 sec)
    
  • Префиксы локаторов с выражениями, которые оценивают как скалярные значения, включая ссылки на переменные, литералы, числа и вызовы скалярных функций, не разрешены, и их результаты ошибочны.
  • Оператор :: не поддержан в комбинации с типами узла, такими как следующие:

    • axis::comment()

    • axis::text()
    • axis::processing-instructions()
    • axis::node()

    Однако, имена тестов (такие, как axis::name и axis::*) поддержаны, как показано в этих примерах:

    mysql> SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b');
    +-------------------------------------------------------+
    | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b') |
    +-------------------------------------------------------+
    | x                                                     |
    +-------------------------------------------------------+
    1 row in set (0.02 sec)
    
    mysql> SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*');
    +-------------------------------------------------------+
    | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*') |
    +-------------------------------------------------------+
    | x y                                                   |
    +-------------------------------------------------------+
    1 row in set (0.01 sec)
    
  • Навигация Up-and-down не поддержана в случаях, когда путь привел бы в элемент корня. Таким образом, Вы не можете использовать выражения, которые соответствуют на потомках предков данного элемента, где один или больше предков текущего элемента также предок элемента корня (см. Bug #16321).
  • Следующие функции XPath не поддержаны или имеют проблемы:

    • id()

    • lang()
    • local-name()
    • name()
    • namespace-uri()
    • normalize-space()
    • starts-with()
    • string()
    • substring-after()
    • substring-before()
    • translate()

  • Следующие axes не поддержаны:

    • following-sibling

    • following
    • preceding-sibling
    • preceding

Выражения 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.

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

  • |

    Поразрядный OR:

    mysql> SELECT 29 | 15;
        -> 31
    

    Результат unsigned 64-bit integer.

  • &

    Поразрядный AND:

    mysql> SELECT 29 & 15;
        -> 13
    

    Результат unsigned 64-bit integer.

  • ^

    Поразрядный XOR:

    mysql> SELECT 1 ^ 1;
      -> 0
    mysql> SELECT 1 ^ 0;
      -> 1
    mysql> SELECT 11 ^ 3;
      -> 8
    

    Результат unsigned 64-bit integer.

  • <<

    Смещает longlong число (BIGINT ) влево.

    mysql> SELECT 1 << 2;
      -> 4
    

    Результат unsigned 64-bit integer. Значение является усеченным к 64 битам. В частности, если количество сдвига больше или равно ширине числа unsigned 64-bit, результатом будет 0.

  • >>

    Смещает longlong число (BIGINT ) вправо.

    mysql> SELECT 4 >> 2;
      -> 1
    

    Результат unsigned 64-bit integer. Значение является усеченным к 64 битам. В частности, если количество сдвига больше или равно ширине числа unsigned 64-bit, результатом будет 0.

  • ~

    Инвертирует все биты.

    mysql> SELECT 5 & ~1;
      -> 4
    

    Результат unsigned 64-bit integer.

  • BIT_COUNT(N )

    Возвращает число битов, которые установлены в параметре N.

    mysql> SELECT BIT_COUNT(29), BIT_COUNT(b'101010');
        -> 4, 3
    

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. Чтобы избежать этих типов проблем, приложения могут зашифровать чувствительные значения на стороне клиента прежде, чем послать их серверу. Те же самые соображения относятся к ключам шифрования. Чтобы избежать выставлять их, приложения могут использовать хранимые процедуры, чтобы зашифровать и дешифровать значения на стороне сервера.

  • AES_DECRYPT( crypt_str,key_str[, init_vector])

    Эта функция дешифрует данные, используя официальный алгоритм AES (Advanced Encryption Standard).

    Дополнительный векторный параметр инициализации init_vector. Запросы, применяющие AES_DECRYPT(), опасны для репликации на основе запросов и не могут быть сохранены в кэше запроса.

  • AES_ENCRYPT(str ,key_str[,init_vector ])

    AES_ENCRYPT() и AES_DECRYPT() реализуют шифрование и дешифрование данных, используя официальный алгоритм AES (Advanced Encryption Standard), ранее известный как Rijndael. Стандарт AES разрешает различные длины ключа. По умолчанию эти функции осуществляют AES с 128-битной длиной ключа. Длины ключа 196 или 256 битов могут использоваться, как описано позже. Длина ключа компромисс между скоростью работы и безопасностью.

    AES_ENCRYPT() шифрует строку str с использованием ключевой строки key_str и возвращает двоичную строку, содержащую зашифрованный вывод. AES_DECRYPT() дешифрует зашифрованную строку crypt_str с использованием ключевой строки key_str и возвращает оригинальную строку открытого текста. Если любой функциональный параметр NULL, функция вернет NULL.

    Параметры str и crypt_str могут быть любой длины, дополнение автоматически добавлено к str, чтобы это было кратным числом блоков, как требуется основанными на блоке алгоритмами, такими как AES. Это дополнение автоматически удалено AES_DECRYPT(). Длина crypt_str может быть вычислена, используя эту формулу:

    16 * (trunc(string_length / 16) + 1)
    

    Для длины ключа 128 бит самый безопасный способ передать ключ в key_str это создать действительно случайную 128-битную последовательность и передать это как двоичное значение. Например:

    INSERT INTO t VALUES (1,AES_ENCRYPT('text',
           UNHEX('F3229A0B371ED2D9441B830D21A390C3')));
    

    Пароль может использоваться, чтобы произвести ключ AES, хешируя пароль. Например:

    INSERT INTO t VALUES (1,AES_ENCRYPT('text',
           UNHEX(SHA2('My secret passphrase',512))));
    

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

    Если AES_DECRYPT() обнаруживает недопустимые данные или неправильное дополнение, она возвращает NULL. Однако, возможно для AES_DECRYPT() возвратить не NULL, если входные данные или ключ недопустимы.

    AES_ENCRYPT() и AES_DECRYPT() допускают управление режимом блочного шифрования и берут дополнительный векторный параметр инициализации init_vector:

    • Системная переменная block_encryption_mode управляет режимом для основанных на блоке алгоритмов шифрования. Ее значение по умолчанию aes-128-ecb, которое показывает шифрование, используя длину ключа 128 битов и режим ECB. Для описания разрешенных значений этой переменной см. раздел 6.1.5.

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

    Для режимов, которые требуют дополнительного параметра init_vector, это должны быть 16 байт или больше (байты сверх 16 проигнорированы). Ошибка происходит, если init_vector отсутствует.

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

    Случайная строка байт, чтобы использовать для вектора инициализации, может быть произведена вызовом RANDOM_BYTES(16). Для режимов шифрования, которые требуют вектор инициализации, тот же самый вектор должен использоваться для шифрования и дешифрования.

    mysql> SET block_encryption_mode = 'aes-256-cbc';
    mysql> SET @key_str = SHA2('My secret passphrase',512);
    mysql> SET @init_vector = RANDOM_BYTES(16);
    mysql> SET @crypt_str = AES_ENCRYPT('text',@key_str,@init_vector);
    mysql> SELECT AES_DECRYPT(@crypt_str,@key_str,@init_vector);
    +-----------------------------------------------+
    | AES_DECRYPT(@crypt_str,@key_str,@init_vector) |
    +-----------------------------------------------+
    | text                                          |
    +-----------------------------------------------+
    

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

    Режим блочного шифрования Поддерживается библиотеками SSL Нужен ли вектор инициализации?
    ECBOpenSSL, yaSSLНет
    CBCOpenSSL, yaSSLДа
    CFB1OpenSSLДа
    CFB8OpenSSLДа
    CFB128OpenSSLДа
    OFBOpenSSLДа

    Запросы, использующие AES_ENCRYPT() или AES_DECRYPT() опасны для основанной на запросах репликации и не могут быть сохранены в кэше запроса.

  • COMPRESS( string_to_compress)

    Сжимает строку и возвращает результат как двоичную строку. Эта функция требует, чтобы MySQL был собран с библиотекой сжатия такой, как zlib. Иначе, возвращаемое значение всегда NULL. Сжатая строка может быть расжата UNCOMPRESS().

    mysql> SELECT LENGTH(COMPRESS(REPEAT('a',1000)));
      -> 21
    mysql> SELECT LENGTH(COMPRESS(''));
      -> 0
    mysql> SELECT LENGTH(COMPRESS('a'));
      -> 13
    mysql> SELECT LENGTH(COMPRESS(REPEAT('a',16)));
      -> 15
    

    Сжатое строковое содержание сохранено следующим путем:

    • Пустые строки сохранены как пустые строки.

    • Непустые строки сохранены как 4-байтовая длина несжатой строки (младший байт сначала), сопровождаемая сжатой строкой. Если строка заканчивается пробелом, дополнительный символ . добавлен, чтобы избежать проблемы с обрезкой концевых пробелов, если результат будет сохранен в столбце CHAR или VARCHAR. Однако, использование недвоичных строковых типов данных CHAR или VARCHAR, чтобы сохранить сжатые строки не рекомендуется потому, что преобразование набора символов может произойти. Используйте двоичной строковый столбец VARBINARY или BLOB вместо этого.

  • DECODE(crypt_str ,pass_str)

    DECODE() дешифрует зашифрованную строку crypt_str с использованием pass_str как пароля. crypt_str должна быть строкой, возвращенной из ENCODE().

    Функции ENCODE() и DECODE() устарели в MySQL 8.0, будут удалены в будущем выпуске MySQL и больше не должны использоваться. Рассмотрите использование вместо них AES_ENCRYPT() и AES_DECRYPT().

  • DES_DECRYPT( crypt_str[,key_str])

    Дешифрует строку, зашифрованную с помощью DES_ENCRYPT(). Если ошибка происходит, эта функция возвращает NULL.

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

    Если нет параметра key_str, DES_DECRYPT() исследует первый байт зашифрованной строки, чтобы определить ключевое число DES, которое использовалось, чтобы зашифровать оригинальную строку, затем читает ключ из ключевого файла DES, чтобы дешифровать сообщение. Для того, чтобы работать, пользователь должен иметь привилегию SUPER. Ключевой файл может быть определен с помощью опции сервера --des-key-file .

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

    Если параметр crypt_str не зашифрованная строка, MySQL возвращает crypt_str.

    Функции DES_ENCRYPT() и DES_DECRYPT() устарели, будут удалены в будущем выпуске MySQL и больше не должны использоваться. Рассмотрите использование вместо них AES_ENCRYPT() и AES_DECRYPT().

  • DES_ENCRYPT(str [,{key_num|key_str}])

    Шифрует строку с данным ключом, используя алгоритм Triple-DES.

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

    Ключ шифрования выбирается на основании второго параметра DES_ENCRYPT(), если он задан. Без параметра используется первый ключ из ключевого файла DES. С параметром key_num данное ключевое число (от 0 до 9) из ключевого файла DES используется. С параметром key_str данная ключевая строка используется, чтобы зашифровать str.

    Ключевой файл может быть определен с помощью опции сервера --des-key-file .

    Строка возвращения двоичная строка, где первый символ CHAR(128 | key_num ). Если ошибка происходит, DES_ENCRYPT() вернет NULL.

    Эти 128 добавлены, чтобы облегчить распознавание зашифрованного ключа. Если Вы используете строковый ключ, key_num 127.

    Строковая длина для результата дана этой формулой:

    new_len = orig_len +
                                    (8-(orig_len % 8))+1
    

    У каждой строки в ключевом файле DES есть следующий формат:

    key_num des_key_str
    

    Каждое значение key_num должно быть числом в диапазоне от 0 до 9. Строки в файле могут быть в любом порядке. des_key_str строка, которая используется, чтобы зашифровать сообщение. Должен быть по крайней мере один пробел между числом и ключом. Первый ключ задает значение по умолчанию, которое используется, если Вы не определяете ключевого параметра DES_ENCRYPT().

    Вы можете сказать MySQL читать новые значения ключа из ключевого файла запросом FLUSH DES_KEY_FILE. Это требует привилегию RELOAD .

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

    Функции DES_ENCRYPT() и DES_DECRYPT() устарели будут удалены в будущем выпуске MySQL и больше не должны использоваться. Рассмотрите использование вместо них AES_ENCRYPT() и AES_DECRYPT().

    mysql> SELECT customer_address FROM customer_table
         >        WHERE crypted_credit_card = DES_ENCRYPT('credit_card_number');
    
  • ENCODE(str, pass_str)

    ENCODE() шифрует str с использованием pass_str как пароля. Результат двоичная строка той же самой длины, что и str. Чтобы дешифровать результат, надо использовать DECODE() .

    Функции ENCODE() и DECODE() устарели в MySQL 8.0 будут удалены в будущем выпуске MySQL и больше не должны использоваться.

    Если Вы все еще должны использовать ENCODE(), значение salt должно использоваться с ней, чтобы уменьшить риск. Например:

    ENCODE('cleartext', CONCAT('my_random_salt','my_secret_password'))
    

    Новое случайное значение должно использоваться всякий раз, когда пароль обновлен.

  • ENCRYPT(str[, salt])

    Шифрует str с использование системного вызова Unix crypt() и возвращает двоичную строку. Параметр salt должен быть строкой по крайней мере с двумя символами, или результат будет NULL. Если нет параметра salt, случайное значение используется.

    Функция ENCRYPT() устарела будет удалена в будущем выпуске MySQL и больше не должна использоваться. Рассмотрите использование вместо нее AES_ENCRYPT().

    mysql> SELECT ENCRYPT('hello');
        -> 'VxuFAJXVARROc'
    

    ENCRYPT() игнорирует все кроме первых восьми символов str, по крайней мере, на некоторых системах. Это поведение определено выполнением основного системного вызова crypt().

    Использование ENCRYPT() с многобайтовыми наборами символов ucs2, utf16, utf16le или utf32 не рекомендуются, потому что системный вызов ожидает строку, законченную нулевым байтом.

    Если crypt() не доступно на Вашей системе (как имеет место в Windows), ENCRYPT() всегда возвращает NULL.

  • MD5(str)

    Вычисляет 128-битную контрольную сумму MD5 для строки. Значение возвращено как строка из 32 шестнадцатеричных цифр или NULL, если параметр был NULL. Возвращаемое значение может, например, использоваться в качестве ключа хеша. См. примечания в начале этого раздела о хранении значений хеша эффективно.

    Возвращаемое значение недвоичная строка в наборе символов соединения.

    mysql> SELECT MD5('testing');
      -> 'ae2b1fca515949e5d54fb22b8ed95575'
    

    Это RSA Data Security, Inc. MD5 Message-Digest Algorithm.

  • PASSWORD(str )

    Эта функция устарела и будет удалена в будущем выпуске MySQL.

    Возвращает хешированную строку пароля, вычисленную из пароля открытого текста str. Возвращаемое значение недвоичная строка в наборе символов соединения или NULL, если параметр NULL. Эта функция интерфейс SQL к алгоритму, используемому сервером, чтобы зашифровать пароли MySQL для хранения в таблице mysql.user.

    Переменная old_passwords управляет методом хеширования пароля, используемым функцией PASSWORD(). Это также влияет на пароль, выполненный CREATE USER и GRANT, которые определяют пароль, используя пункт IDENTIFIED BY.

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

    ЗначениеМетод хэширования Связанный плагин аутентификации
    0MySQL 4.1 native hashing mysql_native_password
    2SHA-256 hashing sha256_password

    SHA-256 password hashing (old_passwords=2) использует случайное значение salt, которое делает результат PASSWORD() недетерминированным. Следовательно, запросы, которые используют эту функцию, небезопасны для основанной на запросах репликации и не могут быть сохранены в кэше запроса.

    Шифрование, выполненное PASSWORD(), однонаправленное. Это не тот же самый тип шифрования, используемого для паролей Unix, для него надо использовать ENCRYPT().

    PASSWORD() используется системой аутентификации в сервере MySQL, Вы не должны not использовать это в своих собственных приложениях. С этой целью рассмотрите MD5() или SHA2(). Также см. RFC 2195, section 2 (Challenge-Response Authentication Mechanism (CRAM)).

    При некоторых обстоятельствах, запросы, которые вызывают PASSWORD() могут быть зарегистрированы в журналах сервера или на стороне клиента в файле истории, например, ~/.mysql_history, что означает, что пароли открытого текста могут быть считаны любым имеющим доступ к той информации. Для информации об условиях, при которых это происходит для журналов сервера и как управлять ею, см. раздел 7.1.2.3.

  • RANDOM_BYTES(len )

    Эта функция возвращает двоичную строку из len случайных байт из генератора случайных чисел библиотеки SSL (OpenSSL или yaSSL). Разрешенные значения len от 1 до 1024. Для значений вне диапазона RANDOM_BYTES() производит предупреждение и возвращает NULL.

    RANDOM_BYTES() может использоваться, чтобы обеспечить вектор инициализации для AES_DECRYPT() и AES_ENCRYPT(). Для использования в этом контексте len должен быть по крайней мере 16. Большие значения разрешены, но байты сверх 16 проигнорированы.

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

  • SHA1(str) , SHA(str )

    Вычисляет 160-битовую контрольную сумму SHA-1 для строки, как описано в RFC 3174 (безопасный алгоритм хеша). Значение возвращено как строка из 40 шестнадцатеричных цифр или NULL, если параметр был NULL. Одно из возможных применений для этой функции как ключ хеша. См. примечания в начале этого раздела о хранении значений хеша эффективно. Вы можете также использовать SHA1() как шифровальную функция для того, чтобы сохранить пароли. SHA() синоним для SHA1().

    Возвращаемое значение недвоичная строка в наборе символов соединения.

    mysql> SELECT SHA1('abc');
        -> 'a9993e364706816aba3e25717850c26c9cd0d89d'
    

    SHA1() может считаться более безопасным эквивалентом MD5().

  • SHA2(str, hash_length)

    Вычисляет семейство функций хеша SHA-2 (SHA-224, SHA-256, SHA-384 и SHA-512). Первый параметр строка открытого текста, которая будет хеширована. Второй параметр указывает на желаемую длину в битах результата, у него должно быть значение 224, 256, 384, 512 или 0 (эквивалентен 256). Если любой параметр NULL или длина хеша не одно из разрешенных значений, возвращаемое значение NULL. Иначе функциональный результат значение хеша, содержащее желаемое число битов.

    Возвращаемое значение недвоичная строка в наборе символов соединения.

    mysql> SELECT SHA2('abc', 224);
        -> '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'
    

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

    SHA2() более надежна криптографически, чем MD5() или SHA1().

  • UNCOMPRESS( string_to_uncompress)

    Разжимает строку, сжатую COMPRESS(). Если параметр не сжатое значение, результат NULL. Эта функция требует, чтобы MySQL был собран с библиотекой сжатия такой, как zlib. Иначе возвращаемое значение всегда NULL.

    mysql> SELECT UNCOMPRESS(COMPRESS('any string'));
        -> 'any string'
    mysql> SELECT UNCOMPRESS('any string');
        -> NULL
    
  • UNCOMPRESSED_LENGTH(compressed_string)

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

    mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30)));
        -> 30
    
  • VALIDATE_PASSWORD_STRENGTH(str)

    Учитывая параметр, представляющий пароль открытого текста, эта функция возвращает целое число, чтобы указать, насколько сильный пароль. Возвращаемое значение колеблется от 0 (слабый) до 100 (сильный).

    Оценка пароля VALIDATE_PASSWORD_STRENGTH() сделана плагином validate_password. Если плагин не установлен, функция всегда возвращает 0. Для информации об установке плагина validate_password см. раздел 7.5.2 . Чтобы исследовать или сконфигурировать параметры, которые затрагивают тестирование пароля, проверьте или установите системные переменные, осуществленные плагином validate_password. См. раздел 7.5.2.2.

    Пароль подвергнут все более и более строгим тестам, и возвращаемое значение показывает, какие тесты были удовлетворены, как показано в следующей таблице. Кроме того, если переменная validate_password_check_user_name включена, и пароль соответствует имени пользователя, VALIDATE_PASSWORD_STRENGTH() возвращает 0, независимо от настроек других переменных validate_password.

    Тест пароляВозвращаемое значение
    Длина < 40
    Длина = 4 и < validate_password_length25
    Удовлетворяет политике 1 (LOW) 50
    Удовлетворяет политике 2 (MEDIUM) 75
    Удовлетворяет политике 3 (STRONG) 100

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
  • BENCHMARK(count ,expr)

    Функция BENCHMARK() выполняет выражение expr count раз. Это может использоваться, чтобы оценить, как быстро MySQL обрабатывает выражение. Значение результата всегда 0. Намеченное использование в клиенте mysql, который сообщает о времени выполнения запроса:

    mysql> SELECT BENCHMARK(1000000,ENCODE('hello','goodbye'));
    +----------------------------------------------+
    | BENCHMARK(1000000,ENCODE('hello','goodbye')) |
    +----------------------------------------------+
    | 0                                            |
    +----------------------------------------------+
    1 row in set (4.74 sec)
    

    Время показывает прошедшее время на клиенте, а не время центрального процессора на сервере. Желательно выполнить BENCHMARK() несколько раз и интерпретировать результат относительно того, как загржен сервер.

    BENCHMARK() предназначена для того, чтобы определить эксплуатационные качества во время выполнения скалярных выражений, у которых есть некоторые существенные значения для способа, которым Вы используете их и интерпретируете результаты:

    • Только скалярные выражения могут использоваться. Хотя выражение может быть подзапросом, оно должно возвратить единственный столбец и самое большее единственную строку. Например, BENCHMARK(10, (SELECT * FROM t)) потерпит неудачу, если таблица t имеет больше, чем один столбец или больше, чем одну строку.

    • Выполнение SELECT expr N раз отличается от выполнения SELECT BENCHMARK(N, expr) с точки зрения количества вовлеченных ресурсов. У этих двух запросов есть совсем другие профили выполнения, и Вы не должны ожидать, что они займут то же самое количество времени. В первом случае работают оптимизатор, анализатор, блокировка таблиц, причем все это работает каждый из N раз. Во втором случае структуры памяти, локальное кэширование и оптимизация отрабатывают только однажды, после чего N раз оценивается только само выражение. Результаты BENCHMARK() определяют эксплуатационные качества компонента во время выполнения, давая больше веса тому компоненту и удаляя шум, внесенный сетью, оптимизатором, анализатором и другими компонентами.

  • CHARSET(str)

    Возвращает набор символов строкового параметра.

    mysql> SELECT CHARSET('abc');
      -> 'latin1'
    mysql> SELECT CHARSET(CONVERT('abc' USING utf8));
      -> 'utf8'
    mysql> SELECT CHARSET(USER());
      -> 'utf8'
    
  • COERCIBILITY(str )

    Возвращает сопоставление строкового параметра.

    mysql> SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci);
        -> 0
    mysql> SELECT COERCIBILITY(USER());
        -> 3
    mysql> SELECT COERCIBILITY('abc');
        -> 4
    

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

    ЗначениеСмысл Пример
    0Явное сопоставление Значение с COLLATE
    1Никакого сопоставления Связь строк с различными сопоставлениями
    2Неявное сопоставление Значение столбца, параметр сохраненной процедуры или локальная переменная
    3Постоянная системы Возвращаемое значение USER()
    4Сопоставление Буквальная строка
    5Игнорируемое NULL или выражение произошло из NULL
  • COLLATION(str )

    Возвращает сопоставление строкового параметра.

    mysql> SELECT COLLATION('abc');
        -> 'latin1_swedish_ci'
    mysql> SELECT COLLATION(_utf8'abc');
        -> 'utf8_general_ci'
    
  • CONNECTION_ID()

    Возвращает ID соединения (ID потока). У каждого соединения есть ID, который уникален среди группы в настоящее время присоединенных клиентов.

    Значение, возвращенное CONNECTION_ID(), то же самое, как в столбце ID таблицы INFORMATION_SCHEMA.PROCESSLIST , столбце Id вывода SHOW PROCESSLIST и столбце PROCESSLIST_ID таблицы threads в Performance Schema.

    mysql> SELECT CONNECTION_ID();
      -> 23786
    
  • CURRENT_ROLE()

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

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

    GRANT 'r1', 'r2' TO 'u1'@'localhost';
    

    В сеансах для u1 стартовое значение CURRENT_USER() роль учетной записи по умолчанию или роли. Используя SET ROLE можно менять:

    mysql> SET ROLE ALL; SELECT CURRENT_ROLE();
    +-------------------+
    | CURRENT_ROLE()    |
    +-------------------+
    | `r1`@`%`,`r2`@`%` |
    +-------------------+
    
    mysql> SET ROLE 'r1'; SELECT CURRENT_ROLE();
    +----------------+
    | CURRENT_ROLE() |
    +----------------+
    | `r1`@`%`       |
    +----------------+
    
  • CURRENT_USER, CURRENT_USER()

    Возвращает имя пользователя и комбинацию имени хоста для учетной записи MySQL. Эта учетная запись определяет Ваши привилегии доступа. Возвращаемое значение строка в наборе символов utf8.

    Значение CURRENT_USER() может отличаться от значения USER().

    mysql> SELECT USER();
        -> 'davida@localhost'
    
    mysql> SELECT * FROM mysql.user;
    ERROR 1044: Access denied for user ''@'localhost' to
    database 'mysql'
    
    mysql> SELECT CURRENT_USER();
        -> '@localhost'
    

    Пример иллюстрирует это: хотя клиент определил имя пользователя davida (как обозначено значением функции USER()), сервер подтверждает подлинность клиента, использующего анонимную учетную запись пользователя (как обозначено пустой частью имени пользователя в значении CURRENT_USER() ).

    В пределах сохраненной программы или представления CURRENT_USER() возвращает пользователя, который определил объект (как дано значением DEFINER), если не определено с параметром SQL SECURITY INVOKER. В последнем случае CURRENT_USER() возвращает того, кто вызвал обхект.

    У триггеров и событий нет никакой опции, чтобы определить SQL SECURITY, таким образом, для этих объектов CURRENT_USER() возвращает пользователя, который определил объект. Чтобы возвратить вызвашего, надо использовать USER() или SESSION_USER().

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

    Для информации о значениях, что это расширение CURRENT_USER() имеет для репликации в различных выпусках MySQL 8.0 см. see раздел 19.4.1.8 .

  • DATABASE()

    Возвращает значение по умолчанию имени базы данных как строка в utf8. Если нет никакой базы данных по умолчанию, DATABASE() вернет NULL. В пределах сохраненной процедуры база данных по умолчанию это база данных, с которой связана процедура, который не обязательно является той же самой базой данных, которая значение по умолчанию в контексте запроса.

    mysql> SELECT DATABASE();
        -> 'test'
    

    Если нет никакой базы данных по умолчанию, DATABASE() вернет NULL.

  • FOUND_ROWS()

    Запрос SELECT может включать пункт LIMIT, чтобы ограничить число строк, которые сервер возвращает клиенту. В некоторых случаях желательно знать, сколько строк запрос возвратил бы без LIMIT, но не выполняя запрос снова. Чтобы получить это количество строк, включите опцию SQL_CALC_FOUND_ROWS в SELECT и затем вызовите FOUND_ROWS() позже:

    mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
        ->        WHERE id > 100 LIMIT 10;
    mysql> SELECT FOUND_ROWS();
    

    Второй SELECT возвращает число, указывающее сколько строк первый SELECT возвратил бы без LIMIT.

    В отсутствие опции SQL_CALC_FOUND_ROWS и наличии успешного SELECT FOUND_ROWS() возвращает число строк в наборе результатов, возвращенном этим запросом. Если запрос включает LIMIT, FOUND_ROWS() возвращает число строк до limit. Например, FOUND_ROWS() возвращает 10 или 60, соответственно, если запрос включает respectively, if the statement includes LIMIT 10 или LIMIT 50, 10.

    Количество строк, доступное через FOUND_ROWS() является переходным и не предназначено быть доступным после SELECT SQL_CALC_FOUND_ROWS. Если Вы должны обратиться к значению позже, сохраните его:

    mysql> SELECT SQL_CALC_FOUND_ROWS * FROM ... ;
    mysql> SET @rows = FOUND_ROWS();
    

    Если Вы используете SELECT SQL_CALC_FOUND_ROWS, MySQL должен вычислить, сколько строк находится в полном наборе результатов. Однако, это быстрее, чем выполнение запроса снова без LIMIT, потому что набор результатов не надо посылать клиенту.

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

    Использование SQL_CALC_FOUND_ROWS и FOUND_ROWS() более сложно для for UNION, чем для простого SELECT, поскольку LIMIT может произойти в многих местах в UNION. Это может быть применено к отдельному запросу SELECT в UNION или глобально к результату UNION в целом.

    Смысл SQL_CALC_FOUND_ROWS для UNION в том, что это должно возвратить количество строк, которое было бы возвращено без глобального LIMIT. Условия для использования SQL_CALC_FOUND_ROWS с UNION:

    • Ключевое слово SQL_CALC_FOUND_ROWS должно появиться в первом SELECT в UNION.

    • Значение FOUND_ROWS() точно только если используется UNION ALL. Если UNION без ALL, удаление дубликатов происходит и значение FOUND_ROWS() оценено только приблизительно.
    • Если LIMIT не присутствует в UNION, SQL_CALC_FOUND_ROWS проигнорирован и возвращается число строк во временной таблице, которая составлена, чтобы обработать UNION.

    Вне случаев, описанных здесь, поведение FOUND_ROWS() не определено (например, его значение после запроса SELECT, который терпит неудачу с ошибкой).

    FOUND_ROWS() не копируется, достоверно используя основанную на запросах репликацию. Эта функция автоматически копируется, используя основанную на строках репликацию.

  • LAST_INSERT_ID() , LAST_INSERT_ID( expr)

    Без параметра LAST_INSERT_ID() вернет BIGINT UNSIGNED (64-bit) число, представляющее первое автоматически произведенное значение, успешно вставленное для столбца AUTO_INCREMENT в результате выполненного последним запроса INSERT. Значение LAST_INSERT_ID() остается неизменным, если никакие строки успешно не вставлены.

    С параметром LAST_INSERT_ID() возвращает unsigned integer.

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

    mysql> SELECT LAST_INSERT_ID();
        -> 195
    

    В настоящее время выполняющийся запрос не затрагивает значение LAST_INSERT_ID() . Предположите, что Вы производите значение AUTO_INCREMENT с одним запросом, а затем обращаетесь к LAST_INSERT_ID() при вставке нескольих строк INSERT, которое вставляет строки в таблицу с его собственным столбцом AUTO_INCREMENT. Значение LAST_INSERT_ID() останется устойчивым во втором запросе: его значение для второй и более поздних строк не затронуто более ранними вставками строки. Однако, если Вы смешиваете ссылки на LAST_INSERT_ID() и LAST_INSERT_ID( expr), эффект неопределен.

    Если предыдущий запрос возвратил ошибку, значение LAST_INSERT_ID() не определено. Для транзакционных таблиц, если запрос откатился из-за ошибки, значение LAST_INSERT_ID() не определено. Для ручного ROLLBACK значение LAST_INSERT_ID() не восстановлен к тому, что было перед транзакцией, это остается, как было в точке ROLLBACK.

    В пределах тела сохраненной процедуры, функции или триггера, значение LAST_INSERT_ID() изменяется тем же самым путем, что касается запросов, выполненных вне этих видов объектов. Эффект сохраненной процедуры или триггера на значение LAST_INSERT_ID(), зависит от вида процедуры:

    • Если хранимая процедура выполняет запросы, которые изменяют значение LAST_INSERT_ID() , измененное значение замечено запросами, которые следуют за вызовом процедуры.

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

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

    Значение LAST_INSERT_ID() не изменено, если Вы устанавливаете столбец AUTO_INCREMENT строки в значение, которое не является NULL или 0.

    Если Вы вставляете много строк, используя одиночный INSERT, LAST_INSERT_ID() возвращает значение, произведенное для первой вставленной строки. Причина этого состоит в том, чтобы позволить легко воспроизвести тот же самый INSERT для другого сервера.

    Например:

    mysql> USE test;
    Database changed
    mysql> CREATE TABLE t (
        ->   id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
        ->   name VARCHAR(10) NOT NULL);
    Query OK, 0 rows affected (0.09 sec)
    
    mysql> INSERT INTO t VALUES (NULL, 'Bob');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> SELECT * FROM t;
    +----+------+
    | id | name |
    +----+------+
    |  1 | Bob  |
    +----+------+
    1 row in set (0.01 sec)
    
    mysql> SELECT LAST_INSERT_ID();
    +------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 1                |
    +------------------+
    1 row in set (0.00 sec)
    
    mysql> INSERT INTO t VALUES
        -> (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SELECT * FROM t;
    +----+------+
    | id | name |
    +----+------+
    |  1 | Bob  |
    |  2 | Mary |
    |  3 | Jane |
    |  4 | Lisa |
    +----+------+
    4 rows in set (0.01 sec)
    
    mysql> SELECT LAST_INSERT_ID();
    +------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 2                |
    +------------------+
    1 row in set (0.00 sec)
    

    Хотя второй запрос INSERT вставил три новых строки в t, ID, произведенный для первой из этих строк, был 2, и именно это значение возвращено LAST_INSERT_ID() для следующего SELECT.

    Если Вы используете INSERT IGNORE и строка проигнорирована, LAST_INSERT_ID() остается неизменным (или 0 возвращен, если соединение еще не выполнило успешно INSERT) и, для нетранзакционных таблиц, счетчик AUTO_INCREMENT не увеличен. Для таблиц InnoDB счетчик AUTO_INCREMENT увеличен, если innodb_autoinc_lock_mode установлена в 1 или 2:

    mysql> USE test;
    Database changed
    
    mysql> SELECT @@innodb_autoinc_lock_mode;
    +----------------------------+
    | @@innodb_autoinc_lock_mode |
    +----------------------------+
    | 1                          |
    +----------------------------+
    1 row in set (0.00 sec)
    
    mysql> CREATE TABLE `t` (
      `id` INT(11) NOT NULL AUTO_INCREMENT,
      `val` INT(11) DEFAULT NULL, PRIMARY KEY (`id`),
      UNIQUE KEY `i1` (`val`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    Query OK, 0 rows affected (0.02 sec)
    
    -- Insert two rows
    
    mysql> INSERT INTO t (val) VALUES (1),(2);
    Query OK, 2 rows affected (0.00 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    -- With auto_increment_offset=1, the inserted rows
    -- result in an AUTO_INCREMENT value of 3
    
    mysql> SHOW CREATE TABLE t\G
    *************************** 1. row ***************************
     Table: t
    Create Table: CREATE TABLE `t` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `val` int(11) DEFAULT NULL, PRIMARY KEY (`id`),
      UNIQUE KEY `i1` (`val`)
    ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)
    
    -- LAST_INSERT_ID() returns the first automatically generated
    -- value that is successfully inserted for the AUTO_INCREMENT column
    
    mysql> SELECT LAST_INSERT_ID();
    +------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 1                |
    +------------------+
    1 row in set (0.00 sec)
    
    -- The attempted insertion of duplicate rows fail but errors are ignored
    
    mysql> INSERT IGNORE INTO t (val) VALUES (1),(2);
    Query OK, 0 rows affected (0.00 sec)
    Records: 2  Duplicates: 2  Warnings: 0
    
    -- With innodb_autoinc_lock_mode=1, the AUTO_INCREMENT counter
    -- is incremented for the ignored rows
    
    mysql> SHOW CREATE TABLE t\G
    *************************** 1. row ***************************
     Table: t
    Create Table: CREATE TABLE `t` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `val` int(11) DEFAULT NULL, PRIMARY KEY (`id`),
      UNIQUE KEY `i1` (`val`)
    ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)
    
    -- The LAST_INSERT_ID is unchanged becuase the previous insert was unsuccessful
    
    mysql> SELECT LAST_INSERT_ID();
    +------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 1                |
    +------------------+
    1 row in set (0.00 sec)  

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

    1. Составьте таблицу, чтобы сохранить последовательность и инициализируйте это:

      mysql> CREATE TABLE sequence (id INT NOT NULL);
      mysql> INSERT INTO sequence VALUES (0);
      
    2. Используйте таблицу, чтобы произвести порядковые номера:
      mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
      mysql> SELECT LAST_INSERT_ID();
      

      UPDATE постепенно увеличивает счетчик последовательности и вызывает следующий вызов LAST_INSERT_ID() , чтобы возвратить обновленное значение. Запрос SELECT получает это значение. Функция C API mysql_insert_id() может также использоваться, чтобы получить значение. См. раздел 25.8.7.38.

    Отметьте, что mysql_insert_id() обновлен только после INSERT и UPDATE, таким образом, Вы не можете использовать функцию C API, чтобы получить значение для LAST_INSERT_ID(expr) после выполнения других запросов SQL, подобных SELECT или SET.

  • ROLES_GRAPHML()

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

  • ROW_COUNT()

    ROW_COUNT() возвращает значение следующим образом:

    • DDL-запросы: 0. Это относится к таким заявлениям, как CREATE TABLE или DROP TABLE.

    • DML-запросы кроме SELECT: Число затронутых строк. Это относится к таким запросам, как UPDATE, INSERT или DELETE (как прежде), но теперь также к таким запросам, как ALTER TABLE и LOAD DATA INFILE.
    • SELECT: -1, если запрос возвращает набор результатов, или число строк, если он этого не делает. Например, для SELECT * FROM t1 ROW_COUNT() вернет -1. Для SELECT * FROM t1 INTO OUTFILE 'file_name' ROW_COUNT() вернет число строк, записанных в файл.
    • SIGNAL: 0.

    Для UPDATE значение затронутых строк по умолчанию число строк, фактически измененных. Если Вы определяете флаг CLIENT_FOUND_ROWS для mysql_real_connect() соединяясь с mysqld , значение затронутых строк число найденных строк, то есть, соответствующее предложение WHERE.

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

    Для INSERT ... ON DUPLICATE KEY UPDATE значение затронутых строк для каждой строки 1, если строка вставлена как новая строка, 2, если существующая строка обновлена, и 0, если существующая строка установлена в ее текущее состояние. Если Вы определяете флаг CLIENT_FOUND_ROWS, значение затронутых строк 1 (не 0), если существующая строка установлена в ее текущее состояние.

    Значение ROW_COUNT() подобно значению функции C API mysql_affected_rows() и количеству строк, которое выводит на экран клиент mysql.

    mysql> INSERT INTO t VALUES(1),(2),(3);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SELECT ROW_COUNT();
    +-------------+
    | ROW_COUNT() |
    +-------------+
    | 3           |
    +-------------+
    1 row in set (0.00 sec)
    
    mysql> DELETE FROM t WHERE i IN(1,2);
    Query OK, 2 rows affected (0.00 sec)
    
    mysql> SELECT ROW_COUNT();
    +-------------+
    | ROW_COUNT() |
    +-------------+
    | 2           |
    +-------------+
    1 row in set (0.00 sec)
    

    ROW_COUNT() не копируется достоверно, используя основанную на запросе репликацию. Эта функция автоматически копируется, используя основанную на строке репликацию.

  • SCHEMA()

    Синоним для DATABASE() .

  • SESSION_USER()

    SESSION_USER() синоним для USER().

  • SYSTEM_USER()

    SYSTEM_USER() синоним для USER().

  • USER()

    Возвращает текущее имя пользователя MySQL и имя хоста как строку в utf8.

    mysql> SELECT USER();
        -> 'davida@localhost'
    

    Значение указывает на имя пользователя, которое Вы определили, соединяясь с сервером, и хост клиента, с которого Вы соединялись. Значение может отличаться от значения из CURRENT_USER().

  • VERSION()

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

    Эта функция опасна для основанной на запросах репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format установлена в STATEMENT.

    mysql> SELECT VERSION();
        -> '8.0.1-standard'
    

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

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

  • Функции, которые создают конфигурации в различных форматах (WKT, WKB, internal).

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

Для общего обзора о поддержке 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));
  • GeometryCollection( g1,g2,...)

    Конструирует GeometryCollection.

    GeometryCollection() возвращает все надлежащие конфигурации в параметре, даже если присутствует неподдержанная геометрия.

    GeometryCollection() без параметров разрешена как способ создать пустую геометрию.

  • LineString(pt1 ,pt2,...)

    Конструирует LineString значение из многих параметров Point или WKB Point. Если число параметров меньше, чем два, возвращаемое значение NULL.

  • MultiLineString( ls1,ls2,...)

    Конструирует MultiLineString с использованием значения LineString или WKB LineString.

  • MultiPoint(pt1 , pt2,...)

    Конструирует MultiPoint с использованием значения Point или WKB Point.

  • MultiPolygon( poly1,poly2,...)

    Конструирует MultiPolygon из ряда параметров Polygon или WKB Polygon.

  • Point(x, y)

    Конструирует Point с использованием его координат.

  • Polygon(ls1, ls2,...)

    Конструирует Polygon значение из многих параметров LineString или WKB LineString. Если какой-либо параметр не представляет LinearRing (то есть, не закрытый и простое LineString), возвращаемое значение NULL.

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 |
+--------------------------+--------------------------+
  • ST_AsBinary(g ), ST_AsWKB(g )

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

    SELECT ST_AsBinary(g) FROM geom;
    
  • ST_AsText(g ), ST_AsWKT(g )

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

    mysql> SET @g = 'LineString(1 1,2 2,3 3)';
    mysql> SELECT ST_AsText(ST_GeomFromText(@g));
    +--------------------------------+
    | ST_AsText(ST_GeomFromText(@g)) |
    +--------------------------------+
    | LINESTRING(1 1,2 2,3 3)        |
    +--------------------------------+
    

    Вывод для значения MultiPoint включает круглые скобки вокруг каждого пункта. Например:

    mysql> SELECT ST_AsText(ST_GeomFromText(@mp));
    +---------------------------------+
    | ST_AsText(ST_GeomFromText(@mp)) |
    +---------------------------------+
    | MULTIPOINT((1 1),(2 2),(3 3))   |
    +---------------------------------+
    

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

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

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

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

  • ST_Dimension(g )

    Возвращает врожденное измерение значения геометрии g или NULL, если параметр NULL. Измерение может быть -1, 0, 1 или 2. Смысл этих значений дан в разделе 12.5.2.2.

    mysql> SELECT ST_Dimension(ST_GeomFromText('LineString(1 1,2 2)'));
    +------------------------------------------------------+
    | ST_Dimension(ST_GeomFromText('LineString(1 1,2 2)')) |
    +------------------------------------------------------+
    |  1                                                   |
    +------------------------------------------------------+
    
  • ST_Envelope(g )

    Возвращает минимальный ограничительный прямоугольник (MBR) для значения геометрии g или NULL, если параметр NULL. Результат возвращен как значение Polygon, которое определено угловыми точками ограничивающего прямоугольника:

    POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
    
    mysql> SELECT ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,2 2)')));
    +----------------------------------------------------------------+
    | ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,2 2)'))) |
    +----------------------------------------------------------------+
    | POLYGON((1 1, 2 1, 2 2, 1 2, 1 1))                             |
    +----------------------------------------------------------------+
    

    Если параметр точка или вертикальный (или горизонтальный) линейный сегмент, ST_Envelope() возвращает точку или линейный сегмент как его MBR вместо того, чтобы возвратить недопустимый многоугольник:

    mysql> SELECT ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,1 2)')));
    +----------------------------------------------------------------+
    | ST_AsText(ST_Envelope(ST_GeomFromText('LineString(1 1,1 2)'))) |
    +----------------------------------------------------------------+
    | LINESTRING(1 1, 1 2)                                           |
    +----------------------------------------------------------------+
    
  • ST_GeometryType( g)

    Возвращает двоичную строку, указывающую на название типа геометрии, к которой принадлежит g или NULL, если параметр NULL. Имя соответствует одному из подклассов Geometry.

    mysql> SELECT ST_GeometryType(ST_GeomFromText('POINT(1 1)'));
    +------------------------------------------------+
    | ST_GeometryType(ST_GeomFromText('POINT(1 1)')) |
    +------------------------------------------------+
    | POINT                                          |
    +------------------------------------------------+
    
  • ST_IsEmpty(g )

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

    MySQL не поддерживает значения GIS EMPTY, такие как POINT EMPTY.

  • ST_IsSimple(g )

    Возвращает 1, если значение геометрии g не имеет никаких аномальных геометрических пунктов, таких как самопересечение или самокасание. ST_IsSimple() возвращает 0, если параметр не прост и NULL, если параметр NULL.

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

  • ST_SRID(g[, new_srid_val])

    В MySQL значение SRID только целое число, связанное со значением геометрии. Все вычисления сделаны, принимая Евклидову (плоскую) геометрию.

    С единственным параметром, представляющим допустимый объект геометрии g, ST_SRID() возвращает целое число, указывающее на Spatial Reference System ID для g или NULL, если параметр NULL.

    Если параметр не синтаксически правильно построенная геометрия, происходит ошибка ER_GIS_INVALID_DATA.

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

    • Обработка ошибок для первого параметра, что касается синтаксиса единственного параметра, сделана, как описано ранее.

    • Если значение SRID во втором параметре не в пределах диапазона 32-битного целого числа без знака, происходит ошибка ER_DATA_OUT_OF_RANGE .
    • Если значение SRID во втором параметре не обращается к пространственной ссылочной системе, происходит ошибка ER_SRS_NOT_FOUND .

    mysql> SET @g = ST_GeomFromText('LineString(1 1,2 2)', 0);
    mysql> SELECT ST_SRID(@g);
    +-------------+
    | ST_SRID(@g) |
    +-------------+
    | 0           |
    +-------------+
    mysql> SET @g2 = ST_SRID(@g, 4326);
    mysql> SELECT ST_SRID(@g2);
    +--------------+
    | ST_SRID(@g2) |
    +--------------+
    |   4326       |
    +--------------+
    

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

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

  • ST_X(p[, new_x_val])

    С единственным параметром, представляющим допустимый объект Point object p ST_X() возвращает значение X-координаты p как число двойной точности или NULL, если параметр NULL. Эти условия применяются:

    • Если параметр допустимая геометрия, но не объект Point, происходит ошибка ER_UNEXPECTED_GEOMETRY_TYPE.

    • Если параметр не допустимая геометрия, происходит ошибка ER_GIS_INVALID_DATA .

    Если дополнительный второй параметр, представляющий допустимое значение X-координаты, дан, ST_X() возвращает объект Point с X-координатой, равной второму параметру, или NULL, если любой параметр NULL. Эти условия применяются:

    • Обработка ошибок для первого параметра, что касается синтаксиса единственного параметра, сдалана, как описано ранее.

    • Если координатное значение во втором параметре -inf, +inf или NaN, происходит ошибка ER_DATA_OUT_OF_RANGE .

    mysql> SELECT ST_X(POINT(56.7, 53.34));
    +--------------------------+
    | ST_X(POINT(56.7, 53.34)) |
    +--------------------------+
    | 56.7                     |
    +--------------------------+
    
    mysql> SELECT ST_AsText(ST_X(POINT(56.7, 53.34), 10.5));
    +-------------------------------------------+
    | ST_AsText(ST_X(POINT(56.7, 53.34), 10.5)) |
    +-------------------------------------------+
    | POINT(10.5 53.34)                         |
    +-------------------------------------------+
    
  • ST_Y(p[, new_y_val])

    С единственным параметром, представляющим допустимый объект Point p, ST_Y() возвращает значение Y-координаты p как число двойной точности или NULL, если параметр NULL. Эти условия применяются:

    • Если параметр допустимая геометрия, но не объект Point, произойдет ошибка ER_UNEXPECTED_GEOMETRY_TYPE.

    • Если параметр не допустимая геометрия, произойдет ошибка ER_GIS_INVALID_DATA .

    Если дополнительный второй параметр, представляющий допустимое значение Y-координаты, дан, ST_Y() возвращает объект Point с Y-координатой, равной второму параметру, или NULL, если любой параметр NULL. Эти условия применяются:

    • Обработка ошибок для первого параметра, что касается синтаксиса единственного параметра, сделана как описано ранее.

    • Если координатное значение во втором параметре -inf, +inf или NaN, произойдет ошибка ER_DATA_OUT_OF_RANGE .

    mysql> SELECT ST_Y(POINT(56.7, 53.34));
    +--------------------------+
    | ST_Y(POINT(56.7, 53.34)) |
    +--------------------------+
    | 53.34                    |
    +--------------------------+
    
    mysql> SELECT ST_AsText(ST_Y(POINT(56.7, 53.34), 10.5));
    +-------------------------------------------+
    | ST_AsText(ST_Y(POINT(56.7, 53.34), 10.5)) |
    +-------------------------------------------+
    | POINT(56.7 10.5)                          |
    +-------------------------------------------+
    

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

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

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

  • ST_EndPoint(ls )

    Возвращает Point, конечную точку значения LineString ls.

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
    mysql> SELECT ST_AsText(ST_EndPoint(ST_GeomFromText(@ls)));
    +----------------------------------------------+
    | ST_AsText(ST_EndPoint(ST_GeomFromText(@ls))) |
    +----------------------------------------------+
    | POINT(3 3)                                   |
    +----------------------------------------------+
    
  • ST_IsClosed(ls )

    Для значения LineString ls ST_IsClosed() возвращает 1, если ls закрыт (то есть, значения ST_StartPoint() и ST_EndPoint() то же самое).

    Для значения MultiLineString ls ST_IsClosed() возвращает 1, если ls закрыт (то есть, значения ST_StartPoint() и ST_EndPoint() те же самые для каждой LineString в ls).

    ST_IsClosed() возвращает 0, если ls не закрыт, и NULL, если ls NULL.

    mysql> SET @ls1 = 'LineString(1 1,2 2,3 3,2 2)';
    mysql> SET @ls2 = 'LineString(1 1,2 2,3 3,1 1)';
    mysql> SELECT ST_IsClosed(ST_GeomFromText(@ls1));
    +------------------------------------+
    | ST_IsClosed(ST_GeomFromText(@ls1)) |
    +------------------------------------+
    | 0                                  |
    +------------------------------------+
    
    mysql> SELECT ST_IsClosed(ST_GeomFromText(@ls2));
    +------------------------------------+
    | ST_IsClosed(ST_GeomFromText(@ls2)) |
    +------------------------------------+
    | 1                                  |
    +------------------------------------+
    mysql> SET @ls3 = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';
    mysql> SELECT ST_IsClosed(ST_GeomFromText(@ls3));
    +------------------------------------+
    | ST_IsClosed(ST_GeomFromText(@ls3)) |
    +------------------------------------+
    | 0                                  |
    +------------------------------------+
    
  • ST_Length(ls )

    Возвращает число двойной точности, указывающее на длину значения LineString или MultiLineString ls в его связанной пространственной ссылке. Длина MultiLineString равна сумме длин элементов.

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
    mysql> SELECT ST_Length(ST_GeomFromText(@ls));
    +---------------------------------+
    | ST_Length(ST_GeomFromText(@ls)) |
    +---------------------------------+
    | 2.8284271247461903              |
    +---------------------------------+
    
    mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';
    mysql> SELECT ST_Length(ST_GeomFromText(@mls));
    +----------------------------------+
    | ST_Length(ST_GeomFromText(@mls)) |
    +----------------------------------+
    | 4.242640687119286                |
    +----------------------------------+
    
  • ST_NumPoints(ls )

    Возвращает число объектов Point в значении LineString ls.

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
    mysql> SELECT ST_NumPoints(ST_GeomFromText(@ls));
    +------------------------------------+
    | ST_NumPoints(ST_GeomFromText(@ls)) |
    +------------------------------------+
    | 3                                  |
    +------------------------------------+
    
  • ST_PointN(ls ,N)

    Возвращает N-ый Point в Linestring ls. Точки пронумерованы, начиная с 1.

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
    mysql> SELECT ST_AsText(ST_PointN(ST_GeomFromText(@ls),2));
    +----------------------------------------------+
    | ST_AsText(ST_PointN(ST_GeomFromText(@ls),2)) |
    +----------------------------------------------+
    | POINT(2 2)                                   |
    +----------------------------------------------+
    
  • ST_StartPoint( ls)

    Возвращает Point, который является стартовой точкой LineString ls.

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
    mysql> SELECT ST_AsText(ST_StartPoint(ST_GeomFromText(@ls)));
    +------------------------------------------------+
    | ST_AsText(ST_StartPoint(ST_GeomFromText(@ls))) |
    +------------------------------------------------+
    | POINT(1 1)                                     |
    +------------------------------------------------+
    

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

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

  • ST_Area(poly )

    Возвращает число двойной точности, указывающее на область параметра, как измерено в его пространственной ссылочной системе. Для параметров измерения 0 или 1 результат 0.

    Результат сумма значений областей всех компонентов для набора геометрии. Если набор геометрии пуст, его область возвращена как 0.

    mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))';
    mysql> SELECT ST_Area(ST_GeomFromText(@poly));
    +---------------------------------+
    | ST_Area(ST_GeomFromText(@poly)) |
    +---------------------------------+
    | 4                               |
    +---------------------------------+
    
    mysql> SET @mpoly =
        ->     'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))';
    mysql> SELECT ST_Area(ST_GeomFromText(@mpoly));
    +----------------------------------+
    | ST_Area(ST_GeomFromText(@mpoly)) |
    +----------------------------------+
    |  8                               |
    +----------------------------------+
    
  • ST_Centroid(mpoly )

    Возвращает математическую среднюю точку для MultiPolygon mpoly как Point.

    Эта функция обрабатывает наборы геометрии, вычисляя центроидный пункт для компонентов самого высокого измерения в наборе. Такие компоненты извлечены и превращены в MultiPolygon, MultiLineString или MultiPoint для центроидного вычисления. Если параметр пустой набор геометрии, возвращаемое значение NULL.

    mysql> SET @poly = ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),
        ->             (5 5,7 5,7 7,5 7,5 5))');
    mysql> SELECT ST_GeometryType(@poly),ST_AsText(ST_Centroid(@poly));
    +------------------------+--------------------------------------------+
    | ST_GeometryType(@poly) | ST_AsText(ST_Centroid(@poly))              |
    +------------------------+--------------------------------------------+
    | POLYGON                | POINT(4.958333333333333 4.958333333333333) |
    +------------------------+--------------------------------------------+
    
  • ST_ExteriorRing( poly)

    Возвращает внешнее кольцо Polygon poly как LineString.

    mysql> SET @poly = 'Polygon((0 0,0 3,3 3,3 0,0 0),
        ->             (1 1,1 2,2 2,2 1,1 1))';
    mysql> SELECT ST_AsText(ST_ExteriorRing(ST_GeomFromText(@poly)));
    +----------------------------------------------------+
    | ST_AsText(ST_ExteriorRing(ST_GeomFromText(@poly))) |
    +----------------------------------------------------+
    | LINESTRING(0 0,0 3,3 3,3 0,0 0)                    |
    +----------------------------------------------------+
    
  • ST_InteriorRingN( poly,N)

    Возвращает N-ое кольцо для Polygon poly как LineString. Кольца пронумерованы, начиная с 1.

    mysql> SET @poly = 'Polygon((0 0,0 3,3 3,3 0,0 0),
        ->             (1 1,1 2,2 2,2 1,1 1))';
    mysql> SELECT ST_AsText(ST_InteriorRingN(ST_GeomFromText(@poly),1));
    +-------------------------------------------------------+
    | ST_AsText(ST_InteriorRingN(ST_GeomFromText(@poly),1)) |
    +-------------------------------------------------------+
    | LINESTRING(1 1,1 2,2 2,2 1,1 1)                       |
    +-------------------------------------------------------+
    
  • ST_NumInteriorRing( poly), ST_NumInteriorRings( poly)

    Возвращается число колец для Polygon poly.

    mysql> SET @poly =
        ->     'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
    mysql> SELECT ST_NumInteriorRings(ST_GeomFromText(@poly));
    +---------------------------------------------+
    | ST_NumInteriorRings(ST_GeomFromText(@poly)) |
    +---------------------------------------------+
    |   1                                         |
    +---------------------------------------------+
    

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

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

  • ST_GeometryN(gc ,N)

    Возвращает N-ую геометрию в GeometryCollection gc. Геометрии нумерованы, начиная с 1.

    mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';
    mysql> SELECT ST_AsText(ST_GeometryN(ST_GeomFromText(@gc),1));
    +-------------------------------------------------+
    | ST_AsText(ST_GeometryN(ST_GeomFromText(@gc),1)) |
    +-------------------------------------------------+
    | POINT(1 1)                                      |
    +-------------------------------------------------+
    
  • ST_NumGeometries( gc)

    Возвращает число конфигураций в GeometryCollection gc.

    mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';
    mysql> SELECT ST_NumGeometries(ST_GeomFromText(@gc));
    +----------------------------------------+
    | ST_NumGeometries(ST_GeomFromText(@gc)) |
    +----------------------------------------+
    |  2                                     |
    +----------------------------------------+
    

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

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

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

  • ST_Buffer(g ,d[,strategy1[, strategy2[,strategy3]]])

    Возвращает геометрию, которая представляет все пункты, расстояние которых от геометрии g меньше или равно d, или NULL, если какой-либо параметр NULL. SRID параметра геометрии должен быть 0, потому что ST_Buffer() поддерживает только декартову систему координат. Для недопустимого параметра геометрии будет ошибка ER_GIS_INVALID_DATA .

    Если параметр геометрии пуст, ST_Buffer() возвращает пустую геометрию.

    Если расстояние 0, ST_Buffer() возвращает неизменный параметр геометрии:

    mysql> SET @pt = ST_GeomFromText('POINT(0 0)');
    mysql> SELECT ST_AsText(ST_Buffer(@pt, 0));
    +------------------------------+
    | ST_AsText(ST_Buffer(@pt, 0)) |
    +------------------------------+
    | POINT(0 0)                   |
    +------------------------------+
    

    ST_Buffer() поддерживает отрицательные расстояния для Polygon и MultiPolygon и для наборов геометрии, содержащих значения Polygon или MultiPolygon. Результат может быть пустой геометрией. Ошибка ER_WRONG_ARGUMENTS происходит для ST_Buffer() с отрицательным расстоянием для Point, MultiPoint, LineString и MultiLineString и для наборов геометрии, не содержащих любого значения Polygon или MultiPolygon.

    ST_Buffer() разрешает до трех дополнительных параметров стратегии после параметра расстояния. Стратегии влияют на буферное вычисление. Эти параметры строковые значения байта, произведенные ST_Buffer_Strategy() , чтобы использовать для стратегий точки, соединения и завершения:

    • Стратегии точки относятся к конфигурации Point и MultiPoint. Если никакая стратегия точки не определена, значение по умолчанию ST_Buffer_Strategy('point_circle', 32).

    • Стратегии соединения относятся к LineString, MultiLineString, Polygon и MultiPolygon. Если никакая стратегия не определена, значение по умолчанию ST_Buffer_Strategy('join_round', 32).
    • Стратегии завершения относятся к LineString и MultiLineString. Если никакая стратегия не определена, значение по умолчанию ST_Buffer_Strategy('end_round', 32).

    До одной стратегии каждого типа может быть определено, и их можно задать в любом порядке. Если много стратегий данного типа определено, происходит ошибка ER_WRONG_ARGUMENTS .

    mysql> SET @pt = ST_GeomFromText('POINT(0 0)');
    mysql> SET @pt_strategy = ST_Buffer_Strategy('point_square');
    mysql> SELECT ST_AsText(ST_Buffer(@pt, 2, @pt_strategy));
    +--------------------------------------------+
    | ST_AsText(ST_Buffer(@pt, 2, @pt_strategy)) |
    +--------------------------------------------+
    | POLYGON((-2 -2,2 -2,2 2,-2 2,-2 -2))       |
    +--------------------------------------------+
    
    mysql> SET @ls = ST_GeomFromText('LINESTRING(0 0,0 5,5 5)');
    mysql> SET @end_strategy = ST_Buffer_Strategy('end_flat');
    mysql> SET @join_strategy = ST_Buffer_Strategy('join_round', 10);
    mysql> SELECT ST_AsText(ST_Buffer(@ls, 5, @end_strategy, @join_strategy))
    +---------------------------------------------------------------+
    | ST_AsText(ST_Buffer(@ls, 5, @end_strategy, @join_strategy))   |
    +---------------------------------------------------------------+
    | POLYGON((5 5,5 10,0 10,-3.5355339059327373 8.535533905932738, |
    | -5 5,-5 0,0 0,5 0,5 5))                                       |
    +---------------------------------------------------------------+
    
  • ST_Buffer_Strategy( strategy[,points_per_circle])

    Эта функция возвращает строку байтов стратегии для использования с ST_Buffer(), чтобы влиять на буферное вычисление. Результат NULL, если какой-либо параметр NULL. Если какой-либо параметр недопустим, происходит ошибка ER_WRONG_ARGUMENTS.

    Информация о стратегиях доступна на Boost.org.

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

    • Для стратегий точки разрешенные значения 'point_circle' и 'point_square'.

    • Для стратегий объединения разрешенные значения 'join_round' и 'join_miter'.
    • Для стратегий завершения разрешенные значения 'end_round' и 'end_flat'.

    Если первый параметр 'point_circle', 'join_round', 'join_miter' или 'end_round', параметр points_per_circle должен быть дан как положительное числовое значение. Максимум points_per_circle значение системной переменной max_points_in_geometry. Если первый параметр 'point_square' или 'end_flat', параметр points_per_circle не должен быть дан или происходит ошибка ER_WRONG_ARGUMENTS .

    Для примеров см. описание ST_Buffer().

  • ST_ConvexHull(g )

    Возвращает геометрию, которая представляет выпуклый контур значения геометрии g.

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

    mysql> SET @g = 'MULTIPOINT(5 0,25 0,15 10,15 25)';
    mysql> SELECT ST_AsText(ST_ConvexHull(ST_GeomFromText(@g)));
    +-----------------------------------------------+
    | ST_AsText(ST_ConvexHull(ST_GeomFromText(@g))) |
    +-----------------------------------------------+
    | POLYGON((5 0,25 0,15 25,5 0))                 |
    +-----------------------------------------------+
    
  • ST_Difference(g1 , g2)

    Возвращает геометрию, которая представляет различие в наборе точек значений геометрий g1 и g2.

    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);
    mysql> SELECT ST_AsText(ST_Difference(@g1, @g2));
    +------------------------------------+
    | ST_AsText(ST_Difference(@g1, @g2)) |
    +------------------------------------+
    | POINT(1 1)                         |
    +------------------------------------+
    
  • ST_Intersection( g1, g2)

    Возвращает геометрию, которая представляет пересечение набора точек значений геометрий g1 и g2.

    mysql> SET @g1 = ST_GeomFromText('LineString(1 1, 3 3)');
    mysql> SET @g2 = ST_GeomFromText('LineString(1 3, 3 1)');
    mysql> SELECT ST_AsText(ST_Intersection(@g1, @g2));
    +--------------------------------------+
    | ST_AsText(ST_Intersection(@g1, @g2)) |
    +--------------------------------------+
    | POINT(2 2)                           |
    +--------------------------------------+
    
  • ST_SymDifference( g1, g2)

    Возвращает геометрию, которая представляет симметрическое различие набора точек значений геометрий g1 и g2, которая определена как:

    g1 symdifference g2 := (g1 union g2)
    difference (g1 intersection g2)
    

    Или в нотации вызова функции:

    ST_SymDifference(g1, g2) =
                     ST_Difference(ST_Union(g1,
                     g2),
                     ST_Intersection(g1,
                     g2))
    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);
    mysql> SELECT ST_AsText(ST_SymDifference(@g1, @g2));
    +-------------------------------------------+
    | ST_AsText(ST_SymDifference(@g1, @g2))     |
    +-------------------------------------------+
    | GEOMETRYCOLLECTION(POINT(1 1),POINT(2 2)) |
    +-------------------------------------------+
    
  • ST_Union(g1, g2)

    Возвращает геометрию, которая представляет союз наборов точек значений геометрий g1 и g2.

    mysql> SET @g1 = ST_GeomFromText('LineString(1 1, 3 3)');
    mysql> SET @g2 = ST_GeomFromText('LineString(1 3, 3 1)');
    mysql> SELECT ST_AsText(ST_Union(@g1, @g2));
    +--------------------------------------+
    | ST_AsText(ST_Union(@g1, @g2))        |
    +--------------------------------------+
    | MULTILINESTRING((1 1,3 3),(1 3,3 1)) |
    +--------------------------------------+
    

Кроме того, раздел 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() возвращает ложь, если вызвана с конфигурациями различных измерений.

  • ST_Contains(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, содержит ли g1 полностью g2. Это проверяет противоположные отношения как ST_Within().

  • ST_Crosses(g1 ,g2)

    Возвращает 1, если g1 пространственно пересекает g2. Возвращает NULL, если g1 Polygon или MultiPolygon, или если g2 Point или MultiPoint. Иначе вернет 0.

    Эта функция возвращает 0, если вызвана с неподходящей комбинацией типов параметров геометрии. Например, это возвращает 0, если первый параметр Polygon или MultiPolygon и\или второй параметр Point или MultiPoint.

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

    • Эти две конфигурации пересекаются.

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

  • ST_Disjoint(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, является ли g1 пространственно несвязной (не пересекается) с g2.

  • ST_Distance(g1 , g2)

    Возвращает расстояние между g1 и g2.

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

    Если промежуточный или окончательный результат производит NaN или отрицательное число, эта функция производит ошибку ER_GIS_INVALID_DATA .

    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);
    mysql> SELECT ST_Distance(@g1, @g2);
    +-----------------------+
    | ST_Distance(@g1, @g2) |
    +-----------------------+
    | 1.4142135623730951    |
    +-----------------------+
    
  • ST_Equals(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, равно ли пространственно g1 g2.

    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);
    mysql> SELECT ST_Equals(@g1, @g1), ST_Equals(@g1, @g2);
    +---------------------+---------------------+
    | ST_Equals(@g1, @g1) | ST_Equals(@g1, @g2) |
    +---------------------+---------------------+
    |   1                 |   0                 |
    +---------------------+---------------------+
    
  • ST_Intersects(g1 , g2)

    Возвращает 1 или 0, чтобы указать, пересекается ли пространственно g1 и g2.

  • ST_Overlaps(g1 , g2)

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

    Эта функция возвращает 0, если вызвана с неподходящей комбинацией типов параметров геометрии. Например, это возвращает 0, если вызвана с конфигурациями различных измерений, или любой параметр Point.

  • ST_Touches(g1 ,g2)

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

    Функция возвращает 0, если вызвана с неподходящей комбинацией типов параметров геометрии. Например, это возвращает 0, если любой из параметров Point или MultiPoint.

  • ST_Within(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, находится ли g1 пространственно в пределах g2. Это проверяет противоположные отношения как ST_Contains().

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

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

  • MBRContains(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, содержит ли минимальный ограничительный прямоугольник g1 такой же прямоугольник g2. Это проверяет противоположные отношения как MBRWithin().

    mysql> SET @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
    mysql> SET @g2 = ST_GeomFromText('Point(1 1)');
    mysql> SELECT MBRContains(@g1,@g2), MBRWithin(@g2,@g1);
    +----------------------+--------------------+
    | MBRContains(@g1,@g2) | MBRWithin(@g2,@g1) |
    +----------------------+--------------------+
    | 1                    |  1                 |
    +----------------------+--------------------+
    
  • MBRCoveredBy(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, покрыт ли минимальный ограничительный прямоугольник g1 прямоугольником g2. Это проверяет противоположные отношения как MBRCovers().

    MBRCoveredBy() и MBRCovers() обрабатывают параметры и возвращают значение следующим образом:

    • Возвратить NULL, если любой параметр NULL или пустая геометрия.

    • Возвратить ошибку ER_GIS_INVALID_DATA, если любой параметр не допустимая строка геометрии (SRID плюс значение WKB).
    • Иначе вернуть не-NULL.

    mysql> SET @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
    mysql> SET @g2 = ST_GeomFromText('Point(1 1)');
    mysql> SELECT MBRCovers(@g1,@g2), MBRCoveredby(@g1,@g2);
    +--------------------+-----------------------+
    | MBRCovers(@g1,@g2) | MBRCoveredby(@g1,@g2) |
    +--------------------+-----------------------+
    |  1                 | 0                     |
    +--------------------+-----------------------+
    
    mysql> SELECT MBRCovers(@g2,@g1), MBRCoveredby(@g2,@g1);
    +--------------------+-----------------------+
    | MBRCovers(@g2,@g1) | MBRCoveredby(@g2,@g1) |
    +--------------------+-----------------------+
    |  0                 | 1                     |
    +--------------------+-----------------------+
    
  • MBRCovers(g1 ,g2)

    Возвращает 1 или 0, чтобы указать, покрывает ли минимальный ограничительный прямоугольник g1 прямоугольник g2. Это проверяет противоположные отношения как MBRCoveredBy().

  • MBRDisjoint(g1 ,g2)

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

  • MBREquals(g1 , g2)

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

  • MBRIntersects(g1 ,g2)

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

  • MBROverlaps(g1 ,g2)

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

  • MBRTouches(g1 ,g2)

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

  • MBRWithin(g1 ,g2)

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

    mysql> SET @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
    mysql> SET @g2 = ST_GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))');
    mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);
    +--------------------+--------------------+
    | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |
    +--------------------+--------------------+
    |  1                 |  0                 |
    +--------------------+--------------------+
    

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

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

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

  • ST_GeoHash(longitude , latitude, max_length), ST_GeoHash(point , max_length)

    Возвращает строку geohash в наборе символов соединения и сопоставлении. Результат NULL если какой-либо параметр NULL. Ошибка происходит, если какой-либо параметр недопустим.

    Для первого синтаксиса longitude должно быть числом в диапазоне [-180, 180], а latitude должно быть числом в диапазоне [-90, 90]. Для второго синтаксиса требуется значение POINT, где координаты X и Y находятся в допустимых диапазонах для долготы и широты, соответственно.

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

    mysql> SELECT ST_GeoHash(180,0,10), ST_GeoHash(-180,-90,15);
    +----------------------+-------------------------+
    | ST_GeoHash(180,0,10) | ST_GeoHash(-180,-90,15) |
    +----------------------+-------------------------+
    | xbpbpbpbpb           | 000000000000000         |
    +----------------------+-------------------------+
    
  • ST_LatFromGeoHash( geohash_str)

    Возвращает широту из строкового значения geohash как значение DOUBLE в диапазоне [-90, 90]. Результат NULL, если какой-либо параметр NULL. Ошибка происходит, если параметр недопустим.

    Функция ST_LatFromGeoHash() читает не больше, чем 433 символа из geohash_str. Это представляет верхний предел информации во внутреннем представлении координатных значений. Символы после 433 проигнорированы, даже если они незаконны и производят ошибку.

    mysql> SELECT ST_LatFromGeoHash(ST_GeoHash(45,-20,10));
    +------------------------------------------+
    | ST_LatFromGeoHash(ST_GeoHash(45,-20,10)) |
    +------------------------------------------+
    |  -20                                     |
    +------------------------------------------+
    
  • ST_LongFromGeoHash( geohash_str)

    Возвращает долготу из строкового значения geohash как значение DOUBLE в диапазоне [-180, 180]. Результат NULL, если какой-либо параметр NULL. Ошибка происходит, если параметр недопустим.

    Замечания в описании ST_LatFromGeoHash() относительно максимального количества символов, обработанных из параметра geohash_str параметр также относятся к ST_LongFromGeoHash() .

    mysql> SELECT ST_LongFromGeoHash(ST_GeoHash(45,-20,10));
    +-------------------------------------------+
    | ST_LongFromGeoHash(ST_GeoHash(45,-20,10)) |
    +-------------------------------------------+
    | 45                                        |
    +-------------------------------------------+
    
  • ST_PointFromGeoHash(geohash_str, srid)

    Возвращает значение POINT, содержащее расшифрованное значение geohash, данное в виде строки. Координаты X и Y точки это долгота в диапазоне [-180, 180] и широта в диапазоне [-90, 90], соответственно. srid это unsigned 32-bit integer. Результат NULL, если какой-либо параметр NULL. Ошибка происходит, если какой-либо параметр недопустим.

    Замечания в описании ST_LatFromGeoHash() относительно максимального количества символов, обработанных из geohash_str применимы и для ST_PointFromGeoHash() .

    mysql> SET @gh = ST_GeoHash(45,-20,10);
    mysql> SELECT ST_AsText(ST_PointFromGeoHash(@gh,0));
    +---------------------------------------+
    | ST_AsText(ST_PointFromGeoHash(@gh,0)) |
    +---------------------------------------+
    | POINT(45 -20)                         |
    +---------------------------------------+
    

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.

  • ST_AsGeoJSON(g [, max_dec_digits [, options]])

    Производит объект GeoJSON из геометрии g. У строки объекта есть набор символов соединения и сопоставление.

    max_dec_digits, если определено, ограничивает число десятичных цифр для координат. Если не определен, этот параметр по умолчанию установлен к его максимальному значению 232-1. Минимум 0.

    options, если определено, битовая маска. Следующая таблица показывает разрешенные значения флага. Если у параметра геометрии есть SRID 0, никакой объект CRS не произведен даже для тех значений флага, которые его просят.

    Значение флагаСмысл
    0Никаких опций нет. Это значение по умолчанию, если options не задано.
    1Добавить ограничивающий прямоугольник к выводу.
    2Добавить короткий формат CRS URN к выводу. Формат значения по умолчанию: короткий формат (EPSG:srid).
    4Добавить длинный формат CRS URN к выводу (urn:ogc:def:crs:EPSG::srid). Этот флаг переопределяет 2. Например, значения опции 5 и 7 означают то же самое (добавить ограничивающий прямоугольник и длинный формат CRS URN).

    Если какой-либо параметр NULL, возвращаемое значение NULL. Если любой параметр не-NULL недопустим, ошибка происходит.

    mysql> SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)'),2);
    +-------------------------------------------------------------+
    | ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)'),2) |
    +-------------------------------------------------------------+
    | {"type": "Point", "coordinates": [11.11, 12.22]}            |
    +-------------------------------------------------------------+
    
  • ST_GeomFromGeoJSON(str[, options[, srid]])

    Разбирает строку str, представляющую объект GeoJSON и возвращает геометрию.

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

    Значение опцииСмысл
    1 Отклонить документ и произвести ошибку. Это значение по умолчанию, если options не определен.
    2, 3, 4 Принять документ и обрезать координаты для более высоких координатных измерений.

    Значения options 2, 3 и 4 в настоящее время оказывают то же самое влияние. Если конфигурации с координатными измерениями выше 2 будут поддержаны в будущем, то эти значения окажут различные влияния.

    Параметр srid, если дан, должен быть 32-bit unsigned integer. Если не дан, у возвращаемого значения геометрии есть SRID 4326.

    У геометрии GeoJSON, объектов feature и feature collection может быть свойство crs. Разборы функции парсинга под названием CRS URN в пространствах имен urn:ogc:def:crs:EPSG::srid и EPSG:srid, но не CRS, данный как объект ссылки. Кроме того, urn:ogc:def:crs:OGC:1.3:CRS84 признан как SRID 4326. Если у объекта есть CRS, который не понят, ошибка происходит, за исключением того, что если дополнительный параметр srid дан, любой CRS проигнорирован, даже если это недопустимо.

    Как определено в спецификации GeoJSON, парсинг является чувствительным к регистру для члена type ввода GeoJSON (Point, LineString и т.д.). Спецификация ничего не определяет относительно чувствительности к регистру для другого парсинга, который в MySQL не является чувствительным к регистру.

    Если какой-либо параметр NULL, возвращаемое значение NULL. Если любой параметр не-NULL недопустим, происходит ошибка.

    Этот пример показывает результат парсинга для простого объекта GeoJSON:

    mysql> SET @json = '{ "type": "Point", "coordinates": [102.0, 0.0]}';
    mysql> SELECT ST_AsText(ST_GeomFromGeoJSON(@json));
    +--------------------------------------+
    | ST_AsText(ST_GeomFromGeoJSON(@json)) |
    +--------------------------------------+
    | POINT(102 0)                         |
    +--------------------------------------+
    

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

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

  • ST_Distance_Sphere( g1, g2 [,radius ])

    Возвращает минимальное сферическое расстояние между двумя точками и/или мультиточками на сфере, в метрах или NULL, если какой-либо параметр геометрии NULL или пустой.

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

    Параметры геометрии должны состоять из пунктов, которые определяют (долгота, широта) координатные значения:

    • Долгота и широта первые и вторые координаты пункта, соответственно.

    • Обе координаты в градусах.
    • Значения долготы должны быть в диапазоне (-180, 180]. Положительные значения к востоку от главного меридиана.
    • Значения широты должны быть в диапазоне [-90, 90]. Положительные значения к северу от экватора.

    Поддержанные комбинации параметра (Point, Point), (Point, MultiPoint), и (MultiPoint, Point). Ошибка ER_GIS_UNSUPPORTED_ARGUMENT происходит для других комбинаций.

    Ошибка ER_GIS_INVALID_DATA происходит, если какой-либо параметр геометрии не допустимая строка геометрии.

    mysql> SET @pt1 = ST_GeomFromText('POINT(0 0)');
    mysql> SET @pt2 = ST_GeomFromText('POINT(180 0)');
    mysql> SELECT ST_Distance_Sphere(@pt1, @pt2);
    +--------------------------------+
    | ST_Distance_Sphere(@pt1, @pt2) |
    +--------------------------------+
    |   20015042.813723423           |
    +--------------------------------+
    
  • ST_IsValid(g )

    Проверяет, допустима ли геометрия, как определено спецификацией OGC. ST_IsValid() Возвращает 1, если параметр допустимая строка геометрии и геометрически допустим, 0, если параметр не допустимая строка геометрии или не геометрически допустим, NULL если параметр NULL.

    Единственная допустимая пустая геометрия представлена в форме пустого значения набора геометрии. ST_IsValid() возвращает 1 в этом случае.

    ST_IsValid() работает только для декартовой системы координат и требует параметра геометрии с SRID 0. Иначе будет ошибка ER_WRONG_ARGUMENTS .

    mysql> SET @ls1 = ST_GeomFromText('LINESTRING(0 0)');
    mysql> SET @ls2 = ST_GeomFromText('LINESTRING(0 0, 1 1)');
    mysql> SELECT ST_IsValid(@ls1);
    +------------------+
    | ST_IsValid(@ls1) |
    +------------------+
    | 0                |
    +------------------+
    
    mysql> SELECT ST_IsValid(@ls2);
    +------------------+
    | ST_IsValid(@ls2) |
    +------------------+
    | 1                |
    +------------------+
    
  • ST_MakeEnvelope( pt1, pt2)

    Возвращает прямоугольник, который формирует конверт вокруг двух точек. Возвращенная геометрия Point, LineString, Polygon или NULL, если какой-либо параметр NULL.

    Вычисления сделаны, используя декартовую систему координат, а не на сфере, сфероиде или Земле.

    Учитывая два пункта pt1 и pt2, ST_MakeEnvelope() создает геометрию результата в абстрактном плане так:

    • Если pt1 = pt2, результат pt1.

    • Иначе, если (pt1, pt2) вертикальный или горизонтальный линейный сегмент, результат линейный сегмент (pt1, pt2).
    • Иначе результат многоугольник, использующий pt1 и pt2 как точки диагонали.

    У геометрии результата есть SRID 0.

    ST_MakeEnvelope() требует параметры Point геометрии с SRID 0. Иначе будет ошибка ER_WRONG_ARGUMENTS.

    Ошибка ER_GIS_INVALID_DATA происходит, если какой-либо параметр не допустимая строка геометрии, или если какое-либо координатное значение двух пунктов бесконечно (то есть, NaN).

    mysql> SET @pt1 = ST_GeomFromText('POINT(0 0)');
    mysql> SET @pt2 = ST_GeomFromText('POINT(1 1)');
    mysql> SELECT ST_AsText(ST_MakeEnvelope(@pt1, @pt2));
    +----------------------------------------+
    | ST_AsText(ST_MakeEnvelope(@pt1, @pt2)) |
    +----------------------------------------+
    | POLYGON((0 0,1 0,1 1,0 1,0 0))         |
    +----------------------------------------+
    
  • ST_Simplify(g , max_distance)

    Упрощает геометрию, используя алгоритм Дугласа-Пеукера и возвращает упрощенное значение того же самого типа или NULL, если какой-либо параметр NULL.

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

    Параметр max_distance расстояние (в единицах входных координат) вершины к другим сегментам, которые будут удалены. Вершины в пределах этого расстояния удалены. Ошибка ER_WRONG_ARGUMENTS происходит, если max_distance не положителен или является NaN.

    Согласно Boost.Geometry, конфигурации могли бы стать недопустимыми в результате процесса упрощения, и процесс мог бы создать самопересечения. Если Вы хотите проверить законность результата, передайте его ST_IsValid().

    Ошибка ER_GIS_INVALID_DATA происходит, если параметр геометрии не допустимая строка геометрии.

    mysql> SET @g = ST_GeomFromText('LINESTRING(0 0,0 1,1 1,1 2,2 2,2 3,3 3)');
    mysql> SELECT ST_AsText(ST_Simplify(@g, 0.5));
    +---------------------------------+
    | ST_AsText(ST_Simplify(@g, 0.5)) |
    +---------------------------------+
    | LINESTRING(0 0,0 1,1 1,2 3,3 3) |
    +---------------------------------+
    
    mysql> SELECT ST_AsText(ST_Simplify(@g, 1.0));
    +---------------------------------+
    | ST_AsText(ST_Simplify(@g, 1.0)) |
    +---------------------------------+
    | LINESTRING(0 0,3 3)             |
    +---------------------------------+
    mysql> SELECT ST_AsText(ST_Simplify(@g));
    
  • ST_Validate(g )

    Утверждает геометрию согласно спецификации OGC. ST_Validate() возвращает геометрию, если это допустимая строка геометрии и геометрически допустимо, NULL, если параметр не допустимая строка геометрии, геометрически недопустим или NULL.

    Геометрия может быть допустимой строкой (значение WKB плюс SRID), но геометрически недопустимой. Например, этот многоугольник геометрически недопустим: POLYGON((0 0, 0 0, 0 0, 0 0, 0 0)).

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

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

    Единственная допустимая пустая геометрия представлена в форме пустого значения набора геометрии. ST_Validate() возвращает это непосредственно без дальнейших проверок в этом случае.

    ST_Validate() работает только для декартовой системы координат и требуют параметра геометрии с SRID 0. Иначе произойдет ошибка ER_WRONG_ARGUMENTS .

    mysql> SET @ls1 = ST_GeomFromText('LINESTRING(0 0)');
    mysql> SET @ls2 = ST_GeomFromText('LINESTRING(0 0, 1 1)');
    mysql> SELECT ST_AsText(ST_Validate(@ls1));
    +------------------------------+
    | ST_AsText(ST_Validate(@ls1)) |
    +------------------------------+
    | NULL                         |
    +------------------------------+
    
    mysql> SELECT ST_AsText(ST_Validate(@ls2));
    +------------------------------+
    | ST_AsText(ST_Validate(@ls2)) |
    +------------------------------+
    | LINESTRING(0 0,1 1)          |
    +------------------------------+
    

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_ARRAY([val [, val] ...])

    Оценивает (возможно пустой) список значений и возвращает массив JSON, содержащий те значения.

    mysql> SELECT JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME());
    +---------------------------------------------+
    | JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME()) |
    +---------------------------------------------+
    | [1, "abc", null, true, "11:30:24.000000"]   |
    +---------------------------------------------+
    
  • JSON_OBJECT([key , val[, key, val] ...])

    Оценивает (возможно пустой) список пар ключа/значения и возвращает объект JSON, содержащий те пары. Ошибка происходит, если какое-либо ключевое имя NULL или число параметров является странным.

    mysql> SELECT JSON_OBJECT('id', 87, 'name', 'carrot');
    +-----------------------------------------+
    | JSON_OBJECT('id', 87, 'name', 'carrot') |
    +-----------------------------------------+
    | {"id": 87, "name": "carrot"}            |
    +-----------------------------------------+
    
  • JSON_QUOTE(json_val )

    Заключает строку в кавычки как значение JSON символами двойной кавычки и экранируя внутренние кавычки и другие символы, возвращая результат как строку utf8mb4. Возвращает NULL, если параметр NULL.

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

    Определенные специальные символы оставляют с наклонными чертами влево как escape-последовательности, показанные в таблице 13.21.

    mysql> SELECT JSON_QUOTE('null'), JSON_QUOTE('"null"');
    +--------------------+----------------------+
    | JSON_QUOTE('null') | JSON_QUOTE('"null"') |
    +--------------------+----------------------+
    | "null"             | "\"null\""           |
    +--------------------+----------------------+
    
    mysql> SELECT JSON_QUOTE('[1, 2, 3]');
    +-------------------------+
    | JSON_QUOTE('[1, 2, 3]') |
    +-------------------------+
    | "[1, 2, 3]"             |
    +-------------------------+
    

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

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

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

  • JSON_CONTAINS( json_doc, val[, path])

    Возвращает 0 или 1, чтобы указать, содержится ли определенное значение в цели документа JSON или, если задан параметр path, в определенном пути в пределах целевого документа. Возвращает NULL, если какой-либо параметр NULL или параметр пути не идентифицирует раздел целевого документа. Ошибка происходит, если или параметр документа не допустимый документ JSON или параметр path недопустимое выражение пути или содержит подстановочный знак * (или **).

    Чтобы проверить только, существуют ли какие-либо данные в пути, надо использовать JSON_CONTAINS_PATH().

    Следующие правила определяют логику:

    • Скаляр кандидата содержится в целевом скаляре, если и только если они сопоставимы и равны. Два скалярных значения сопоставимы, если у них есть те же самые типы JSON_TYPE() , за исключением того, что значения типов INTEGER и DECIMAL также сопоставимы друг с другом.

    • Массив кандидата содержится в целевом массиве, если и только если каждый элемент в кандидате содержится в некотором элементе цели.
    • Немассив кандидата содержится в целевом массиве, если и только если кандидат содержится в некотором элементе цели.
    • Объект кандидата содержится в целевом объекте, если и только если для каждого ключа в кандидате есть ключ с тем же самым именем в цели, и значение, связанное с возможным ключом, содержится в значении, связанном с целевым ключом.

    Иначе значение кандидата не содержится в целевом документе.

    mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
    mysql> SET @j2 = '1';
    mysql> SELECT JSON_CONTAINS(@j, @j2, '$.a');
    +-------------------------------+
    | JSON_CONTAINS(@j, @j2, '$.a') |
    +-------------------------------+
    |   1                           |
    +-------------------------------+
    
    mysql> SELECT JSON_CONTAINS(@j, @j2, '$.b');
    +-------------------------------+
    | JSON_CONTAINS(@j, @j2, '$.b') |
    +-------------------------------+
    |   0                           |
    +-------------------------------+
    
    mysql> SET @j2 = '{"d": 4}';
    mysql> SELECT JSON_CONTAINS(@j, @j2, '$.a');
    +-------------------------------+
    | JSON_CONTAINS(@j, @j2, '$.a') |
    +-------------------------------+
    |   0                           |
    +-------------------------------+
    
    mysql> SELECT JSON_CONTAINS(@j, @j2, '$.c');
    +-------------------------------+
    | JSON_CONTAINS(@j, @j2, '$.c') |
    +-------------------------------+
    |   1                           |
    +-------------------------------+
    
  • JSON_CONTAINS_PATH( json_doc, one_or_all, path[, path] ...)

    Возвращает 0 или 1, чтобы указать, содержит ли документ JSON данные в заданном пути или путях. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если параметр json_doc не допустимый документ JSON, любой параметр path не допустимое выражение пути или one_or_all не 'one' или 'all'.

    Чтобы проверить на определенное значение в пути, надо использовать JSON_CONTAINS().

    Возвращаемое значение 0, если никакой указанный путь не существует в пределах документа. Иначе, возвращаемое значение зависит от параметра one_or_all:

    • 'one': 1, если по крайней мере один путь существует в пределах документа, 0 иначе.

    • 'all': 1, если все пути существуют в пределах документа, 0 иначе.

    mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
    mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e');
    +---------------------------------------------+
    | JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e') |
    +---------------------------------------------+
    |   1                                         |
    +---------------------------------------------+
    
    mysql> SELECT JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e');
    +---------------------------------------------+
    | JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e') |
    +---------------------------------------------+
    |   0                                         |
    +---------------------------------------------+
    
    mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.c.d');
    +----------------------------------------+
    | JSON_CONTAINS_PATH(@j, 'one', '$.c.d') |
    +----------------------------------------+
    |  1                                     |
    +----------------------------------------+
    
    mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a.d');
    +----------------------------------------+
    | JSON_CONTAINS_PATH(@j, 'one', '$.a.d') |
    +----------------------------------------+
    |  0                                     |
    +----------------------------------------+
    
  • JSON_EXTRACT( json_doc, path[, path] ...)

    Возвращает данные из документа JSON, выбранные из частей документа, соответствующих path. Возвращает NULL если какой-либо параметр NULL или никакие пути не определяют местонахождение значения в документе. Ошибка происходит, если параметр json_doc не допустимый документ JSON или любой параметр path не допустимое выражение пути.

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

    mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]');
    +--------------------------------------------+
    | JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]') |
    +--------------------------------------------+
    | 20                                         |
    +--------------------------------------------+
    
    mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]');
    +----------------------------------------------------+
    | JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]') |
    +----------------------------------------------------+
    | [20, 10]                                           |
    +----------------------------------------------------+
    
    mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]');
    +-----------------------------------------------+
    | JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]') |
    +-----------------------------------------------+
    | [30, 40]                                      |
    +-----------------------------------------------+
    

    MySQL поддерживает оператор -> как сокращение для для этой функции при использовании с 2 параметрами, где левая сторона идентификатор столбца JSON (не выражение) и правая сторона является путем JSON, который будет соответствующим в пределах столбца.

  • column ->path

    Оператор -> служит псевдонимом для JSON_EXTRACT(), когда функция используется с двумя параметрами, идентификатор столбца слева и путь JSON справа, который оценен против документа JSON (значение столбца). Вы можете использовать такие выражения вместо идентификаторов столбца везде, где они происходят в запросах SQL.

    Два запроса SELECT, показанные здесь, производят тот же самый вывод:

    mysql> SELECT c, JSON_EXTRACT(c, "$.id"), g FROM jemp
         >           WHERE JSON_EXTRACT(c, "$.id") > 1
         >           ORDER BY JSON_EXTRACT(c, "$.name");
    +-------------------------------+-----------+------+
    | c                             | c->"$.id" | g |
    +-------------------------------+-----------+------+
    | {"id": "3", "name": "Barney"} | "3"       | 3    |
    | {"id": "4", "name": "Betty"}  | "4"       | 4    |
    | {"id": "2", "name": "Wilma"}  | "2"       | 2    |
    +-------------------------------+-----------+------+
    3 rows in set (0.00 sec)
    
    mysql> SELECT c, c->"$.id", g FROM jemp
         >           WHERE c->"$.id" > 1
         >           ORDER BY c->"$.name";
    +-------------------------------+-----------+------+
    | c                             | c->"$.id" | g |
    +-------------------------------+-----------+------+
    | {"id": "3", "name": "Barney"} | "3"       | 3    |
    | {"id": "4", "name": "Betty"}  | "4"       | 4    |
    | {"id": "2", "name": "Wilma"}  | "2"       | 2    |
    +-------------------------------+-----------+------+
    3 rows in set (0.00 sec)
    

    Эта функциональность не ограничена SELECT, как показано здесь:

    mysql> ALTER TABLE jemp ADD COLUMN n INT;
    Query OK, 0 rows affected (0.68 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> UPDATE jemp SET n=1 WHERE c->"$.id" = "4";
    Query OK, 1 row affected (0.04 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT c, c->"$.id", g, n FROM jemp
         >           WHERE JSON_EXTRACT(c, "$.id") > 1
         >           ORDER BY c->"$.name";
    +-------------------------------+-----------+------+------+
    | c                             | c->"$.id" | g | n    |
    +-------------------------------+-----------+------+------+
    | {"id": "3", "name": "Barney"} | "3"       | 3    | NULL |
    | {"id": "4", "name": "Betty"}  | "4"       | 4    | 1    |
    | {"id": "2", "name": "Wilma"}  | "2"       | 2    | NULL |
    +-------------------------------+-----------+------+------+
    3 rows in set (0.00 sec)
    
    mysql> DELETE FROM jemp WHERE c->"$.id" = "4";
    Query OK, 1 row affected (0.04 sec)
    
    mysql> SELECT c, c->"$.id", g, n FROM jemp
         >           WHERE JSON_EXTRACT(c, "$.id") > 1
         >           ORDER BY c->"$.name";
    +-------------------------------+-----------+------+------+
    | c                             | c->"$.id" | g   | n    |
    +-------------------------------+-----------+------+------+
    | {"id": "3", "name": "Barney"} | "3"       | 3    | NULL |
    | {"id": "2", "name": "Wilma"}  | "2"       | 2    | NULL |
    +-------------------------------+-----------+------+------+
    2 rows in set (0.00 sec)
    

    Это также работает со значениями массива JSON, как показано здесь:

    mysql> CREATE TABLE tj10 (a JSON, b INT);
    Query OK, 0 rows affected (0.26 sec)
    
    mysql> INSERT INTO tj10
         >        VALUES ("[3,10,5,17,44]", 33), ("[3,10,5,17,[22,44,66]]", 0);
    Query OK, 1 row affected (0.04 sec)
    
    mysql> SELECT a->"$[4]" FROM tj10;
    +--------------+
    | a->"$[4]" |
    +--------------+
    | 44           |
    | [22, 44, 66] |
    +--------------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT * FROM tj10 WHERE a->"$[0]" = 3;
    +------------------------------+---+
    | a                            | b |
    +------------------------------+---+
    | [3, 10, 5, 17, 44]           |33 |
    | [3, 10, 5, 17, [22, 44, 66]] | 0 |
    +------------------------------+---+
    2 rows in set (0.00 sec)
    

    Поддержаны вложенные массивы. Использование выражения -> оценивается какe NULL, если никакой ключ соответствия не найден в цели документа JSON, как показано здесь:

    mysql> SELECT * FROM tj10 WHERE a->"$[4][1]" IS NOT NULL;
    +------------------------------+---+
    | a                            | b |
    +------------------------------+---+
    | [3, 10, 5, 17, [22, 44, 66]] | 0 |
    +------------------------------+---+
    
    mysql> SELECT a->"$[4][1]" FROM tj10;
    +--------------+
    | a->"$[4][1]" |
    +--------------+
    | NULL         |
    | 44           |
    +--------------+
    2 rows in set (0.00 sec)
    

    Это то же самое поведение, как в таких случаях, используя JSON_EXTRACT():

    mysql> SELECT JSON_EXTRACT(a, "$[4][1]") FROM tj10;
    +----------------------------+
    | JSON_EXTRACT(a, "$[4][1]") |
    +----------------------------+
    | NULL                       |
    | 44                         |
    +----------------------------+
    2 rows in set (0.00 sec)
    
  • column ->>path

    Это улучшенный, закрывающий кавычки оператор извлечения. Принимая во внимание, что оператор -> просто извлекает значение, ->> кроме того, закрывает кавычки в извлеченном результате. Другими словами, для данного значения столбца JSON column и выражение пути path следующие три выражения возвращают то же самое значение:

    Оператор ->> может использоваться везде, где JSON_UNQUOTE(JSON_EXTRACT()) был бы позволен. Это включает (но не ограничено) списки SELECT, предложения WHERE и HAVING, определения ORDER BY и GROUP BY .

    Следующие запросы демонстрируют некоторые эквиваленты оператора ->> с другими выражениями в клиенте mysql:

    mysql> SELECT * FROM jemp WHERE g > 2;
    +-------------------------------+---+
    | c                             | g |
    +-------------------------------+---+
    | {"id": "3", "name": "Barney"} | 3 |
    | {"id": "4", "name": "Betty"}  | 4 |
    +-------------------------------+---+
    2 rows in set (0.01 sec)
    
    mysql> SELECT c->'$.name' AS name FROM jemp WHERE g > 2;
    +----------+
    | name     |
    +----------+
    | "Barney" |
    | "Betty"  |
    +----------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT JSON_UNQUOTE(c->'$.name') AS name
        ->        FROM jemp WHERE g > 2;
    +--------+
    | name   |
    +--------+
    | Barney |
    | Betty  |
    +--------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT c->>'$.name' AS name
        ->        FROM jemp WHERE g > 2;
    +--------+
    | name   |
    +--------+
    | Barney |
    | Betty  |
    +--------+
    2 rows in set (0.00 sec)
    

    Этот оператор может также использоваться с массивами JSON, как показано здесь:

    mysql> CREATE TABLE tj10 (a JSON, b INT);
    Query OK, 0 rows affected (0.26 sec)
    
    mysql> INSERT INTO tj10 VALUES
        ->        ('[3,10,5,"x",44]', 33),
        ->        ('[3,10,5,17,[22,"y",66]]', 0);
    Query OK, 2 rows affected (0.04 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> SELECT a->"$[3]", a->"$[4][1]" FROM tj10;
    +-----------+--------------+
    | a->"$[3]" | a->"$[4][1]" |
    +-----------+--------------+
    | "x"       | NULL         |
    | 17        |  "y"         |
    +-----------+--------------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT a->>"$[3]", a->>"$[4][1]" FROM tj10;
    +------------+---------------+
    | a->>"$[3]" | a->>"$[4][1]" |
    +------------+---------------+
    | x          | NULL          |
    | 17         | y             |
    +------------+---------------+
    2 rows in set (0.00 sec)
    

    Как с -> , оператор ->> всегда расширяется в выводе EXPLAIN, как следующий пример демонстрирует:

    mysql> EXPLAIN SELECT c->>'$.name' AS name
        ->         FROM jemp WHERE g > 2\G
    *************************** 1. row ***************************
     id: 1
      select_type: SIMPLE
      table: jemp
       partitions: NULL
       type: range
    possible_keys: i
    key: i
    key_len: 5
    ref: NULL
       rows: 2
     filtered: 100.00
      Extra: Using where
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Note
       Code: 1003
    Message: /* select#1 */ select
    json_unquote(json_extract(`jtest`.`jemp`.`c`,'$.name')) AS `name` from
                 `jtest`.`jemp` where (`jtest`.`jemp`.`g` > 2)
    1 row in set (0.00 sec)
    

    Это подобно тому, как MySQL расширяет оператор -> при тех же самых обстоятельствах.

  • JSON_KEYS(json_doc [, path])

    Возвращает ключи из высокоуровневого значения объекта JSON как массив JSON или если параметр path задан, высокоуровневые ключи из выбранного пути. Возвращает NULL, если какой-либо параметр NULL, параметр json_doc не объект или path, если задан, не определяет местонахождение объекта. Ошибка происходит, если параметр json_doc не допустимый документ JSON или path не допустимое выражение пути или содержит подстановочный знак * или **.

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

    mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}');
    +---------------------------------------+
    | JSON_KEYS('{"a": 1, "b": {"c": 30}}') |
    +---------------------------------------+
    | ["a", "b"]                            |
    +---------------------------------------+
    
    mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b');
    +----------------------------------------------+
    | JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b') |
    +----------------------------------------------+
    | ["c"]                                        |
    +----------------------------------------------+
    
  • JSON_SEARCH( json_doc, one_or_all, search_str[, escape_char[, path] ...])

    Возвращает путь к данной строке в пределах документа JSON. Возвращает Returns NULL, если любой из параметров json_doc, search_str или path NULL, path не существует в пределах документа, search_str не найден. Ошибка происходит, если json_doc не допустимый документ JSON, любой параметр path не допустимое выражение пути, one_or_all не 'one' или 'all' или escape_char не постоянное выражение.

    Параметр one_or_all затрагивает поиск следующим образом:

    • 'one': Поиск заканчивается после первого соответствия и возвращает одну строку пути. Не определено, какое соответствие считают первым.

    • 'all': Поиск возвращает все строки пути соответствия, таким образом, что никакие дублирующие пути не включены. Если есть много строк, они оформлены как массив. Порядок элементов массива неопределен.

    В пределах поисковой строки search_str символы % и _ работают как в операторе LIKE: % соответствует любому числу символов (включая нулевые символы), а _ соответствует точно одному символу.

    Чтобы определить символ % или _ в строке поиска, предварите его символом ESC. Значение по умолчанию \, если параметр escape_char отсутствует или NULL. Иначе escape_char должен быть константой, которая пуста или один символ.

    Для обработки символа ESC, отличие от поведения LIKE состоит в том что символ ESC для JSON_SEARCH() должен быть оценен как константа во время компиляции, не только во время выполнения. Например, если JSON_SEARCH() используется в готовом запросе и параметр escape_char поставляется, используя ?, значение параметра могло бы быть постоянным во время выполнения, но не во время компиляции.

    mysql> SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]';
    mysql> SELECT JSON_SEARCH(@j, 'one', 'abc');
    +-------------------------------+
    | JSON_SEARCH(@j, 'one', 'abc') |
    +-------------------------------+
    | "$[0]"                        |
    +-------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', 'abc');
    +-------------------------------+
    | JSON_SEARCH(@j, 'all', 'abc') |
    +-------------------------------+
    | ["$[0]", "$[2].x"]            |
    +-------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', 'ghi');
    +-------------------------------+
    | JSON_SEARCH(@j, 'all', 'ghi') |
    +-------------------------------+
    | NULL                          |
    +-------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10');
    +------------------------------+
    | JSON_SEARCH(@j, 'all', '10') |
    +------------------------------+
    | "$[1][0].k"                  |
    +------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$');
    +-----------------------------------------+
    | JSON_SEARCH(@j, 'all', '10', NULL, '$') |
    +-----------------------------------------+
    | "$[1][0].k"                             |
    +-----------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*]');
    +--------------------------------------------+
    | JSON_SEARCH(@j, 'all', '10', NULL, '$[*]') |
    +--------------------------------------------+
    | "$[1][0].k"                                |
    +--------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$**.k');
    +---------------------------------------------+
    | JSON_SEARCH(@j, 'all', '10', NULL, '$**.k') |
    +---------------------------------------------+
    | "$[1][0].k"                                 |
    +---------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k');
    +-------------------------------------------------+
    | JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k') |
    +-------------------------------------------------+
    | "$[1][0].k"                                     |
    +-------------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1]');
    +--------------------------------------------+
    | JSON_SEARCH(@j, 'all', '10', NULL, '$[1]') |
    +--------------------------------------------+
    | "$[1][0].k"                                |
    +--------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]');
    +-----------------------------------------------+
    | JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]') |
    +-----------------------------------------------+
    | "$[1][0].k"                                   |
    +-----------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]');
    +---------------------------------------------+
    | JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]') |
    +---------------------------------------------+
    | "$[2].x"                                    |
    +---------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%a%');
    +-------------------------------+
    | JSON_SEARCH(@j, 'all', '%a%') |
    +-------------------------------+
    | ["$[0]", "$[2].x"]            |
    +-------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%b%');
    +-------------------------------+
    | JSON_SEARCH(@j, 'all', '%b%') |
    +-------------------------------+
    | ["$[0]", "$[2].x", "$[3].y"]  |
    +-------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]');
    +---------------------------------------------+
    | JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]') |
    +---------------------------------------------+
    | "$[0]"                                      |
    +---------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]');
    +---------------------------------------------+
    | JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]') |
    +---------------------------------------------+
    | "$[2].x"                                    |
    +---------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]');
    +---------------------------------------------+
    | JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]') |
    +---------------------------------------------+
    | NULL                                        |
    +---------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[1]');
    +-------------------------------------------+
    | JSON_SEARCH(@j, 'all', '%b%', '', '$[1]') |
    +-------------------------------------------+
    | NULL                                      |
    +-------------------------------------------+
    
    mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[3]');
    +-------------------------------------------+
    | JSON_SEARCH(@j, 'all', '%b%', '', '$[3]') |
    +-------------------------------------------+
    | "$[3].y"                                  |
    +-------------------------------------------+
    

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

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

  • JSON_APPEND( json_doc, path, val[, path, val] ...)

    Эта функция была переименована в JSON_ARRAY_APPEND() .

  • JSON_ARRAY_APPEND( json_doc, path, val[, path, val] ...)

    Добавляет значения в конец обозначенных массивов в пределах документа JSON и возвращает результат. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если json_doc не допустимый документ JSON или любой параметр path не допустимое выражение пути или содержит подстановочный знак * или **.

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

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

    mysql> SET @j = '["a", ["b", "c"], "d"]';
    mysql> SELECT JSON_ARRAY_APPEND(@j, '$[1]', 1);
    +----------------------------------+
    | JSON_ARRAY_APPEND(@j, '$[1]', 1) |
    +----------------------------------+
    | ["a", ["b", "c", 1], "d"]        |
    +----------------------------------+
    
    mysql> SELECT JSON_ARRAY_APPEND(@j, '$[0]', 2);
    +----------------------------------+
    | JSON_ARRAY_APPEND(@j, '$[0]', 2) |
    +----------------------------------+
    | [["a", 2], ["b", "c"], "d"]      |
    +----------------------------------+
    
    mysql> SELECT JSON_ARRAY_APPEND(@j, '$[1][0]', 3);
    +-------------------------------------+
    | JSON_ARRAY_APPEND(@j, '$[1][0]', 3) |
    +-------------------------------------+
    | ["a", [["b", 3], "c"], "d"]         |
    +-------------------------------------+
    
    mysql> SET @j = '{"a": 1, "b": [2, 3], "c": 4}';
    mysql> SELECT JSON_ARRAY_APPEND(@j, '$.b', 'x');
    +------------------------------------+
    | JSON_ARRAY_APPEND(@j, '$.b', 'x')  |
    +------------------------------------+
    | {"a": 1, "b": [2, 3, "x"], "c": 4} |
    +------------------------------------+
    
    mysql> SELECT JSON_ARRAY_APPEND(@j, '$.c', 'y');
    +--------------------------------------+
    | JSON_ARRAY_APPEND(@j, '$.c', 'y')    |
    +--------------------------------------+
    | {"a": 1, "b": [2, 3], "c": [4, "y"]} |
    +--------------------------------------+
    
    mysql> SET @j = '{"a": 1}';
    mysql> SELECT JSON_ARRAY_APPEND(@j, '$', 'z');
    +---------------------------------+
    | JSON_ARRAY_APPEND(@j, '$', 'z') |
    +---------------------------------+
    | [{"a": 1}, "z"]                 |
    +---------------------------------+
    
  • JSON_ARRAY_INSERT( json_doc, path, val[, path, val] ...)

    Обновляет документ JSON, вставляя в массив в пределах документа и возвращая измененный документ. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если json_doc не допустимый документ JSON или любой параметр path не допустимое выражение пути, содержит подстановочный знак * или ** или не заканчивается идентификатором элемента массива.

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

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

    mysql> SET @j = '["a", {"b": [1, 2]}, [3, 4]]';
    mysql> SELECT JSON_ARRAY_INSERT(@j, '$[1]', 'x');
    +------------------------------------+
    | JSON_ARRAY_INSERT(@j, '$[1]', 'x') |
    +------------------------------------+
    | ["a", "x", {"b": [1, 2]}, [3, 4]]  |
    +------------------------------------+
    
    mysql> SELECT JSON_ARRAY_INSERT(@j, '$[100]', 'x');
    +--------------------------------------+
    | JSON_ARRAY_INSERT(@j, '$[100]', 'x') |
    +--------------------------------------+
    | ["a", {"b": [1, 2]}, [3, 4], "x"]    |
    +--------------------------------------+
    
    mysql> SELECT JSON_ARRAY_INSERT(@j, '$[1].b[0]', 'x');
    +-----------------------------------------+
    | JSON_ARRAY_INSERT(@j, '$[1].b[0]', 'x') |
    +-----------------------------------------+
    | ["a", {"b": ["x", 1, 2]}, [3, 4]]       |
    +-----------------------------------------+
    
    mysql> SELECT JSON_ARRAY_INSERT(@j, '$[2][1]', 'y');
    +---------------------------------------+
    | JSON_ARRAY_INSERT(@j, '$[2][1]', 'y') |
    +---------------------------------------+
    | ["a", {"b": [1, 2]}, [3, "y", 4]]     |
    +---------------------------------------+
    
    mysql> SELECT JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y');
    +----------------------------------------------------+
    | JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y') |
    +----------------------------------------------------+
    | ["x", "a", {"b": [1, 2]}, [3, 4]]                  |
    +----------------------------------------------------+
    

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

  • JSON_INSERT( json_doc, path, val[, path, val] ...)

    Вставляет данные в документ JSON и возвращает результат. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если параметр json_doc не допустимый документ JSON или любой параметр path не допустимое выражение пути или содержит подстановочный знак * или **.

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

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

    • Член, не присутствующий в существующем объекте. Член добавлен к объекту и связан с новым значением.

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

    Иначе пара пути/значения для несуществующего пути в документе проигнорирована и не имеет никакого эффекта.

    Для сравнения JSON_INSERT(), JSON_REPLACE() и JSON_SET() см. описание JSON_SET().

    mysql> SET @j = '{ "a": 1, "b": [2, 3]}';
    mysql> SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]');
    +----------------------------------------------------+
    | JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]') |
    +----------------------------------------------------+
    | {"a": 1, "b": [2, 3], "c": "[true, false]"}        |
    +----------------------------------------------------+
    
  • JSON_MERGE(json_doc , json_doc[, json_doc] ...)

    Сливает два или больше документа JSON и возвращает слитный результат. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если какой-либо параметр не допустимый документ JSON.

    Слияние имеет место согласно следующим правилам:

    • Смежные массивы слиты в единственный массив.

    • Смежные объекты слиты в единственный объект.
    • Скалярное значение автооформлено и слито как массив.
    • Смежные массив и объект слиты, оформляя объект как массив и сливая два массива.

    mysql> SELECT JSON_MERGE('[1, 2]', '[true, false]');
    +---------------------------------------+
    | JSON_MERGE('[1, 2]', '[true, false]') |
    +---------------------------------------+
    | [1, 2, true, false]                   |
    +---------------------------------------+
    
    mysql> SELECT JSON_MERGE('{"name": "x"}', '{"id": 47}');
    +-------------------------------------------+
    | JSON_MERGE('{"name": "x"}', '{"id": 47}') |
    +-------------------------------------------+
    | {"id": 47, "name": "x"}                   |
    +-------------------------------------------+
    
    mysql> SELECT JSON_MERGE('1', 'true');
    +-------------------------+
    | JSON_MERGE('1', 'true') |
    +-------------------------+
    | [1, true]               |
    +-------------------------+
    
    mysql> SELECT JSON_MERGE('[1, 2]', '{"id": 47}');
    +------------------------------------+
    | JSON_MERGE('[1, 2]', '{"id": 47}') |
    +------------------------------------+
    | [1, 2, {"id": 47}]                 |
    +------------------------------------+
    
  • JSON_REMOVE(json_doc , path[, path] ...)

    Удаляет данные из документа JSON и возвращает результат. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если json_doc не допустимый документ JSON или любой параметр path не допустимое выражение пути или содержит подстановочный знак $, * или **.

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

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

    mysql> SET @j = '["a", ["b", "c"], "d"]';
    mysql> SELECT JSON_REMOVE(@j, '$[1]');
    +-------------------------+
    | JSON_REMOVE(@j, '$[1]') |
    +-------------------------+
    | ["a", "d"]              |
    +-------------------------+
    
  • JSON_REPLACE( json_doc, path, val[, path, val] ...)

    Заменяет существующие значения в документе JSON и возвращает результат. Возвращает NULL, если какой-либо параметр NULL. Ошибка происходит, если параметр json_doc не допустимый документ JSONили любой path не допустимое выражение пути или содержит подстановочный знак * или **.

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

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

    mysql> SET @j = '{ "a": 1, "b": [2, 3]}';
    mysql> SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]');
    +-----------------------------------------------------+
    | JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]') |
    +-----------------------------------------------------+
    | {"a": 10, "b": [2, 3]}                              |
    +-----------------------------------------------------+
    
  • JSON_SET(json_doc , path, val[, path, val] ...)

    Вставляет или обновляет данные в документе JSON и возвращает результат. Возвращает NULL, если какой-либо параметр NULL или path, если дано, не определяет местонахождение объекта. Ошибка происходит, если json_doc не допустимый документ JSON или path не допустимое выражение пути или содержит подстановочный знак * или **.

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

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

    • Член, не присутствующий в существующем объекте. Член добавлен к объекту и связан с новым значением.

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

    Иначе пара пути/значения для несуществующего пути в документе проигнорирована и не имеет никакого эффекта.

    Функции JSON_SET(), JSON_INSERT() и JSON_REPLACE() связаны:

    • JSON_SET() заменяет существующие значения и добавляет несуществующие значения.

    • JSON_INSERT() вставляет значения, не заменяя существующие.
    • JSON_REPLACE() заменяет только существующие значения.

    Следующие примеры иллюстрируют эти различия, используя один путь, который действительно существует в документе ($.a) и другой, который не существует ($.c):

    mysql> SET @j = '{ "a": 1, "b": [2, 3]}';
    mysql> SELECT JSON_SET(@j, '$.a', 10, '$.c', '[true, false]');
    +-------------------------------------------------+
    | JSON_SET(@j, '$.a', 10, '$.c', '[true, false]') |
    +-------------------------------------------------+
    | {"a": 10, "b": [2, 3], "c": "[true, false]"}    |
    +-------------------------------------------------+
    
    mysql> SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]');
    +----------------------------------------------------+
    | JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]') |
    +----------------------------------------------------+
    | {"a": 1, "b": [2, 3], "c": "[true, false]"}        |
    +----------------------------------------------------+
    
    mysql> SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]');
    +-----------------------------------------------------+
    | JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]') |
    +-----------------------------------------------------+
    | {"a": 10, "b": [2, 3]}                              |
    +-----------------------------------------------------+
    
  • JSON_UNQUOTE(val )

    Закрывает кавычки значения JSON и возвращает результат как строку в utf8mb4. Возвращает NULL, если параметр NULL. Ошибка происходит, если значение начинается и заканчивается двойными кавычками, но не является допустимой буквальной строкой JSON.

    В пределах строки у определенных последовательностей нет особого значения, если включен режим SQL NO_BACKSLASH_ESCAPES. Каждая из этих последовательностей начинается с наклонной черты влево (\), известной как escape character. MySQL признает escape-последовательности, показанные в таблице 13.21. Для всех других escape-последовательностей проигнорирована наклонная черта влево. Таким образом, экранированный символ интерпретируется, как будто его не экранировали. Например, \x соответствует x. Эти последовательности являются чувствительными к регистру. Например, \b интерпретируется как клавиша Backspace, но \B интерпретируется только как B.

    Таблица 13.21. Специальные символы escape-последовательностей для JSON_UNQUOTE()

    Escape-последовательность Символ, представленный последовательностью
    \" Двойная кавычка (")
    \bbackspace
    \fСимвол перевода формата
    \nНовая строка
    \rВозврат каретки
    \tТабуляция
    \\ backslash (\)
    \uXXXX Байты UTF-8 для значения Unicode XXXX

    Два простых примера использования этой функции:

    mysql> SET @j = '"abc"';
    mysql> SELECT @j, JSON_UNQUOTE(@j);
    +-------+------------------+
    | @j    | JSON_UNQUOTE(@j) |
    +-------+------------------+
    | "abc" | abc              |
    +-------+------------------+
    
    mysql> SET @j = '[1, 2, 3]';
    mysql> SELECT @j, JSON_UNQUOTE(@j);
    +-----------+------------------+
    | @j        | JSON_UNQUOTE(@j) |
    +-----------+------------------+
    | [1, 2, 3] | [1, 2, 3]        |
    +-----------+------------------+
    

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

    mysql> SELECT @@sql_mode;
    +------------+
    | @@sql_mode |
    +------------+
    |            |
    +------------+
    
    mysql> SELECT JSON_UNQUOTE('"\\t\\u0032"');
    +------------------------------+
    | JSON_UNQUOTE('"\\t\\u0032"') |
    +------------------------------+
    | 2                            |
    +------------------------------+
    
    mysql> SET @@sql_mode = 'NO_BACKSLASH_ESCAPES';
    mysql> SELECT JSON_UNQUOTE('"\\t\\u0032"');
    +------------------------------+
    | JSON_UNQUOTE('"\\t\\u0032"') |
    +------------------------------+
    | \t\u0032                     |
    +------------------------------+
    
    mysql> SELECT JSON_UNQUOTE('"\t\u0032"');
    +----------------------------+
    | JSON_UNQUOTE('"\t\u0032"') |
    +----------------------------+
    | 2                          |
    +----------------------------+
    

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

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

  • JSON_DEPTH(json_doc )

    Возвращает максимальную глубину документа JSON. Возвращает NULL, если параметр NULL. Ошибка происходит, если параметр не допустимый документ JSON.

    У пустого массива, пустого объекта или скалярного значения есть глубина 1. У непустого массива, содержащего только элементы глубины 1 или непустой объект, содержащий только значения глубины 1, есть глубина 2. Иначе у документа JSON есть глубина больше 2.

    mysql> SELECT JSON_DEPTH('{}'), JSON_DEPTH('[]'), JSON_DEPTH('true');
    +------------------+------------------+--------------------+
    | JSON_DEPTH('{}') | JSON_DEPTH('[]') | JSON_DEPTH('true') |
    +------------------+------------------+--------------------+
    | 1                | 1                |  1                 |
    +------------------+------------------+--------------------+
    
    mysql> SELECT JSON_DEPTH('[10, 20]'), JSON_DEPTH('[[], {}]');
    +------------------------+------------------------+
    | JSON_DEPTH('[10, 20]') | JSON_DEPTH('[[], {}]') |
    +------------------------+------------------------+
    |  2                     |  2                     |
    +------------------------+------------------------+
    
    mysql> SELECT JSON_DEPTH('[10, {"a": 20}]');
    +-------------------------------+
    | JSON_DEPTH('[10, {"a": 20}]') |
    +-------------------------------+
    |   3                           |
    +-------------------------------+
    
  • JSON_LENGTH(json_doc [, path])

    Возвращает длину документа JSON или, если задан path, длину значения в пределах документа, идентифицированного путем. Возвращает NULL, если какой-либо параметр NULL или path не идентифицирует значение в документе. Ошибка происходит, если json_doc не допустимый документ JSON или параметр path не допустимое выражение пути или содержит подстановочный знак * или **.

    Длина документа определена следующим образом:

    • Длина скаляра 1.

    • Длина массива = число элементов массива.
    • Длина объекта = число членов объекта.
    • Длина не считает длину вложенных массивов или объектов.

    mysql> SELECT JSON_LENGTH('[1, 2, {"a": 3}]');
    +---------------------------------+
    | JSON_LENGTH('[1, 2, {"a": 3}]') |
    +---------------------------------+
    | 3                               |
    +---------------------------------+
    
    mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}');
    +-----------------------------------------+
    | JSON_LENGTH('{"a": 1, "b": {"c": 30}}') |
    +-----------------------------------------+
    |   2                                     |
    +-----------------------------------------+
    
    mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');
    +------------------------------------------------+
    | JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b') |
    +------------------------------------------------+
    | 1                                              |
    +------------------------------------------------+
    
  • JSON_TYPE(json_val )

    Возвращает строку utf8mb4, указывающую на тип значения JSON:

    mysql> SET @j = '{"a": [10, true]}';
    mysql> SELECT JSON_TYPE(@j);
    +---------------+
    | JSON_TYPE(@j) |
    +---------------+
    | OBJECT        |
    +---------------+
    
    mysql> SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a'));
    +------------------------------------+
    | JSON_TYPE(JSON_EXTRACT(@j, '$.a')) |
    +------------------------------------+
    | ARRAY                              |
    +------------------------------------+
    
    mysql> SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]'));
    +---------------------------------------+
    | JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]')) |
    +---------------------------------------+
    | INTEGER                               |
    +---------------------------------------+
    
    mysql> SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[1]'));
    +---------------------------------------+
    | JSON_TYPE(JSON_EXTRACT(@j, '$.a[1]')) |
    +---------------------------------------+
    | BOOLEAN                               |
    +---------------------------------------+
    

    JSON_TYPE() возвращает NULL, если параметр NULL:

    mysql> SELECT JSON_TYPE(NULL);
    +-----------------+
    | JSON_TYPE(NULL) |
    +-----------------+
    | NULL            |
    +-----------------+
    

    Ошибка происходит, если параметр не допустимое значение JSON:

    mysql> SELECT JSON_TYPE(1);
    ERROR 3146 (22032): Invalid data type for JSON data in argument 1
    to function json_type; a JSON string or JSON type is required.
    

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

    • Просто типы JSON:

      • OBJECT: Объекты JSON.

      • ARRAY: Массивы JSON.
      • BOOLEAN: Истинные и ложные литералы JSON.
      • NULL: Литерал JSON null.

    • Числовые типы:

    • Временные типы:

    • Строковые типы:

    • Двоичные типы:

    • Все другие типы:

      • OPAQUE (raw биты).

  • JSON_VALID(val )

    Возвращает 0 или 1, чтобы указать, является ли значение допустимым документом JSON. Возвращает NULL, если параметр NULL.

    mysql> SELECT JSON_VALID('{"a": 1}');
    +------------------------+
    | JSON_VALID('{"a": 1}') |
    +------------------------+
    |  1                     |
    +------------------------+
    
    mysql> SELECT JSON_VALID('hello'), JSON_VALID('"hello"');
    +---------------------+-----------------------+
    | JSON_VALID('hello') | JSON_VALID('"hello"') |
    +---------------------+-----------------------+
    |   0                 | 1                     |
    +---------------------+-----------------------+
    

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 не поддерживает их.

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

  • .* представляет значения всех членов в объекте.

  • [*] представляет значения всех элементов в массиве.
  • [prefix]**suffix представляет все пути, начинающиеся с prefix с окончанием suffix. prefix является дополнительным, в то время как suffix обязателен. Путь, возможно, не заканчивается в **.

    Кроме того, путь, возможно, не содержит последовательность ***.

Для примеров синтаксиса пути см. описания различных функций 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 не выполнятся на ведомом устройстве
  • GTID_SUBSET(subset ,set)

    Учитывая два набора ID subset и set, вернет истину, если все GTID в subset находятся также в set. Иначе ложь.

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

    mysql> SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23',
        ->        '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G
    *************************** 1. row ***************************
    GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 1
    1 row in set (0.00 sec)
    
    mysql> SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23-25',
        ->        '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G
    *************************** 1. row ***************************
    GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23-25',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 1
    1 row in set (0.00 sec)
    
    mysql> SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25',
        ->        '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G
    *************************** 1. row ***************************
    GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 0
    1 row in set (0.00 sec)
    
  • GTID_SUBTRACT( set,subset)

    Учитывая два набора глобальных операционных ID subset и set, возвращает только те GTID из set, которые не находятся в subset.

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

    mysql> SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
        -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:21')\G
    *************************** 1. row ***************************
    GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:21'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:22-57
    1 row in set (0.00 sec)
    
    mysql> SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
        -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25')\G
    *************************** 1. row ***************************
    GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:26-57
    1 row in set (0.00 sec)
    
    mysql> SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
        -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:23-24')\G
    *************************** 1. row ***************************
    GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57',
    '3E11FA47-71CA-11E1-9E33-C80AA9429562:23-24'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:21-22:25-57
    1 row in set (0.01 sec)
    
  • WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(gtid_set[, timeout][,channel])

    Ждать, пока ведомый поток SQL не выполнит все транзакции, глобальные операционные идентификаторы которых содержатся в gtid_set (см. раздел 19.1.3.1 для определения GTID sets), или timeout секунд, смотря что происходит сначала. timeout является дополнительным параметром: тайм-аут по умолчанию составляет 0 секунд, когда функция ждет, пока все транзакции в наборе GTID не были выполнены.

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

    mysql> SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS('3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5');
        -> 5
    

    Возвращаемое значение число транзакционных событий, которые были запущены. Если GTID-репликация не является активной (то есть, если значение gtid_mode OFF), тогда это значение неопределено и таким образом WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() вернет NULL. Если ведомое устройство не работает, эта функция также возвращает NULL.

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

  • WAIT_FOR_EXECUTED_GTID_SET(gtid_set[, timeout])

    WAIT_FOR_EXECUTED_GTID_SET() подобна WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() в том, что ждет, пока сервер не выполнит все транзакции, глобальные операционные идентификаторы которых содержатся в gtid_set, или пока не пройдет timeout секунд. В отличие от WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(), WAIT_FOR_EXECUTED_GTID_SET() не принимает во внимание, работает ли ведомое устройство или нет, и ошибка возвращена, если GTID-репликация не включена вообще.

    Кроме того, WAIT_FOR_EXECUTED_GTID_SET() возвращает только статус запроса, где 0 представляет успех, 1, представляет тайм-аут, а любые другие отказы возвращают сообщение об ошибке.

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
  • ANY_VALUE(arg )

    Эта функция полезна для запросов GROUP BY, когда включен режим SQL ONLY_FULL_GROUP_BY, для случаев, когда MySQL отклоняет запрос, который как Вы знаете, допустим по причинам, которые MySQL не может определить. Функциональное возвращаемое значение и тип те же самые, что и возвращаемое значение и тип его параметра, но функциональный результат не проверен в режиме SQL ONLY_FULL_GROUP_BY .

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

    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
    

    Отказ происходит потому, что address несоединенный столбец, который не упомянут в столбцах GROUP BY и функционально не зависит от них. В результате значение address для строк в пределах каждой группы name недетерминировано. Есть много способов заставить MySQL принимать запрос:

    • Измените таблицу, чтобы сделать name первичным ключом или уникальным столбцом NOT NULL. Это позволяет MySQL определить, что address функционально зависит от name, то есть, address уникально определен через name. Этот метод является неподходящим, если NULL должен быть разрешен как допустимое значение name.

    • Используйте ANY_VALUE() , чтобы обратиться к address:
      SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;
      

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

    • Выключите ONLY_FULL_GROUP_BY. Это эквивалентно использованию ANY_VALUE() с включенным ONLY_FULL_GROUP_BY, как описано в предыдущем элементе.

    ANY_VALUE() также полезна, если функциональная зависимость существует между столбцами, но MySQL не может определить это. Следующий запрос допустим потому, что age функционально зависит от группирующегося столбца age-1, но MySQL не может сказать это и отклоняет запрос при включении ONLY_FULL_GROUP_BY:

    SELECT age FROM t GROUP BY age-1;
    

    Чтобы заставить MySQL принимать запрос, надо использовать ANY_VALUE():

    SELECT ANY_VALUE(age) FROM t GROUP BY age-1;
    

    ANY_VALUE() может использоваться для запросов, которые обращаются к совокупным функциям в отсутствие предложения 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() говорит MySQL принимать запрос:

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

    Может случиться так, что из-за некоторого свойства набора определенных данных, Вы знаете, что выбранный несоединенный столбец эффективно функционально зависит от столбца в GROUP BY. Например, приложение может провести в жизнь уникальность одного столбца относительно другого. В этом случае использование ANY_VALUE() уву эффективно функционально зависимый столбец может иметь смысл.

  • BIN_TO_UUID( binary_uuid), BIN_TO_UUID( binary_uuid, swap_flag)

    BIN_TO_UUID() инверсия UUID_TO_BIN() . Это преобразовывает двоичный UUID в строку UUID и возвращает результат. Двоичное значение должно быть UUID как VARBINARY(16). Возвращаемое значение строка utf8 из пяти шестнадцатеричных чисел, разделенных тире. Для деталей об этом формате см. описание функции UUID(). Если параметр UUID NULL, возвращаемое значение NULL. Если какой-либо параметр недопустим, ошибка происходит.

    BIN_TO_UUID() берет один или два параметра:

    • Форма с одним параметром берет двоичное значение UUID. У значения UUID, как предполагается, части time-low и time-high не поменяны. Строковый результат находится в том же самом порядке, как двоичной параметр.

    • Форма с двумя параметрами берет двоичное значение UUID и значение флага:

      • Если swap_flag 0, форма с двумя параметрами эквивалентна форме с одним параметром. Строковый результат находится в том же самом порядке, как двоичной параметр.

      • Если swap_flag 1, у значения UUID, как предполагается, части time-low и time-high поменяны местами. Эти части переставляются назад к их оригинальной позиции в значении результата.

    Для примеров использования и информации о свопинге частей времени см. функциональное описание UUID_TO_BIN().

  • DEFAULT(col_name )

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

    mysql> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;
    
  • FORMAT(X, D)

    Форматирует число X в формат '#,###,###.##', округленный к D десятичных разрядов и возвращает результат как строку. Для деталей см. раздел 13.5.

  • GET_LOCK(str ,timeout)

    Пытается получить блокировку с именем, данным строкой str, с использованием тайм-аута timeout секунд. Отрицательное значение timeout означает бесконечный тайм-аут. Блокировка исключительна. В то время, как они проводится одним сеансом, другие сеансы не могут получить блокировку с тем же самым именем.

    Возвращает 1, если блокировка была получена успешно, 0, если попытка провалена по тайм-ауту (например, потому что другой клиент ранее заблокировал имя), или NULL, если ошибка произошла (такая как исчерпывание памяти, или поток был уничтожен с mysqladmin kill ).

    Блокировка, полученная с GET_LOCK() снята явно, выполняя RELEASE_LOCK() или неявно, когда Ваш сеанс заканчивается. Снятие блокировки может также произойти с другим вызовом GET_LOCK():

    • GET_LOCK() осуществлен, используя подсистему metadata locking (MDL). Многократные одновременные блокировки могут быть приобретены и GET_LOCK() не снимает существующих блокировок. Для данного сеанса даже возможно приобрести много блокировок с тем же самым именем. Другие сеансы не могут приобрести блокировку с этим именем, пока сеанс приобретения не снимает все свои блокировки для имени.

      Блокировки, приобретенные GET_LOCK() появятся в таблице Performance Schema metadata_locks. Столбец OBJECT_TYPE сообщает USER LEVEL LOCK и OBJECT_NAME имя блокировки. Кроме того, способность приобретения многократных блокировок вводит возможность тупика среди клиентов. Когда это происходит, сервер выбирает вызывающего и заканчивает его запрос приобретения блокировки с ошибкой ER_USER_LOCK_DEADLOCK. Эта ошибка не заставляет транзакции откатываться.

    Например, предположите, что Вы выполняете эти запросы:

    SELECT GET_LOCK('lock1',10);
    SELECT GET_LOCK('lock2',10);
    SELECT RELEASE_LOCK('lock2');
    SELECT RELEASE_LOCK('lock1');
    

    Второй GET_LOCK() приобретает вторую блокировку, и оба RELEASE_LOCK() вернут 1 (успех).

    MySQL ограничивает максимальную длину названий блокировки 64 символами.

    Блокировки, полученные с GET_LOCK() не сняты, когда транзакции закрываются или откатываются.

    GET_LOCK() может использоваться, чтобы осуществить блокировки приложения или моделировать блокировки записи. Имена заблокированы на основе всего сервера. Если имя было заблокировано в пределах одного сеанса, GET_LOCK() блокирует любой запрос другого сеанса для блокировки с тем же самым именем. Это позволяет клиентам, которые договариваются о данном имени блокировки, использовать имя, чтобы выполнить совместную консультативную блокировку. Но знайте, что это также позволяет клиенту, который не является членом группы сотрудничающих клиентов, заблокировать имя (неосторожно или сознательно) и таким образом препятствовать тому, чтобы любой из сотрудничающих клиентов блокировал это имя. Один способ уменьшить вероятность этого состоит в том, чтобы использовать имена блокировки, которые являются определенными для базы данных или приложения. Например, используйте названия блокировки формы db_name.str или app_name.str.

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

    GET_LOCK() опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format установлена в значение STATEMENT.

    Со способностью приобретения многоих именованных блокировок в MySQL 5.7.5 для единственного запроса возможно приобрести большое количество блокировок. Например:

    INSERT INTO ... SELECT GET_LOCK(t1.col_name) FROM t1;
    

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

    Различный интерфейс блокировки доступен как плагин или как ряд определяемых пользователем функций. Этот интерфейс обеспечивает пространства имен блокировки и разные блокировки чтения и записи, в отличие от интерфейса, обеспеченного GET_LOCK() и связанных функций. Для деталей см. раздел 26.3.1.

  • INET_ATON(expr )

    Учитывая представление сетевого адреса IPv4 как строки, возвращает целое число, которое представляет числовое значение адреса в сетевом порядке байтов (big endian). INET_ATON() вернет NULL, если это не понимает свой параметр.

    mysql> SELECT INET_ATON('10.0.5.9');
        -> 167773449
    

    INET_ATON() возвращает или, возможно, не возвращает не-NULL результат для кратких IP-адресов (таких, как '127.1' как представление '127.0.0.1'). Из-за этого INET_ATON() не должна использоваться для таких адресов.

    Чтобы сохранить значения, произведенные INET_ATON(), используйте столбец INT UNSIGNED, а не INT, который со знаком. Если Вы используете столбец со знаком, значения, соответствующие IP-адресам, для которых первый октет больше 127, не могут быть сохранены правильно. См. раздел 12.2.6.

  • INET_NTOA(expr )

    Учитывая числовой сетевой адрес IPv4 в сетевом порядке байтов, возвращает строковое представление адреса как недвоичную строку в наборе символов соединения. INET_NTOA() возвращает NULL, если это не понимает свой параметр.

    mysql> SELECT INET_NTOA(167773449);
        -> '10.0.5.9'
    
  • INET6_ATON(expr )

    Учитывая сетевой адрес IPv6 или IPv4 как строку, возвращает двоичную строку, которая представляет числовое значение адреса в сетевом порядке байтов (big endian). Поскольку адреса числового формата IPv6 требуют большего количества байтов чем самый большой тип целого числа, представление, возвращенное этой функцией, имеет тип данных VARBINARY: VARBINARY(16) для IPv6 и VARBINARY(4) для IPv4. Если параметр не допустимый адрес, INET6_ATON() вернет NULL.

    Следующее использование в качестве примера HEX() показывает результат INET6_ATON() в пригодной для печати форме:

    mysql> SELECT HEX(INET6_ATON('fdfe::5a55:caff:fefa:9089'));
        -> 'FDFE0000000000005A55CAFFFEFA9089'
    mysql> SELECT HEX(INET6_ATON('10.0.5.9'));
        -> '0A000509'
    

    INET6_ATON() имеет несколько ограничений на допустимые параметры. Они даны в следующем списке наряду с примерами.

    • Зональный ID не разрешен, как в fe80::3%1 или fe80::3%eth0.

    • Сетевая маска не разрешена, как в 2001:45f:3:ba::/64 или 192.168.1.0/24.
    • Для значений, представляющих адреса IPv4, поддержаны только бесклассовые адреса. Адреса наподобие 192.168.1 отклонены. Номер порта не разрешен, как в 192.168.1.2:8080. Шестнадцатеричные числа в компонентах адреса не разрешены, как в 192.0xa0.1.2. Восьмеричные числа не поддержаны: 192.168.010.1 обработан как 192.168.10.1, а не 192.168.8.1. Эти ограничения IPv4 также относятся к адресам IPv6, у которых есть части адреса IPv4, такие как IPv4-совместимые или IPv4-отображенные адреса.

    Чтобы преобразовать адрес IPv4 expr представленный в числовой форме как значение INT в адрес IPv6, представленный в числовой форме как значение VARBINARY, используйте это выражение:

    INET6_ATON(INET_NTOA(expr))
    

    Например:

    mysql> SELECT HEX(INET6_ATON(INET_NTOA(167773449)));
        -> '0A000509'
    
  • INET6_NTOA(expr )

    Учитывая IPv6 или сетевой адрес IPv4, представленный в числовой форме как двоичная строка, возвращает строковое представление адреса как недвоичная строка в наборе символов соединения. Если параметр не допустимый адрес, INET6_NTOA() вернет NULL.

    INET6_NTOA() имеет эти свойства:

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

    • У строки возврата есть максимальная длина 39 (4 x 8 + 7). Учитывая это, запрос:
      CREATE TABLE t AS SELECT INET6_NTOA(expr) AS c1;
      

      У получающейся таблицы было бы это определение:

      CREATE TABLE t (c1 VARCHAR(39) CHARACTER SET utf8 DEFAULT NULL);
      
    • Строка возврата использует строчные буквы для адресов IPv6.

    mysql> SELECT INET6_NTOA(INET6_ATON('fdfe::5a55:caff:fefa:9089'));
        -> 'fdfe::5a55:caff:fefa:9089'
    mysql> SELECT INET6_NTOA(INET6_ATON('10.0.5.9'));
        -> '10.0.5.9'
    mysql> SELECT INET6_NTOA(UNHEX('FDFE0000000000005A55CAFFFEFA9089'));
        -> 'fdfe::5a55:caff:fefa:9089'
    mysql> SELECT INET6_NTOA(UNHEX('0A000509'));
        -> '10.0.5.9'
    
  • IS_FREE_LOCK(str )

    Проверяет, можно ли блокировку str свободно использовать (то есть, не заблокирована ли она). Возвращает 1, если блокировка свободна (никто не использует блокировку), 0, если блокировка используется, и NULL, если ошибка происходит (такая, как неправильный параметр).

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

  • IS_IPV4(expr )

    Возвращает 1, если параметр допустимый адрес IPv4, определенный как строка, 0 иначе.

    mysql> SELECT IS_IPV4('10.0.5.9'), IS_IPV4('10.0.5.256');
        -> 1, 0
    

    Для данного параметра, если IS_IPV4() вернет 1, INET_ATON()INET6_ATON()) возвратят не NULL. Обратное заявление не истина: в некоторых случаях INET_ATON() возвращает не NULL, когда IS_IPV4() возвращает 0.

    Как подразумевается предыдущими замечаниями, IS_IPV4() более строго, чем INET_ATON() составляет допустимый адрес IPv4, таким образом, это может быть полезно для приложений, которые должны выполнить сильные проверки от недопустимых значений. Альтернативно, можно использовать INET6_ATON(), чтобы преобразовать IPv4 к внутренней форме и проверить на NULL (который указывает на недопустимый адрес). INET6_ATON() одинаково сильно как IS_IPV4() в проверке адресов IPv4.

  • IS_IPV4_COMPAT( expr)

    Эта функция берет адрес IPv6, представленный в числовой форме как двоичная строка, как возвращено INET6_ATON(). Это возвращает 1, если параметр допустимый IPv4-совместимый адрес IPv6, 0 иначе. У IPv4-совместимых адресов есть форма ::ipv4_address.

    mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::10.0.5.9'));
      -> 1
    mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::ffff:10.0.5.9'));
      -> 0
    

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

    mysql> SELECT HEX(INET6_ATON('192.168.0.1'));
        -> 'C0A80001'
    

    Выраженный в IPv4-совместимой форме ::192.168.0.1 эквивалент ::c0a8:0001 или (без начальных нулей) ::c0a8:1.

    mysql> SELECT
        ->   IS_IPV4_COMPAT(INET6_ATON('::192.168.0.1')),
        ->   IS_IPV4_COMPAT(INET6_ATON('::c0a8:0001')),
        ->   IS_IPV4_COMPAT(INET6_ATON('::c0a8:1'));
        -> 1, 1, 1
    
  • IS_IPV4_MAPPED( expr)

    Эта функция берет адрес IPv6, представленный в числовой форме как двоичная строка, как возвращено INET6_ATON(). Это возвращает 1, если параметр допустимый IPv4-отображенный адрес IPv6, 0 иначе. У IPv4-отображенных адресов есть форма ::ffff:ipv4_address.

    mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::10.0.5.9'));
      -> 0
    mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:10.0.5.9'));
      -> 1
    

    Как с IS_IPV4_COMPAT() часть IPv4 IPv4-отображенного адреса может также быть представлена, используя шестнадцатеричную нотацию:

    mysql> SELECT
        ->   IS_IPV4_MAPPED(INET6_ATON('::ffff:192.168.0.1')),
        ->   IS_IPV4_MAPPED(INET6_ATON('::ffff:c0a8:0001')),
        ->   IS_IPV4_MAPPED(INET6_ATON('::ffff:c0a8:1'));
        -> 1, 1, 1
    
  • IS_IPV6(expr )

    Возвращает 1, если параметр допустимый адрес IPv6, определенный как строка, 0 иначе. Эта функция не полагает, что адреса IPv4 допустимые адреса IPv6.

    mysql> SELECT IS_IPV6('10.0.5.9'), IS_IPV6('::1');
        -> 0, 1
    

    Для данного параметра если IS_IPV6() вернет 1, INET6_ATON() вернет не NULL.

  • IS_USED_LOCK(str )

    Проверяет, используется ли блокировка str (то есть, заблокирована). Если так, это возвращает идентификатор соединения сеанса клиента, который держит блокировку. Иначе это возвращает NULL.

    Эта функция опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format установлена в STATEMENT.

  • IS_UUID(string_uuid )

    Возвращает 1, если параметр допустимый строковый формат UUID, 0, если параметр не допустимый UUID, и NULL, если параметр NULL.

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

    aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
    

    Эти форматы также разрешены:

    aaaaaaaabbbbccccddddeeeeeeeeeeee
    {aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee}
    

    Для значений полей в пределах значения см. функциональное описание UUID().

    mysql> SELECT IS_UUID('6ccd780c-baba-1026-9564-0040f4311e29');
    +-------------------------------------------------+
    | IS_UUID('6ccd780c-baba-1026-9564-0040f4311e29') |
    +-------------------------------------------------+
    | 1                                               |
    +-------------------------------------------------+
    
    mysql> SELECT IS_UUID('6CCD780C-BABA-1026-9564-0040F4311E29');
    +-------------------------------------------------+
    | IS_UUID('6CCD780C-BABA-1026-9564-0040F4311E29') |
    +-------------------------------------------------+
    | 1                                               |
    +-------------------------------------------------+
    
    mysql> SELECT IS_UUID('6ccd780cbaba102695640040f4311e29');
    +---------------------------------------------+
    | IS_UUID('6ccd780cbaba102695640040f4311e29') |
    +---------------------------------------------+
    | 1                                           |
    +---------------------------------------------+
    
    mysql> SELECT IS_UUID('{6ccd780c-baba-1026-9564-0040f4311e29}');
    +---------------------------------------------------+
    | IS_UUID('{6ccd780c-baba-1026-9564-0040f4311e29}') |
    +---------------------------------------------------+
    | 1                                                 |
    +---------------------------------------------------+
    
    mysql> SELECT IS_UUID('6ccd780c-baba-1026-9564-0040f4311e2');
    +------------------------------------------------+
    | IS_UUID('6ccd780c-baba-1026-9564-0040f4311e2') |
    +------------------------------------------------+
    | 0                                              |
    +------------------------------------------------+
    
    mysql> SELECT IS_UUID(RAND());
    +-----------------+
    | IS_UUID(RAND()) |
    +-----------------+
    | 0               |
    +-----------------+
    
  • MASTER_POS_WAIT( log_name,log_pos[,timeout ][,channel_name])

    Эта функция полезна для управления синхронизацией основной/ведомый. Это блокирует, пока ведомое устройство не считает и применит все обновления до указанной позиции в основном журнале. Возвращаемое значение число событий журнала, которые должно было ждать ведомое устройство до указанной позиции. Функция возвращает NULL, если ведомый поток SQL не запущен, основная информация ведомого устройства не инициализирована, параметры неправильные или ошибка происходит. Это возвращается -1, если тайм-аут был превышен. Если ведомые потоки SQL стоят в то время, как MASTER_POS_WAIT() ждет, функция возвращает NULL. Если ведомое устройство проходит указанную позицию, функция немедленно возвращается.

    Если значение timeout определено, MASTER_POS_WAIT() ожидает timeout секунд. Здесь timeout должно быть больше 0: ноль или отрицательный timeout означает отсутствие тайм-аута.

    Дополнительный параметр channel позволяет Вам выбрать, какой канал репликации применяется в функции. См. подробности в разделе 19.2.3.

    Эта функция опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format находится в значении STATEMENT.

  • NAME_CONST(name ,value)

    Возвращает данное значение. Когда используется, чтобы произвести столбец набора результатов, NAME_CONST() заставляет столбец иметь имя. Параметры должны быть константами.

    mysql> SELECT NAME_CONST('myname', 14);
    +--------+
    | myname |
    +--------+
    | 14     |
    +--------+
    

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

    Для Ваших приложений Вы можете получить точно тот же самый результат как в примере при использовании простого совмещения имен:

    mysql> SELECT 14 AS myname;
    +--------+
    | myname |
    +--------+
    | 14     |
    +--------+
    1 row in set (0.00 sec)
    
  • RELEASE_ALL_LOCKS()

    Снимает все названные блокировки, проводимые текущим сеансом и возвращает число блокировок (0, если не было ни одной).

    Эта функция опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format в состоянии STATEMENT.

  • RELEASE_LOCK(str )

    Снимает все блокировки, названные str. Возвращает 1, если блокировка была выпущена, 0, если блокировка не была установлена этим потоком (тогда блокировка не снята) и NULL, если названная блокировка не существовала. Блокировка не существует, если она никогда не получалась вызовом GET_LOCK() или если она была ранее снята.

    Запрос DO удобно использовать с RELEASE_LOCK(). См. раздел 14.2.3.

    Эта функция опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format в состоянии STATEMENT.

  • SLEEP(duration )

    Ждет число секунд, данное параметром duration, и затем возвращает 0. У продолжительности может быть дробная часть. Если параметр NULL или отрицательный, SLEEP() производит предупреждение, или ошибку в строгом режиме SQL.

    Когда функция завершает нормально (без прерывания), это возвращает 0:

    mysql> SELECT SLEEP(1000);
    +-------------+
    | SLEEP(1000) |
    +-------------+
    | 0           |
    +-------------+
    

    Когда SLEEP() единственная вещь, вызванная запросом, который прерван, она возвращает 1, а сам запрос не возвращает ошибки. Это истина, уничтожен ли запрос, или произошел тайм-аут:

    • Этот запрос прерван, используя KILL QUERY другого сеанса:

      mysql> SELECT SLEEP(1000);
      +-------------+
      | SLEEP(1000) |
      +-------------+
      | 1           |
      +-------------+
      
    • Этот запрос прерван по тайм-ауту:
      mysql> SELECT /*+ MAX_EXECUTION_TIME(1) */ SLEEP(1000);
      +-------------+
      | SLEEP(1000) |
      +-------------+
      | 1           |
      +-------------+
      

    Когда SLEEP() только часть запроса, который прерван, этот запрос возвращает ошибку:

    • Этот запрос прерван, используя KILL QUERY другого сеанса:

      mysql> SELECT 1 FROM t1 WHERE SLEEP(1000);
      ERROR 1317 (70100): Query execution was interrupted
      
    • Этот запрос прерван по тайм-ауту:
      mysql> SELECT /*+ MAX_EXECUTION_TIME(1000) */ 1 FROM t1 WHERE SLEEP(1000);
      ERROR 3024 (HY000): Query execution was interrupted, maximum statement
      execution time exceeded
      

    Эта функция опасна для основанной на запросе репликации. Предупреждение зарегистрировано, если Вы используете эту функцию, когда binlog_format в состоянии STATEMENT.

  • UUID()

    Возвращает универсальный уникальный идентификатор (UUID), произведенный согласно RFC 4122, A Universally Unique IDentifier (UUID) URN Namespace ( http://www.ietf.org/rfc/rfc4122.txt).

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

    Хотя значения UUID() предназначены, чтобы быть уникальными, они являются не обязательно непредсказуемыми. Если непредсказуемость требуется, значения UUID должны быть произведены другим путем.

    UUID() возвращает значение, которое соответствует версии 1 UUID как описано в RFC 4122. Значение 128-битное число, представленное как строка utf8 из пяти шестнадцатеричных чисел в формате aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:

    • Первые три числа произведены из нижней, средней и верхней частей timestamp. Верхняя часть также включает номер версии UUID.

    • Четвертое число сохраняет временную уникальность в случае, если значение timestamp теряет монотонность (например, из-за летнего времени).
    • Пятое число номер узла в IEEE 802, который обеспечивает пространственную уникальность. Случайным числом заменяют, если значение не доступно (например, потому что у устройства узла нет никакой карты Ethernet, или неизвестно, как найти адрес аппаратных средств интерфейса в операционной системе узла). В этом случае, пространственная уникальность не может быть гарантирована. Однако, у столкновения должна быть очень низкая вероятность.

      MAC-адрес интерфейса принят во внимание только в FreeBSD и Linux. В других операционных системах MySQL использует беспорядочно произведенное 48-битное число.

    mysql> SELECT UUID();
        -> '6ccd780c-baba-1026-9564-0040f4311e29'
    

    Чтобы преобразовать между строкой и двоичным значением UUID, используйте функции UUID_TO_BIN() и BIN_TO_UUID() . Чтобы проверить, является ли строка допустимым значением UUID, используйте функцию IS_UUID() .

    UUID() не работает с основанной на запросах репликацией.

  • UUID_SHORT()

    Возвращает короткий универсальный идентификатор как 64-битное целое число без знака. Значения, возвращенные UUID_SHORT() отличаются от строкового формата 128-битных идентификаторов, возвращенных функцией UUID() и имеют различные свойства уникальности. Значение UUID_SHORT() как гарантируют, будет уникально, если следующие условия будут выполнены:

    • Значение server_id текущего сервера между 0 и 255 и уникально среди Вашей группы основных и ведомых серверов.

    • Вы не задерживаете системное время для своего узла сервера между перезапусками mysqld .
    • Вы вызываете UUID_SHORT() в среднем меньше, чем 16 миллионов раз в секунду между перезапусками mysqld .

    Возвращаемое значение UUID_SHORT() создано этим путем:

      (server_id & 255) << 56
    + (server_startup_time_in_seconds << 24)
    + incremented_variable++;
    
    mysql> SELECT UUID_SHORT();
        -> 92395783831158784
    

    UUID_SHORT() не работает с основанной на запросе репликацией.

  • UUID_TO_BIN( string_uuid), UUID_TO_BIN( string_uuid, swap_flag)

    Преобразовывает строку UUID в двоичный UUID и возвращает результат. Описание IS_UUID() перечисляет разрешенные строковые форматы UUID. Возвращаемое значение UUID имеет тип VARBINARY(16). Если параметр UUID NULL, возвращаемое значение NULL. Если какой-либо параметр недопустим, происходит ошибка.

    UUID_TO_BIN() берет один или два параметра:

    • Форма с одним параметром берет строку значения UUID. Двоичный результат находится в том же самом порядке как строковый параметр.

    • Форма с двумя параметрами берет строку значения UUID и значение флага:

      • Если swap_flag 0, форма с двумя параметрами эквивалентна форме с одним параметром. Двоичный результат находится в том же самом порядке как строковый параметр.

      • Если swap_flag 1, формат возвращаемого значения отличается: части времени (первые и третьи группы шестнадцатеричных цифр, соответственно) переставлены. Это перемещает переменную часть направо и может улучшить эффективность индексации, если результат сохранен в индексированном столбце.

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

    Предположите, что у Вас есть следующая строка значение UUID:

    mysql> SET @uuid = '6ccd780c-baba-1026-9564-0040f4311e29';
    

    Чтобы преобразовать строку UUID в двоичный вид с или без свопинга части времени, надо использовать UUID_TO_BIN():

    mysql> SELECT HEX(UUID_TO_BIN(@uuid));
    +----------------------------------+
    | HEX(UUID_TO_BIN(@uuid))          |
    +----------------------------------+
    | 6CCD780CBABA102695640040F4311E29 |
    +----------------------------------+
    
    mysql> SELECT HEX(UUID_TO_BIN(@uuid, 0));
    +----------------------------------+
    | HEX(UUID_TO_BIN(@uuid, 0))       |
    +----------------------------------+
    | 6CCD780CBABA102695640040F4311E29 |
    +----------------------------------+
    
    mysql> SELECT HEX(UUID_TO_BIN(@uuid, 1));
    +----------------------------------+
    | HEX(UUID_TO_BIN(@uuid, 1))       |
    +----------------------------------+
    | 1026BABA6CCD780C95640040F4311E29 |
    +----------------------------------+
    

    Преобразовать двоичной UUID, возвращенный UUID_TO_BIN() в строку UUID можно через BIN_TO_UUID(). Если Вы производите двоичный UUID, вызывая UUID_TO_BIN() со вторым параметром 1, чтобы поменять части времени, Вы должны также передать второй параметр 1 в BIN_TO_UUID() для обратной перестановки частей времени, преобразовывая двоичной UUID назад в строку UUID:

    mysql> SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid));
    +--------------------------------------+
    | BIN_TO_UUID(UUID_TO_BIN(@uuid))|
    +--------------------------------------+
    | 6ccd780c-baba-1026-9564-0040f4311e29 |
    +--------------------------------------+
    
    mysql> SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,0),0);
    +--------------------------------------+
    | BIN_TO_UUID(UUID_TO_BIN(@uuid,0),0)  |
    +--------------------------------------+
    | 6ccd780c-baba-1026-9564-0040f4311e29 |
    +--------------------------------------+
    
    mysql> SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,1),1);
    +--------------------------------------+
    | BIN_TO_UUID(UUID_TO_BIN(@uuid,1),1)  |
    +--------------------------------------+
    | 6ccd780c-baba-1026-9564-0040f4311e29 |
    +--------------------------------------+
    

    Если использование свопинга части времени не будет тем же самым для преобразования в обоих направлениях, то оригинальный UUID не будет восстановлен должным образом:

    mysql> SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,0),1);
    +--------------------------------------+
    | BIN_TO_UUID(UUID_TO_BIN(@uuid,0),1)  |
    +--------------------------------------+
    | baba1026-780c-6ccd-9564-0040f4311e29 |
    +--------------------------------------+
    
    mysql> SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,1),0);
    +--------------------------------------+
    | BIN_TO_UUID(UUID_TO_BIN(@uuid,1),0)  |
    +--------------------------------------+
    | 1026baba-6ccd-780c-9564-0040f4311e29 |
    +--------------------------------------+
    
  • VALUES(col_name )

    В запросе INSERT ... ON DUPLICATE KEY UPDATE Вы можете использовать функцию VALUES(col_name) в предложении UPDATE, чтобы обратиться к значениям столбцов из INSERT. Другими словами, VALUES(col_name) в UPDATE относится к значению col_name, которое было бы вставлено, не имея никакого конфликта дублирования ключа. Эта функция особенно полезна при вставке многих строк. Функция VALUES() является значащей только в предложении ON DUPLICATE KEY UPDATE в запросе INSERT, иначе вернет NULL. См. раздел 14.2.5.3.

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
        ->        ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
    

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 и усечение могло бы произойти.

  • AVG([DISTINCT] expr)

    Возвращает среднее значение expr. Опция DISTINCT может использоваться, чтобы возвратить среднее число отличных значений expr.

    AVG() возвращает NULL, если не было никаких строк соответствия.

    mysql> SELECT student_name, AVG(test_score)
        ->   FROM student
        ->   GROUP BY student_name;
    
  • BIT_AND(expr )

    Возвращает поразрядное AND из всех битов в expr. Вычисление выполнено с 64-битной точностью (BIGINT).

    BIT_AND() вернет 18446744073709551615, если не было никаких строк соответствия. Это значение unsigned BIGINT со всеми битами, установленными в 1.

  • BIT_OR(expr)

    Возвращает поразрядное OR из всех битов в expr. Вычисление выполнено с 64-битной точностью (BIGINT).

    BIT_OR() возвращает 0, если не было никаких строк соответствия.

  • BIT_XOR(expr )

    Возвращает поразрядное XOR всех битов в expr. Вычисление выполнено с 64-битной точностью (BIGINT).

    BIT_XOR() возвращает 0, если не было никаких строк соответствия.

  • COUNT(expr)

    Возвращает количество не-NULL значений expr в строках, полученных SELECT. Результат значение типа BIGINT.

    COUNT() возвращает 0, если не было никаких строк соответствия.

    mysql> SELECT student.student_name,COUNT(*)
        ->   FROM student,course
        ->   WHERE student.student_id=course.student_id GROUP BY student_name;
    

    COUNT(*) несколько отличается в том, что это возвращает количество полученных строк, не учитывая, содержат ли они значения NULL.

    COUNT(*) оптимизирована, чтобы возвратить очень быстро, если SELECT получает данные от одной таблицы, никакие другие столбцы не получены и нет предложения WHERE. Например:

    mysql> SELECT COUNT(*) FROM student;
    

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

  • COUNT(DISTINCT expr,[expr...])

    Возвращает количество строк с различными значениями не-NULL expr.

    COUNT(DISTINCT) возвращает 0, если не было никаких строк соответствия.

    mysql> SELECT COUNT(DISTINCT results) FROM student;
    

    В MySQL Вы можете получить число отличных комбинаций выражения, которые не содержат NULL, давая список выражений. В стандартном SQL Вы должны были бы сделать связь всех выражений внутри COUNT(DISTINCT ...).

  • GROUP_CONCAT(expr )

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

    GROUP_CONCAT([DISTINCT] expr [,expr ...]
       [ORDER BY {unsigned_integer | col_name | expr}
       [ASC | DESC] [,col_name ...]]
       [SEPARATOR str_val])
    
    mysql> SELECT student_name, GROUP_CONCAT(test_score)
        ->        FROM student
        ->        GROUP BY student_name;
    

    Или:

    mysql> SELECT student_name, GROUP_CONCAT(DISTINCT test_score
        ->        ORDER BY test_score DESC SEPARATOR ' ')
        ->        FROM student GROUP BY student_name;
    

    В MySQL Вы можете получить связанные значения комбинаций выражения. Чтобы устранить дублирующие значения, используйте DISTINCT. Чтобы отсортировать значения в результате, используйте ORDER BY. Чтобы отсортировать в обратном порядке, добавьте ключевое слово DESC к названию столбца, который Вы сортируете в ORDER BY. Значение по умолчанию порядок по возрастанию, это может быть определено явно, используя ключевое слово ASC. Разделитель по умолчанию между значениями в группе запятая (,). Чтобы определить разделитель явно, надо использовать SEPARATOR сопровождаемое строковым значением, которое должно быть вставлено между групповыми значениями. Чтобы устранить разделитель вообще, определите SEPARATOR ''.

    Результат является усеченным к максимальной длине, которая дана переменной group_concat_max_len , у которой есть значение по умолчанию 1024. Значение может быть установлено выше, хотя эффективная максимальная длина возвращаемого значения ограничена значением max_allowed_packet . Синтаксис, чтобы изменить значение group_concat_max_len во время выполнения, где val unsigned integer:

    SET [GLOBAL | SESSION] group_concat_max_len = val;
    

    Возвращаемое значение недвоичная или двоичная строка, в зависимости от того, являются ли параметрами недвоичные или двоичные строки. Тип результата TEXT или BLOB. Если group_concat_max_len меньше или равно 512, тогда тип результата VARCHAR или VARBINARY.

  • JSON_ARRAYAGG([ col)

    Соединяет набор результатов как массив JSON, чьи элементы состоят из строк. Порядок элементов в этом массиве неопределен. Функция действует на столбец или выражение, которое оценивается к единственному значению. Возвращает NULL, если результат не содержит строк, или в случае ошибки.

    Эта функция была добавлена в MySQL 8.0.1.

    mysql> SELECT col FROM t1;
    +--------------------------------------+
    | col                                  |
    +--------------------------------------+
    | {"key1": "value1", "key2": "value2"} |
    | {"keyA": "valueA", "keyB": "valueB"} |
    +--------------------------------------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT JSON_ARRAYAGG(col) FROM t1;
    +------------------------------------------------------------------------------+
    | JSON_ARRAYAGG(col)                                                           |
    +------------------------------------------------------------------------------+
    | [{"key1": "value1", "key2": "value2"}, {"keyA": "valueA", "keyB": "valueB"}] |
    +------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
  • JSON_OBJECTAGG([ key, value)

    Берет два имени столбцов или выражения как параметры, первый из них используется в качестве ключа, второй как значение, и возвращает объект JSON, содержащий пары ключа/значения. Элементы с дубликатами ключей пропущены. Вы можете определить константу как ключ, но результат всегда содержит самое большее один элемент строки. Возвращает NULL, если результат не содержит строк, или в случае ошибки. Ошибка происходит, если какое-либо ключевое имя NULL или число параметров не равно 2.

    Эта функция была добавлена в MySQL 8.0.1.

    mysql> SELECT id, name FROM t3 WHERE id < 10;
    +----+------+
    | id | name |
    +----+------+
    |2   | joe  |
    |5   | fred |
    +----+------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT JSON_OBJECTAGG(id, name) FROM t3 WHERE id < 10;
    +---------------------------+
    | JSON_OBJECTAGG(id, name)  |
    +---------------------------+
    | {"2": "joe", "5": "fred"} |
    +---------------------------+
    1 row in set (0.00 sec)
    
  • MAX([DISTINCT] expr)

    Возвращает максимальное значение expr. MAX() может взять строковый параметр, в таких случаях это возвращает максимальное строковое значение. См. раздел 9.3.1. Ключевое слово DISTINCT может использоваться, чтобы найти максимум отличных значений expr, однако, это приводит к тому же самому результату, как и исключение DISTINCT.

    MAX() возвращает NULL, если не было никаких строк соответствия.

    mysql> SELECT student_name, MIN(test_score), MAX(test_score)
        ->        FROM student
        ->        GROUP BY student_name;
    

    Для MAX() MySQL в настоящее время сравнивает столбцы ENUM и SET их строковым значением, а не относительной позицией строки в наборе. Это отличается от сравнения ORDER BY. Это, как ожидают, будет исправлено в будущем выпуске MySQL.

  • MIN([DISTINCT] expr)

    Возвращает минимальное значение expr. MIN() может взять строковый параметр, в таких случаях это возвращает минимальное строковое значение. См. раздел 9.3.1. Ключевое слово DISTINCT может использоваться, чтобы найти минимум отличных значений expr, однако, это приводит к тому же самому результату, как и исключение DISTINCT.

    MIN() возвращает NULL, если не было никаких строк соответствия.

    mysql> SELECT student_name, MIN(test_score), MAX(test_score)
        ->        FROM student
        ->        GROUP BY student_name;
    

    Для MIN() MySQL в настоящее время сравнивает столбцы ENUM и SET их строковым значением, а не относительной позицией строки в наборе. Это отличается от сравнения ORDER BY. Это, как ожидают, будет исправлено в будущем выпуске MySQL.

  • STD(expr)

    Возвращает стандартное отклонение expr. Это расширение к стандартному SQL. Стандартная функция SQL STDDEV_POP() может использоваться вместо этого.

    STD() возвращает NULL, если не было никаких строк соответствия.

  • STDDEV(expr)

    Возвращает стандартное отклонение expr. Эта функция обеспечена для совместимости с Oracle. Стандартная функция SQL STDDEV_POP() может использоваться вместо этого.

    STDDEV() возвращает NULL, если не было никаких строк соответствия.

  • STDDEV_POP(expr )

    Возвращает стандартное отклонение expr (квадратный корень VAR_POP() ). Вы можете также использовать STD() или STDDEV(), которые эквивалентны, но не стандартный SQL.

    STDDEV_POP() возвращает NULL, если не было никаких строк соответствия.

  • STDDEV_SAMP(expr )

    Возвращает типовое стандартное отклонение expr (квадратный корень VAR_SAMP() ).

    STDDEV_SAMP() возвращает NULL, если не было никаких строк соответствия.

  • SUM([DISTINCT] expr)

    Возвращает сумму expr. Если у набора нет никаких строк, SUM() возвращает NULL. Ключевое слово DISTINCT может использоваться, чтобы суммировать только отличные значения expr.

    SUM() возвращает NULL, если не было никаких строк соответствия.

  • VAR_POP(expr )

    Возвращает различие стандарта expr. Это рассматривает строки как целое, не как образец, таким образом, у этого есть число строк как знаменатель. Вы можете также использовать VARIANCE(), который эквивалентен, но не является стандартом SQL.

    VAR_POP() возвращает NULL, если не было никаких строк соответствия.

  • VAR_SAMP(expr )

    Возвращает типовое различие expr. Таким образом, знаменатель число строк минус одна.

    VAR_SAMP() возвращает NULL, если не было никаких строк соответствия.

  • VARIANCE(expr )

    Возвращает различие стандарта expr. Это расширение к стандартному SQL. Стандартная функция SQL VAR_POP() может использоваться вместо этого.

    VARIANCE() возвращает NULL, если не было никаких строк соответствия.

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:

  • После каждого набора строк product для данных year и country дополнительная сводная строка произведена, показывая общее количество для всех product. Эти строки имеют столбец product установленный в NULL.

  • После каждого набора строк в течение данного year дополнительная сводная строка произведена, показывая общее количество для всех country и product. Эти строки имеют столбцы country и products установленные в NULL.
  • Наконец, после всех других строк, дополнительная сводная строка произведена, показывая общий итог для всех year, country и products. Эта строка имеет столбцы year, country и products установленные в NULL.

Другие соображения, используя 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 не удовлетворяет по крайней мере одно из этих условий:

  • Выражение равно одному в списке select.

  • Все столбцы, на которые ссылается выражение и принадлежащий выбранным таблицам запроса, являются элементами списка select.

Другое расширение 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:

  • Точные вычисления: Для чисел точного значения вычисления не вводят ошибки с плавающей запятой. Вместо этого используется высокая точность. Например, MySQL обрабатывает такое число, как .0001 как точное значение, а не как приближение, и суммирование его 10000 раз приводит к результату точно 1, а не значению, которое является просто близким к 1.

  • Четкое поведение округления: Для чисел точного значения результат ROUND() зависит от параметра, а не от таких факторов окружающей среды, как основная библиотека C.
  • Независимость от платформы: Операции на точных числовых значениях те же самое на различных платформах, таких как Windows и Unix.
  • Управление обработкой недопустимых значений : Переполнение и деление на ноль обнаруживаемы и могут быть обработаны как ошибки. Например, Вы можете обработать значение, которое является слишком большим для столбца, как ошибку вместо того, чтобы иметь значение, усеченное до пределов диапазона типа данных столбца. Точно так же Вы можете обработать деление на ноль как ошибку, а не как работу, которая приводит к результату NULL. Многое определено установкой режима 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 (и его синонимов) с особым отношением к следующим темам:

  • Максимальное количество цифр.

  • Формат хранения.
  • Требования хранения.
  • Нестандартное расширение MySQL верхнего диапазона столбцов DECIMAL.

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

  • M максимальное количество цифр (точность). У этого есть диапазон от 1 до 65.

  • D число цифр направо от десятичной запятой (масштаб). Это имеет диапазон от 0 до 30 и должно быть не больше M.

Максимальное значение 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 допустимо.

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

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

  • Если никаких приблизительных значений нет, выражение содержит только точные значения. Если какое-либо точное значение содержит дробную часть (значение после десятичной запятой), выражение оценено, используя DECIMAL у точной арифметики и имеет точность 65 цифр. Например, 1.0/3.0 может быть приближен в десятичной записи как .333..., но не пишется как точное число, таким образом, (1.0/3.0)*3.0 не оценивается точно как 1.0.
  • Иначе выражение содержит только целочисленные значения. Выражение точно и оценено, используя арифметику целого числа и имеет точность BIGINT (64 бита).

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

Вставки в числовые столбцы, затронуты режимом 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 обрабатывает деление на ноль по-другому:

  • Если строгий режим не включен, происходит предупреждение.

  • Если строгий режим включен, insert и update, вызвавшие такую ситуацию, запрещены, и происходит ошибка.

Другими словами, вставки и обновления, вовлекающие выражения, которые вызывают деление на ноль могут быть обработаны как ошибки, но это требует 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() округляет по-разному в зависимости от того, точен ли параметр или приблизителен:

  • Для чисел точного значения ROUND() использует правило округления половины вверх: значение с дробной частью .5 или больше округлено вверх к следующему целому числу, если положительное или вниз к следующему целому числу, если отрицательное. Значение с дробной частью меньше, чем .5 округлены в меньшую сторону к следующему целому числу в соответствующую сторону.

  • Для чисел приблизительной точности результат зависит от библиотеки C. На многих системах это означает, что 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, это означает, что результаты последовательны, независмо от платформы.

  • Округление для точных столбцов значений (DECIMAL и целые числа) использует правило округления половины вверх. Значения с дробной частью .5 или больше округлены до самого близкого целого числа в сторону от нуля, как показано здесь:

    mysql> SELECT ROUND(2.5), ROUND(-2.5);
    +------------+-------------+
    | ROUND(2.5) | ROUND(-2.5) |
    +------------+-------------+
    | 3          | -3          |
    +------------+-------------+
    
  • Округление для значений с плавающей запятой пользуется библиотекой C, которая на многих системах использует другую логику. Значения с любой дробной частью на таких системах округлены к самому близкому числу:
    mysql> SELECT ROUND(2.5E0), ROUND(-2.5E0);
    +--------------+---------------+
    | ROUND(2.5E0) | ROUND(-2.5E0) |
    +--------------+---------------+
    |  2           |  -2           |
    +--------------+---------------+
    

Пример 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    |       |
+--------+---------------+------+-----+---------+-------+

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru