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

Глава 12. Типы данных

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

Описания типа данных используют эти соглашения:

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

  • D относится к числам с плавающей запятой и фиксированной точкой и указывает на число цифр после десятичной запятой (масштаб). Максимальное возможное значение 30, но должно быть не больше M-2.
  • fsp относится к типам TIME, DATETIME и TIMESTAMP и представляет дробную точность секунд, то есть, число цифр после десятичной запятой для дробных частей секунд. Значение fsp, если есть, должно быть в диапазоне от 0 до 6. Значение 0 показывает, что нет никакой дробной части. Если опущено, точность по умолчанию 0. Это отличается от стандартного значения по умолчанию SQL 6 для совместимости с предыдущими версиями MySQL.
  • Квадратные скобки ([ и ]) указывают на дополнительные части определений типа.

12.1. Краткий обзор типов данных

12.1.1. Краткий обзор числовых типов

Для дополнительной информации о свойствах и требованиях хранения числовых типов см. разделы 12.2 и 12.8.

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

Если Вы определяете ZEROFILL для числового столбца, MySQL автоматически добавляет UNSIGNED столбцу.

Типы числовых данных, которые разрешают UNSIGNED, также разрешают SIGNED. Однако, эти типы данных со знаком по умолчанию, таким образом, SIGNED не имеет никакого эффекта.

SERIAL означает BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.

SERIAL DEFAULT VALUE в определении целого числа столбец псевдоним для NOT NULL AUTO_INCREMENT UNIQUE.

Когда Вы используете вычитание между целочисленными значениями, где каждое число имеет тип UNSIGNED, результат со знаком, если включен режим SQL NO_UNSIGNED_SUBTRACTION. См. раздел 13.10.

  • BIT[(M)]

    Тип битового значения. M указывает на число битов на значение, от 1 до 64. Значение по умолчанию 1, если M пропущен.

  • TINYINT[(M )] [UNSIGNED] [ZEROFILL]

    Очень маленькое целое число. Диапазон со знаком от -128 до 127. Диапазон без знака от 0 до 255.

  • BOOL, BOOLEAN

    Эти типы синонимы для TINYINT(1). Значение ноля считают ложным. Ненулевые значения считают истиной:

    mysql> SELECT IF(0, 'true', 'false');
    +------------------------+
    | IF(0, 'true', 'false') |
    +------------------------+
    | false                  |
    +------------------------+
    
    mysql> SELECT IF(1, 'true', 'false');
    +------------------------+
    | IF(1, 'true', 'false') |
    +------------------------+
    | true                   |
    +------------------------+
    
    mysql> SELECT IF(2, 'true', 'false');
    +------------------------+
    | IF(2, 'true', 'false') |
    +------------------------+
    | true                   |
    +------------------------+
    

    Однако, значения TRUE и FALSE просто псевдонимы для 1 и 0, соответственно, как показано здесь:

    mysql> SELECT IF(0 = FALSE, 'true', 'false');
    +--------------------------------+
    | IF(0 = FALSE, 'true', 'false') |
    +--------------------------------+
    | true                           |
    +--------------------------------+
    
    mysql> SELECT IF(1 = TRUE, 'true', 'false');
    +-------------------------------+
    | IF(1 = TRUE, 'true', 'false') |
    +-------------------------------+
    | true                          |
    +-------------------------------+
    
    mysql> SELECT IF(2 = TRUE, 'true', 'false');
    +-------------------------------+
    | IF(2 = TRUE, 'true', 'false') |
    +-------------------------------+
    | false                         |
    +-------------------------------+
    
    mysql> SELECT IF(2 = FALSE, 'true', 'false');
    +--------------------------------+
    | IF(2 = FALSE, 'true', 'false') |
    +--------------------------------+
    | false                          |
    +--------------------------------+
    

    Последние два запроса выводят на экран такие результаты, потому что 2 не равно ни 1, ни 0.

  • SMALLINT[(M )] [UNSIGNED] [ZEROFILL]

    Маленькое целое число. Диапазон со знаком от -32768 до 32767. Диапазон без знака от 0 до 65535.

  • MEDIUMINT[(M )] [UNSIGNED] [ZEROFILL]

    Целое число среднего размера. Диапазон со знаком от -8388608 до 8388607. Диапазон без знака от 0 до 16777215.

  • INT[(M)] [UNSIGNED] [ZEROFILL]

    Целое число нормального размера. Диапазон со знаком от -2147483648 до 2147483647. Диапазон без знака от 0 до 4294967295.

  • INTEGER[(M )] [UNSIGNED] [ZEROFILL]

    Этот тип синоним для INT .

  • BIGINT[(M)] [UNSIGNED] [ZEROFILL]

    Большое целое число. Диапазон со знаком от -9223372036854775808 до 9223372036854775807. Диапазон без знака от is 0 до 18446744073709551615.

    SERIAL псевдоним для BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.

    Некоторые вещи Вы должны знать относительно столбцов BIGINT:

    • Вся арифметика сделана, используя знаковые значения BIGINT или DOUBLE, таким образом, Вы не должны использовать большие целые числа без знака, больше 9223372036854775807 (63 bits), кроме как с разрядными функциями! Если Вы делаете это, некоторые из последних цифр в результате могут быть неправильными из-за округления ошибок, преобразовывая BIGINT в DOUBLE.

      MySQL может обработать BIGINT в следующих случаях:

      • Используя целые числа, чтобы сохранить большие значения без знака в столбце BIGINT.

      • В MIN(col_name ) или MAX( col_name), где col_name обращается к столбцу BIGINT .
      • Используя операторы (+, -, * и подобные где оба операнда целые числа.

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

    • Операторы -, + и * применяют арифметику BIGINT, когда оба операнда целочисленные значения. Это означает, что, если Вы умножаете два больших целых числа (или получаете результат из функций, которые возвращают целые числа), Вы можете получить неожиданные результаты, когда результат больше 9223372036854775807.

  • DECIMAL[(M [,D])] [UNSIGNED] [ZEROFILL]

    Упакованное точное число фиксированной точки. M общее количество цифр (точность), а D число цифр после десятичной запятой (масштаб). Десятичная запятая и (для отрицательных чисел) знак - не включены в M. Если D 0, у значений нет никакой десятичной запятой или дробной части. Максимальное количество цифр (M) для DECIMAL 65. Максимальное количество поддержанных десятичных чисел (D) 30. Если D пропущено, по умолчанию 0. Если M пропущено, по умолчанию 10.

    UNSIGNED, если определено, отвергает отрицательные величины.

    Все основные вычисления (+, -, *, /) со столбцами DECIMAL сделаны с точностью в 65 цифр.

  • DEC[(M [,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M [,D])] [UNSIGNED] [ZEROFILL], FIXED[(M [,D])] [UNSIGNED] [ZEROFILL]

    Эти типы синонимы для DECIMAL. FIXED синоним доступен для совместимости с другими системами базы данных.

  • FLOAT[(M ,D)] [UNSIGNED] [ZEROFILL]

    Маленькое (одинарная точность) число с плавающей запятой. Допустимые значения от -3.402823466E+38 до -1.175494351E-38, 0 и от 1.175494351E-38 до 3.402823466E+38. Это теоретические пределы, основанные на стандарте IEEE. Фактический диапазон может быть немного меньшим в зависимости от Ваших аппаратных средств или операционной системы.

    M общее количество цифр и D число цифр после десятичной запятой. Если M и D опущены, значения сохранены к пределам, разрешенным аппаратными средствами. Число одинарной точности с плавающей запятой имеет приблизительно 7 десятичных разрядов.

    UNSIGNED, если определено, отвергает отрицательные величины.

    Использование FLOAT может дать Вам некоторые неожиданные проблемы, потому что все вычисления в MySQL сделаны с двойной точностью. См. раздел B.5.4.7.

  • DOUBLE[(M ,D)] [UNSIGNED] [ZEROFILL]

    Нормальный размер (двойная точность) число с плавающей запятой. Допустимые значения от -1.7976931348623157E+308 до -2.2250738585072014E-308, 0 и от 2.2250738585072014E-308 до 1.7976931348623157E+308. Это теоретические пределы, основанные на стандарте IEEE. Фактический диапазон может быть немного меньшим в зависимости от Ваших аппаратных средств или операционной системы.

    M общее количество цифр и D число цифр после десятичной запятой. Если M и D опущены, значения сохранены к пределам, разрешенным аппаратными средствами. Число двойной точности с плавающей запятой имеет приблизительно 15 десятичных разрядов.

    UNSIGNED, если определено, отвергает отрицательные величины.

  • DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M, D)] [UNSIGNED] [ZEROFILL]

    Эти типы синонимы для DOUBLE. Исключение: если включен режим SQL REAL_AS_FLOAT, REAL синоним для FLOAT, а не для DOUBLE.

  • FLOAT(p ) [UNSIGNED] [ZEROFILL]

    Число с плавающей запятой. p представляет точность в битах, но MySQL использует это значение только, чтобы определить, использовать ли FLOAT или DOUBLE для получающегося типа данных. Если p от 0 до 24, тип данных становится FLOAT без значения M или D. Если p от 25 до 53, тип данных становится DOUBLE без значения M или D. Диапазон получающегося столбца то же самое, что касается одинарной точности FLOAT или двойной точности DOUBLE , описанные ранее в этом разделе.

    Синтаксис FLOAT( p) предусмотрен для совместимости с ODBC.

12.1.2. Краткий обзор типов даты и времени

Для дополнительной информации о свойствах и требованиях хранения временных типов см. разделы 12.3 и 12.8. Для описаний функций, которые воздействуют на временные значения см. раздел 13.7.

Для описания диапазона DATE и DATETIME "поддерживается" означает, что, хотя более ранние значения могли бы работать, нет никакой гарантии.

MySQL разрешает дробные секунды для значений TIME, DATETIME и TIMESTAMP с точностью до микросекунд (6 цифр). Чтобы определить столбец, который включает дробную часть секунд, используйте синтаксис type_name (fsp), где type_name TIME, DATETIME или TIMESTAMP, а fsp дробная точность секунд. Например:

CREATE TABLE t1 (t TIME(3), dt DATETIME(6));

Значение fsp, если есть, должно быть в диапазоне от 0 до 6. Значение 0 показывает, что нет никакой дробной части. Если опущено, точность значения по умолчанию 0. Это отличается от стандартного значения по умолчанию SQL 6, для совместимости с предыдущими версиями MySQL.

Любой столбец TIMESTAMP или DATETIME в таблице может иметь автоматическую инициализацию и свойства обновления.

  • DATE

    Дата. Поддержанный диапазон от '1000-01-01' до '9999-12-31'. MySQL отображает значения DATE в формате 'YYYY-MM-DD', но разрешает назначение значений столбцам DATE, используя строки или числа.

  • DATETIME[(fsp)]

    Комбинация даты и времени. Поддержанный диапазон от '1000-01-01 00:00:00.000000' до '9999-12-31 23:59:59.999999'. MySQL отображает значения displays DATETIME в формате 'YYYY-MM-DD HH:MM:SS[.fraction]', но разрешает назначение значений столбцам DATETIME, используя строки или числа.

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

    Автоматическая инициализация и обновение для столбцов DATETIME могут быть определены, используя предложения DEFAULT и ON UPDATE, как описано в разделе 12.3.5.

  • TIMESTAMP[(fsp)]

    Метка времени (timestamp). Диапазон от '1970-01-01 00:00:01.000000' UTC до '2038-01-19 03:14:07.999999' UTC. Значения TIMESTAMP сохранены как число секунд начиная с '1970-01-01 00:00:00' UTC. TIMESTAMP не может представить значение '1970-01-01 00:00:00', потому что это эквивалентно 0 секундам от начала эпохи, а значение 0 сохранено для того, чтобы представить '0000-00-00 00:00:00', нулевое значение TIMESTAMP.

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

    Как сервер обрабатывает определения TIMESTAMP зависит от значения переменной explicit_defaults_for_timestamp (см. раздел 6.1.5). По умолчанию explicit_defaults_for_timestamp отключена, и сервер обрабатывает TIMESTAMP следующим образом:

    Если не определено иначе, первый столбец TIMESTAMP в таблице определен, чтобы быть автоматически установленным в дату и время новой модификации если значение не назначено явно. Это делает TIMESTAMP полезным для записи моментов операций INSERT или UPDATE. Вы можете также установить любой столбец TIMESTAMP к текущей дате и времени, назначая ему значение NULL, если это не было определено с атрибутом NULL, чтобы разрешить NULL.

    Автоматическая инициализация и обновление к текущей дате и времени может быть определено, используя предложения DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP. По умолчанию первый столбец TIMESTAMP имеет эти свойства, как ранее отмечено. Однако, любой столбец TIMESTAMP в таблице может быть определен, чтобы иметь эти свойства.

    Если explicit_defaults_for_timestamp включен, нет никакого автоматического назначения атрибутов DEFAULT CURRENT_TIMESTAMP или ON UPDATE CURRENT_TIMESTAMP любому столбцу TIMESTAMP. Они должны быть включены явно в определении столбца. Кроме того, любой TIMESTAMP, не объявленный явно как NOT NULL, допускает значения NULL.

  • TIME[(fsp)]

    Время. Диапазон от '-838:59:59.000000' до '838:59:59.000000'. MySQL отображает значения TIME в формате 'HH:MM:SS[.fraction]', но позволяет задавать значения столбцов TIME, используя строки или числа.

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

  • YEAR[(4)]

    Год в формате с четырьмя цифрами. MySQL отображает значения YEAR в формате YYYY, но позволяет задавать значения столбцов YEAR, используя строки или числа. Значения показываются от 1901 до 2155 и 0000.

    Для дополнительной информации о формате и интерпретации входных значений YEAR см. раздел 12.3.3.

    MySQL 8.0 не поддерживает тип данных YEAR(2), разрешенный в более старых версиях MySQL. Для инструкций по преобразованию в to YEAR(4) см. раздел 12.3.4.

Совокупные функции 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;

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

12.1.3. Краткий обзор строк

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

MySQL интерпретирует технические требования длины в символьных определениях столбца в символьных модулях. Это относится к типам CHAR, VARCHAR и TEXT.

Определения столбца для многих строковых типов данных могут включать признаки, которые определяют набор символов или сопоставление столбца. Эти признаки относятся к типам CHAR, VARCHAR, TEXT, ENUM и SET.

  • Признак CHARACTER SET определяет набор символов, а COLLATE определяет сопоставление для набора символов. Например:

    CREATE TABLE t (c1 VARCHAR(20) CHARACTER SET utf8,
                    c2 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs);
    

    Это табличное определение создает столбец, названный c1, который имеет набор символов utf8 с сопоставлением по умолчанию для того набора символов, и столбец c2, у которого есть набор символов latin1 и чувствительное к регистру сопоставление.

    Правила для того, чтобы назначить набор символов и сопоставление, когда один или оба атрибута CHARACTER SET и COLLATE отсутствуют, описаны в разделе 11.1.3.5 .

    CHARSET синоним для CHARACTER SET.

  • Определение атрибута CHARACTER SET binary для типа данных строки символов заставляет столбец создаваться как соответствующий двоичный строковый тип данных: CHAR станет BINARY, VARCHAR станет VARBINARY, а TEXT станет BLOB.Для типов ENUM и SET этого не происходит: они создаются как объявлено. Предположите, что Вы определяете таблицу, используя это определение:
    CREATE TABLE t (c1 VARCHAR(10) CHARACTER SET binary,
                    c2 TEXT CHARACTER SET binary,
                    c3 ENUM('a','b','c') CHARACTER SET binary);
    

    У получающейся таблицы есть это определение:

    CREATE TABLE t (c1 VARBINARY(10), c2 BLOB,
                    c3 ENUM('a','b','c') CHARACTER SET binary);
    
  • Признак BINARY стенография для того, чтобы определить табличный набор символов по умолчанию и сопоставление _bin того набора символов. В этом случае, сравнение и сортировка основаны на значениях кодов символов.
  • Атрибут ASCII сокращение для CHARACTER SET latin1.
  • Атрибут UNICODE сокращение для CHARACTER SET ucs2.

Символьное сравнение столбца и сортировка основаны на сопоставлении, назначенном столбцу. Для типов CHAR, VARCHAR, TEXT, ENUM и SET Вы можете объявить столбец с двоичным сопоставлением (_bin) или признаком BINARY, чтобы использовать основные символьные кодовые обозначения, а не лексическое упорядочивание.

  • [NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]

    Строка фиксированной длины, которая всегда дополнена справа пробелами до указанной длины, когда сохранена. M представляет длину столбца в символах. Диапазон M от 0 до 255. Если M опущен, длина 1.

    Конечные пробелы удалены, когда значения CHAR получены, если режим SQL PAD_CHAR_TO_FULL_LENGTH выключен.

    CHAR сокращение для CHARACTER. NATIONAL CHAR (или NCHAR) стандартный способ SQL определить, что столбец CHAR должен использовать некоторый предопределенный набор символов. MySQL использует utf8 как этот предопределенный набор символов.

    Тип CHAR BYTE псевдоним для BINARY. Это особенность совместимости.

    MySQL разрешает Вам создавать столбец типа CHAR(0). Это полезно прежде всего, когда Вы должны быть совместимы со старыми приложениями, которые зависят от существования столбца, но которые фактически не используют его значение. CHAR(0) также довольно хорош, когда Вы нуждаетесь в столбце, который может взять только два значения: столбец, который определен как CHAR(0) NULL занимает только один бит и может взять только значения NULL и '' (пустая строка).

  • [NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name]

    Строка переменной длины. M представляет максимальную длину столбца в символах. Диапазон M от 0 до 65535. Эффективная максимальная длина VARCHAR зависит от максимального размера строки (65 535 байтов, который совместно использован всеми столбцами), и используемого набора символов. Например, символы utf8 могут потребовать до трех байтов на символ, таким образом, столбец VARCHAR, который использует набор символов utf8 имеет максимумом 21844 символа. См. раздел C.10.4.

    MySQL хранит значения VARCHAR как префикс в 1 или 2 байта плюс данные. Префикс длины указывает на число байтов в значении. Столбец VARCHAR использует один байт длины, если значения требуют не больше 255 байтов, два байта длины, если значения могут потребовать больше, чем 255 байтов.

    MySQL следует за стандартной спецификацией SQL и НЕ удаляет конечные пробелы из значений VARCHAR.

    VARCHAR сокращение для CHARACTER VARYING. NATIONAL VARCHAR стандартный способ SQL определить, что столбец VARCHAR должен использовать некоторый предопределенный набор символов. MySQL использует utf8 как этот предопределенный набор символов. NVARCHAR сокращение для NATIONAL VARCHAR.

  • BINARY(M )

    Тип BINARY подобен CHAR, но хранит двоичные строки байтов, а не недвоичные строки символов.

  • VARBINARY(M )

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

  • TINYBLOB

    Столбец BLOB с максимальной длиной 255 (28-1) байт. Каждое значение TINYBLOB сохранено, используя 1-байтовую приставку длины, которая указывает на число байтов в значении.

  • TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]

    Столбец TEXT с максимальной длиной (28-1). Эффективная максимальная длина меньше, если значение содержит мультибайтные символы. Каждое значение TINYTEXT сохранено, используя 1-байтовую приставку длины, которая указывает на число байтов в значении.

  • BLOB[(M)]

    Столбец BLOB с максимальной длиной 65535 (216-1) байт. Каждое значение BLOB сохранено, используя 2-байтовую приставку длины, которая указывает на число байтов в значении.

    Дополнительная длина M может быть дана для этого типа. Если это сделано, MySQL создает столбец как самый маленький тип BLOB достаточно большой, чтобы содержать значения длиной в M байт.

  • TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]

    Столбец TEXT с максимальной длиной 65535 (216-1) символов. Эффективная максимальная длина меньше, если значение содержит мультибайтные символы. Каждое значение TEXT сохранено, используя 2-байтовую приставку длины, которая указывает на число байтов в значении.

    Дополнительная длина M может быть дана для этого типа. Если это сделано, MySQL создает столбец как самый маленький тип TEXT достаточно большой, чтобы содержать значения длиной в M байт.

  • MEDIUMBLOB

    Столбец BLOB с максимальной длиной в 16,777,215 (224-1) байт. Каждое значение MEDIUMBLOB сохранено, используя 3-байтовую приставку длины, которая указывает на число байтов в значении.

  • MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]

    Столбец TEXT с максимальной длиной в 16,777,215 (224-1) символов. Эффективная максимальная длина меньше, если значение содержит мультибайтные символы. Каждое значение MEDIUMTEXT сохранено, используя 3-байтовую приставку длины, которая указывает на число байтов в значении.

  • LONGBLOB

    Столбец BLOB с максимальной длиной в 4,294,967,295 байт или 4GB (232-1). Эффективная максимальная длина LONGBLOB зависит от сконфигурированного максимального пакетного размера в протоколе клиент-сервер и доступной памяти. Каждое значение LONGBLOB сохранено, используя 4-байтовую приставку длины, которая указывает на число байтов в значении.

  • LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]

    Столбец TEXT с максимальной длиной в 4,294,967,295 или 4GB (232-1) символов. Эффективная максимальная длина меньше, если значение содержит мультибайтные символы. Эффективная максимальная длина столбцов LONGTEXT также зависит от сконфигурированного максимального пакетного размера в протоколе клиент-сервер и доступной памяти. Каждое значение LONGTEXT сохранено, используя 4-байтовую приставку длины, которая указывает на число байтов в значении.

  • ENUM('value1', 'value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]

    Перечисление. Строковый объект, у которого может быть только одно значение, выбранное из списка значений 'value1', 'value2', ..., NULL или специальное ошибочное значение ''. Значения ENUM представлены внутренне как целые числа.

    У столбца ENUM может быть максимум 65535 отличных элементов.

  • SET('value1', 'value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]

    Набор. Строковый объект, у которого может быть ноль или больше значений, каждое из которых должно быть выбрано из списка значений 'value1', 'value2', .... Значения SET представлены внутренне как целые числа.

    У столбца SET может быть максимум 64 отличных участника.

12.2. Числовые типы

MySQL поддерживает все стандартные типы числовых данных SQL. Эти типы включают точные типы числовых данных (INTEGER, SMALLINT, DECIMAL и NUMERIC), так же как приблизительные типы числовых данных (FLOAT, REAL и DOUBLE PRECISION). Ключевое слово INT синоним для INTEGER, а DEC и FIXED синонимы для DECIMAL. MySQL обрабатывает DOUBLE как синоним для DOUBLE PRECISION (нестандартное расширение). MySQL также обрабатывает REAL как синоним DOUBLE PRECISION (нестандартное расширение), если включен режим SQL REAL_AS_FLOAT.

Тип данных BIT хранит битовые значения и поддержан для MyISAM, MEMORY и InnoDB.

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

Для информации о числовых требованиях хранения типа см. раздел 12.8.

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

12.2.1. Типы целого числа (точное значение) INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

MySQL поддерживает стандартные типы целого числа SQL INTEGER (или INT) и SMALLINT. Как расширение к стандарту, MySQL также поддерживает типы целого числа TINYINT, MEDIUMINT и BIGINT. Следующая таблица показывает необходимое место для хранения и диапазон для каждого типа целого числа.

ТипМесто МинимумМаксимум
(байтов) (Signed/Unsigned) (Signed/Unsigned)
TINYINT1 -128127
0 255
SMALLINT2 -3276832767
0 65535
MEDIUMINT3 -83886088388607
0 16777215
INT4 -21474836482147483647
0 4294967295
BIGINT8 -92233720368547758089223372036854775807
0 18446744073709551615

12.2.2. Типы с фиксированной точкой (точное значение) DECIMAL, NUMERIC

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

MySQL хранит значения DECIMAL в двоичном формате. См. раздел 13.20.

В определении столбца DECIMAL могут быть определены точность и масштаб (обычно так и бывает), например:

salary DECIMAL(5,2)

В этом примере 5 точность и 2 масштаб. Точность представляет число существенных цифр, которые сохранены для значений, а масштаб представляет число цифр, которые могут быть сохранены после десятичной запятой.

Стандартный SQL требует, чтобы DECIMAL(5,2) мог сохранить любое значение с пятью цифрами и двумя десятичными числами, так значения, которые могут быть сохранены в столбце salary в диапазоне от -999.99 до 999.99.

В стандартном SQL синтаксис DECIMAL(M) эквивалентен DECIMAL(M,0). Точно так же синтаксис DECIMAL эквивалентен DECIMAL(M,0), где выполнению разрешают решить значение M. поддерживает обе эти формы синтаксиса DECIMAL. Значение по умолчанию M 10.

Если масштаб 0, значения DECIMAL не содержат десятичной запятой или дробной части.

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

12.2.3. Типы с плавающей запятой (приблизительная точность) FLOAT, DOUBLE

Типы FLOAT и DOUBLE представляют приблизительные значения числовых данных. MySQL использует четыре байта для значений одинарной точности и восемь байтов для значений двойной точности.

Для FLOAT стандарт SQL разрешает дополнительную спецификацию точности (но не диапазон экспоненты) в битах после ключевого слова FLOAT в круглых скобках. MySQL также поддерживает эту дополнительную спецификацию точности, но значение точности используется только, чтобы определить размер хранения. Результаты точностью от 0 до 23 хранятся в 4-байтовом столбце FLOAT одинарной точности. Результаты точностью от 24 до 53 хранятся в 8-байтовом столбце DOUBLE двойной точности.

MySQL разрешает нестандартный синтаксис: FLOAT(M,D) или REAL(M,D) или DOUBLE PRECISION(M,D) . Здесь (M,D) означает, что значения могут быть сохранены размером до M цифр всего из них D цифр могут быть после десятичной запятой. Например, столбец, определенный как FLOAT(7,4) будет выглядеть как -999.9999 при отображении. MySQL выполняет округление, сохраняя значения, так, если Вы вставляете 999.00009 в столбец FLOAT(7,4), приблизительный результат будет 999.0001.

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

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

12.2.4. Тип битового значения BIT

Тип BIT используется, чтобы сохранить битовые значения. Тип BIT(M) включает хранение M-битовых значений. M может колебаться от 1 до 64.

Определить битовые значения можно в нотации b'value'. value двоичное значение из нулей и единиц. Например, b'111' и b'10000000' означают соответственно 7 и 128. См. раздел 10.1.5.

Если Вы назначаете значение столбцу BIT(M), которое меньше M бит, значение дополнено слева нолями. Например, назначая значение b'101' столбцу BIT(6), в действительности Вы делаете то же самое, как назначая b'000101'.

12.2.5. Числовые признаки типа

MySQL поддерживает расширение для того, чтобы произвольно определить ширину типов данных целого числа в круглых скобках после основного ключевого слова для типа. Например, INT(4) определяет INT с шириной отображения четыре цифры. Эта дополнительная ширина может использоваться приложениями, чтобы вывести на экран целочисленные значения, имеющие ширину меньше ширины, определенной для столбца, дополняя их слева пробелами. Таким образом, эта ширина присутствует в метаданных, возвращенных с наборами результатов. Используется ли это или нет, зависит от приложения.

Ширина отображения НЕ ограничивает диапазон значений, которые могут быть сохранены в столбце. И при этом это не мешает вывести на экран правильно значения шире, чем ширина отображения столбца. Например, столбец, определенный как SMALLINT(3) имеет обычный SMALLINT диапазон от -32768 до 32767, и значения вне диапазона, разрешенного тремя цифрами, выведены на экран в полном использовании больше, чем трех цифр.

Когда используется в соединении с дополнительным (нестандартным) признаком ZEROFILL, дополнение значения по умолчанию пробелами заменено нолями. Например, для столбца, объявленного как INT(4) ZEROFILL, значение 5 будет 0005.

Признак ZEROFILL проигнорирован, когда столбец вовлечен в выражения или запрос UNION.

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

У всех типов целого числа может быть дополнительный (нестандартный) признак UNSIGNED. Тип без знака может использоваться, чтобы разрешить только неотрицательные числа в столбце или когда Вы нуждаетесь в большем верхнем числовом диапазоне для столбца. Например, если столбец INT UNSIGNED, размер диапазона столбца тот же самый, но его конечные точки сдвигаются от -2147483648 и 2147483647 к 0 и 4294967295.

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

Если Вы определяете ZEROFILL для числового столбца, MySQL автоматически добавляет UNSIGNED.

У целого числа или типов данных с плавающей запятой может быть дополнительный признак AUTO_INCREMENT. Когда Вы вставляете значение NULL в индексированный столбец AUTO_INCREMENT, реально он будет установлен в следующее значение последовательности. Как правило, это value+1, где value самое большое значение для столбца в настоящее время в таблице. Последовательности AUTO_INCREMENT начинаются с 1.

Сохранение 0 в столбец AUTO_INCREMENT имеет тот же самый эффект, как запись NULL, если включен режим SQL NO_AUTO_VALUE_ON_ZERO.

Вставка NULL для генерации значений AUTO_INCREMENT требует, чтобы столбец был объявлен NOT NULL. Если столбец объявлен NULL, вставка NULL сохранит именно NULL. Когда Вы вставляете любое другое значение в столбец AUTO_INCREMENT, он установлен в это значение, а последовательность сброшена так, чтобы следующее автоматически произведенное значение следовало последовательно из вставленного значения.

В MySQL 8.0 отрицательные величины для столбцов AUTO_INCREMENT не поддержаны.

12.2.6. Обработка переполнения и выхода из диапазона

Когда MySQL сохраняет значение в числовом столбце, которое вне допустимого диапазона типа данных столбца, результат зависит от режима SQL в это время:

  • Если строгий режим SQL включен, MySQL отклоняет значение с ошибкой, и вставка терпит неудачу, в соответствии со стандартом SQL.

  • Если никакие строгие режимы не включены, MySQL отсекает значение к соответствующей конечной точке диапазона и хранит получающееся значение.

    Когда значение вне диапазона назначено столбцу целого числа, MySQL сохранит значение, представляющее соответствующую конечную точку диапазона типа данных столбца. Если Вы сохраните 256 в TINYINT или TINYINT UNSIGNED, MySQL запишет соответственно 127 или 255.

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

О преобразованиях назначения столбца, которые происходят из-за отсечения, когда MySQL не работает в строгом режиме, сообщают предупреждения для for ALTER TABLE, LOAD DATA INFILE, UPDATE и multiple-row INSERT. В строгом режиме терпят неудачу эти запросы, и некоторые или все значения не будут введены или изменены, в зависимости от того, является ли таблица транзакционной таблицей и другими факторами. Для деталей см. раздел 6.1.8.

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

mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807+1)'

Чтобы позволить работе преуспеть в этом случае, преобразуйте значение в беззнаковое;

mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
| 9223372036854775808                       |
+-------------------------------------------+

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

mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
| 9223372036854775808.0     |
+---------------------------+

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

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in
'(cast(0 as unsigned) - 1)'

Если режим SQL NO_UNSIGNED_SUBTRACTION включен, результат отрицателен:

mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| -1                      |
+-------------------------+

Если результат такой работы используется, чтобы обновить столбец UNSIGNED целого числа, результат отсечен к максимальному значению для типа столбца, или отсечен к 0, если включен NO_UNSIGNED_SUBTRACTION. Если строгий режим SQL включен, ошибка происходит, и столбец остается неизменным.

12.3. Типы даты и времени

Типы даты и времени для того, чтобы представить временные значения DATE, TIME, DATETIME, TIMESTAMP и YEAR. У каждого временного типа есть диапазон допустимых значений, так же как нулевое значение, которое может использоваться, когда Вы определяете недопустимое значение, которое не может представить MySQL. Тип TIMESTAMP имеет специальное автоматическое поведение обновления, описанное позже. Для требований хранения временных типов см. раздел 12.8.

Имейте в виду эти общие соображения, работая с типами времени и датой:

  • MySQL получает значения для данной даты или типа времени в стандартном выходном формате, но пытается интерпретировать множество форматов для входных значений, которые Вы поставляете (например, когда Вы определяете значение, которое будет назначено или по сравнению с датой или типом времени). Для описания разрешенных форматов для типов даты и времени см. раздел 10.1.3. Ожидается, что Вы поставляете допустимые значения. Непредсказуемые результаты могут произойти, если Вы используете значения в других форматах.

  • Хотя MySQL пытается интерпретировать значения в нескольких форматах, части даты должны всегда даваться в порядке "день месяца года" (например, '98-09-04'), вместо в "дневном году месяца" ('09-04-98').
  • Даты, содержащие значения года с двумя цифрами, неоднозначны, потому что столетие неизвестно. MySQL интерпретирует значения года с двумя цифрами, используя эти правила:

    • Год в диапазоне 70-99 преобразован в 1970-1999.

    • Год в диапазоне 00-69 преобразован в 2000-2069.

  • Преобразование значений из одного временного типа в другой происходит согласно правилам в разделе 12.3.7.
  • MySQL автоматически преобразовывает дату или время к числу, если значение используется в числовом контексте и наоборот.
  • По умолчанию, когда MySQL сталкивается со значением для типа даты или времени, которое вне диапазона или иначе недопустимо для типа, это преобразовывает значение в нулевое для того типа. Исключение: значения TIME вне диапазона отсечены к соответствующей конечной точке TIME.
  • Устанавливая режим SQL в соответствующее значение, Вы можете определить более точно, какие даты Вы хотите, чтобы MySQL поддерживал. См. раздел 6.1.8. Вы можете заставить MySQL принимать определенные даты, такие, как '2009-11-31', включая режим SQL ALLOW_INVALID_DATES . Это полезно, когда Вы хотите сохранить возможно, неправильное значение, которое пользователь определил (например, в веб-форме) в базе данных для будущей обработки. Под этим режимом MySQL проверяет только, что месяц находится в диапазоне от 1 до 12 и что день находится в диапазоне от 1 до 31.
  • MySQL разрешает Вам хранить даты, где день или месяц и день ноль в столбце DATE или DATETIME. Это полезно для приложений, которые должны сохранить даты рождения, для которых Вы не можете знать точную дату. В этом случае Вы просто храните дату как '2009-00-00' или '2009-01-00'. Если Вы сохраните такие даты, Вы не должны ожидать правильные результаты для таких функций, как DATE_SUB() или DATE_ADD() , которые требует полных дат. Чтобы отвергнуть нулевые части месяца или дня в датах, включите режим NO_ZERO_IN_DATE.
  • MySQL разрешает Вам хранить нулевое значение '0000-00-00' как пустую дату. Это в некоторых случаях более удобно, чем использование значений NULL: занимает меньше места в данных и индексе. Отвергнуть '0000-00-00' можно, включив режим NO_ZERO_DATE.
  • Нулевые дата или время, используемые через Connector/ODBC, преобразованы автоматически в NULL, так как ODBC не может обработать такие значения.

Следующая таблица показывает формат нулевых значений для каждого типа. Нулевые значения являются особенными, но Вы можете сохранить или отослать к ним явно используя значения, показанные в таблице. Вы можете также сделать это с использованием значений '0' или 0, которые легче написать. Для временных типов, которые включают часть даты (DATE, DATETIME и TIMESTAMP), использование этих значений производит предупреждения, если включен режим SQL NO_ZERO_DATE.

Тип данных Нулевое значение
DATE '0000-00-00'
TIME '00:00:00'
DATETIME '0000-00-00 00:00:00'
TIMESTAMP '0000-00-00 00:00:00'
YEAR 0000

12.3.1. Типы DATE, DATETIME и TIMESTAMP

Типы DATE, DATETIME и TIMESTAMP связаны. Этот раздел описывает их характеристики, как они подобны, и как они отличаются. MySQL признает значения DATE, DATETIME и TIMESTAMP в нескольких форматах, описанных в разделе 10.1.3. Для описания диапазона DATE и DATETIME поддерживается означает, что, хотя более ранние значения могли бы работать, нет никакой гарантии.

Тип DATE используется для значений с частью даты, но без части времени. MySQL получает и выводит на экран значения DATE в формате 'YYYY-MM-DD'. Поддержанный диапазон от '1000-01-01' до '9999-12-31'.

Тип DATETIME используется для значений с частями даты и времени. MySQL получает и выводит на экран значения DATETIME в формате 'YYYY-MM-DD HH:MM:SS'. Поддержанный диапазон от '1000-01-01 00:00:00' до '9999-12-31 23:59:59'.

Тип TIMESTAMP используется для значений, которые содержат части даты и времени. TIMESTAMP имеет диапазон от '1970-01-01 00:00:01' UTC до '2038-01-19 03:14:07' UTC.

Значение DATETIME или TIMESTAMP может включать дробную часть секунд до микросекунд (6 цифр). В частности, любая дробная часть в значении, вставленном в столбец DATETIME или TIMESTAMP, сохранена. С включенной дробной частью формат для этих значений 'YYYY-MM-DD HH:MM:SS[.fraction]', где диапазон DATETIME от '1000-01-01 00:00:00.000000' до '9999-12-31 23:59:59.999999', а диапазон TIMESTAMP от '1970-01-01 00:00:01.000000' до '2038-01-19 03:14:07.999999'. Дробная часть должна всегда отделяться от остальной части времени десятичной запятой, никакой другой дробный разделитель секунд не признан. Для информации о дробной поддержке секунд в MySQL см. раздел 12.3.6.

Типы данных TIMESTAMP и DATETIME предлагают автоматическую инициализацию и обновление к текущей дате и времени. Для получения дополнительной информации см. раздел 12.3.5.

MySQL конвертирует значения TIMESTAMP от зоны текущего времени в UTC для хранения и назад из UTC в зону текущего времени для извлечения. Это не происходит для других типов, например, DATETIME. По умолчанию зона текущего времени для каждого соединения это время сервера. Часовой пояс может быть установлен на основе соединения. Пока установка часового пояса остается постоянной, Вы возвращаете то же самое значение, которое Вы храните. Если Вы сохраняете TIMESTAMP, а потом изменяете часовой пояс, полученное значение отличается от значения, которое Вы сохранили. Это происходит, потому что тот же самый часовой пояс не использовался для преобразования в обоих направлениях. Зона текущего времени доступна как значение переменной time_zone. Подробности в разделе 11.6.

Недопустимые значения DATE, DATETIME или TIMESTAMP преобразованы в нулевое значение соответствующего типа ('0000-00-00' или '0000-00-00 00:00:00').

Знайте об определенных свойствах интерпретации значения даты в MySQL:

  • MySQL разрешает облегченный формат для значений, определенных как строки, в которых любой символ пунктуации может использоваться в качестве разделителя между частями даты или частями времени. В некоторых случаях, этот синтаксис может обманывать. Например, такое значение, как '10:11:12' может быть похожим на временное из-за :, но интерпретируется как год '2010-11-12', если используется в контексте даты. Значение '10:45:15' преобразовано в '0000-00-00', потому что '45' недопустимый месяц.

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

  • Сервер требует, чтобы значения месяца и дня были допустимы и не просто в диапазоне 1-12 и 1-31, соответственно. При отключенном строгом режиме недопустимые даты, вроде '2004-04-31', конвертируются в '0000-00-00' и предупреждение произведено. С включенным строгим режимом недопустимые даты производят ошибку. Чтобы разрешить такие даты, включите ALLOW_INVALID_DATES. См. раздел 6.1.8.
  • MySQL не принимает значения TIMESTAMP, которые включают ноль в столбец дня или месяца или значения, которые не являются допустимой датой. Единственное исключение к этому правилу: специальное нулевое значение '0000-00-00 00:00:00'.

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

12.3.2. Тип TIME

MySQL получает и отображает значения TIME в формате 'HH:MM:SS' (или 'HHH:MM:SS' для больших значений часов). Значения TIME могут быть в диапазоне от '-838:59:59' до '838:59:59'. Часть часов может быть настолько большой потому, что TIME может использоваться не только, чтобы представить время суток (которое должно составить меньше 24 часов), но также прошедшее время или временной интервал между двумя событиями (который может быть намного больше, чем 24 часа или даже отрицательным).

MySQL признает значения TIME в нескольких форматах, некоторые из которых могут включать дробную часть секунд до микросекунд (6 цифр). См. раздел 10.1.3. Для информации о дробной поддержке секунд в MySQL см. раздел 12.3.6. С дробной частью диапазон для значения TIME от '-838:59:59.000000' до '838:59:59.000000'.

Будьте осторожны относительно назначения сокращенных значений столбцам TIME. MySQL интерпретирует сокращенные значения TIME с двоеточиями как время дня. Таким образом, '11:12' значит '11:12:00', а не '00:11:12'. MySQL интерпретирует сокращенные значения без двоеточий, используя предположение, что две самых правых цифры представляют секунды (то есть, как прошедшее время, а не как время суток). Например, Вы могли бы думать, что '1112' и 1112 значат '11:12:00' (12 минут после 11 часов), но MySQL интерпретирует их как '00:11:12' (11 минут 12 секунд). Точно так же '12' и 12 интерпретируются как '00:00:12'.

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

По умолчанию значения, которые лежат вне диапазона TIME, но иначе допустимы, отсечены к самой близкой конечной точке диапазона. Например, '-850:00:00' и '850:00:00' преобразованы в '-838:59:59' и '838:59:59'. Недопустимые значения TIME преобразованы в '00:00:00'. Отметьте это потому, что '00:00:00' самостоятельно допустимое значение TIME, нет никакого способа сказать по значению '00:00:00', сохраненному в таблице, было ли оригинальное значение определено как '00:00:00' или это было недопустимо.

Для более строгой обработки недопустимых значений TIME, позвольте строгому режиму SQL вызвать ошибки. См. раздел 6.1.8.

12.3.3. Тип YEAR

Тип YEAR 1-байтовый тип, используемый, чтобы представить значения года. Это может быть объявлено как YEAR или YEAR(4) и имеет ширину четыре символа.

MySQL 8.0 не поддерживает тип YEAR(2), разрешенный в более старых версиях MySQL. Для инструкций по преобразованию в YEAR(4) см. раздел 12.3.4.

MySQL отображает YEAR в формате YYYY с диапазоном от 1901 до 2155 или 0000.

Вы можете определить значения YEAR во множестве форматов:

  • Как число с 4 цифрами в диапазоне от 1901 до 2155.

  • Как строка с 4 цифрами в диапазоне от '1901' до '2155'.
  • Как число с 1 или 2 цифрами в диапазоне от 1 до 99. MySQL преобразовывает значения в диапазонах от 1 до 69 и от 70 до 99 в значения YEAR в диапазонах от 2001 до 2069 и от 1970 до 1999.
  • Как строка с 1 или 2 цифрами в диапазоне от '0' до '99'. MySQL преобразовывает значения в диапазонах от '0' до '69' и от '70' до '99' в значения YEAR в диапазонах от 2000 до 2069 и от 1970 до 1999.
  • Результат вставки числового 0 имеет значение 0000 и внутреннее значение 0000. Чтобы вставить ноль и интерпретировать его как 2000, определите это как строку '0' или '00'.
  • Как результат функции, которая возвращает значение, которое является приемлемым в контексте YEAR, например, NOW().

MySQL конвертирует недопустимые значения YEAR в 0000.

12.3.4. Миграция столбцов из YEAR(2) в YEAR(4)

MySQL 8.0 не поддерживает тип YEAR(2), разрешенный в более старых версиях MySQL. Существующие столбцы YEAR(2) должны быть преобразованы в to YEAR(4), чтобы стать применимыми снова. Этот раздел предоставляет информацию о выполнении преобразования.

Удаление поддержки YEAR(2) в MySQL 8.0

MySQL 8.0 обрабатывает столбцы YEAR(2) следующим образом:

  • Определения столбца YEAR(2) для новых таблиц производят ошибку ER_INVALID_YEAR_COLUMN_LENGTH:

    mysql> CREATE TABLE t1 (y YEAR(2));
    ERROR 1818 (HY000): Supports only YEAR or YEAR(4) column.
    
  • Столбец YEAR(2) в существующих таблицах остается как YEAR(2), но эти столбцы в запросах производят предупреждения или ошибки.
  • Несколько программ и запросов конвертируют YEAR(2) в YEAR(4) автоматически:

    • ALTER TABLE при пересоздании таблицы.

    • REPAIR TABLE (который CHECK TABLE рекомендует, чтобы Вы использовали, если находит, что таблица содержит столбцы YEAR(2)).
    • mysql_upgrade (использует REPAIR TABLE ).
    • Дамп с помощью mysqldump и перезагрузки файла дампа. В отличие от преобразований, выполненных предыдущими вариантами, дамп и перезагрузка имеет потенциал, чтобы изменить значения.

    Обновление MySQL обычно вовлекает по крайней мере один из последних двух вариантов. Однако, относительно YEAR(2) mysql_upgrade предпочтителен. Вы должны избегать использования mysqldump , потому что, как отмечено, это может изменить значения.

Миграция с YEAR(2) на YEAR(4)

Преобразовать столбцы YEAR(2) в YEAR(4) Вы можете сделать вручную в любое время без обновления. Альтернативно Вы можете обновиться до версии MySQL с уменьшенной или удаленной поддержкой YEAR(2) (MySQL 5.6.6 или позже), затем сделать, чтобы MySQL преобразовал столбцы YEAR(2) автоматически. В последнем случае избегайте обновления, выводя и перезагружая Ваши данные, потому что это может изменить значения данных. Кроме того, если Вы используете репликацию, есть соображения обновления, которые Вы должны принять во внимание.

Преобразовать столбцы YEAR(2) в YEAR(4) вручную можно через ALTER TABLE или REPAIR TABLE. Предположите, что таблица t1 имеет это определение:

CREATE TABLE t1 (ycol YEAR(2) NOT NULL DEFAULT '70');

Измените использование столбца ALTER TABLE следующим образом:

ALTER TABLE t1 FORCE;

ALTER TABLE преобразовывает таблицу без изменения значений YEAR(2) . Если сервер ведущее устройство, ALTER TABLE копируется к ведомым устройствам и производит соответствующее табличное изменение на каждом.

Другой метод миграции должен выполнить двойное обновление: установите MySQL, не выводя и не перезагружая Ваши данные. Тогда выполнение run mysql_upgrade , который использует REPAIR TABLE для конвертации YEAR(2) в YEAR(4) не изменяя значения данных. Если сервер ведущее устройство, REPAIR TABLE копируется к ведомым устройствам и производит соответствующие табличные изменения на каждом, если Вы не вызываете mysql_upgrade с опцией --skip-write-binlog.

Обновления серверов репликации обычно обновляют к более новой версии MySQL ведомые устройства, затем обновляя ведущее устройство. Например, если ведущее и ведомое устройства оба выполняют MySQL 5.5, типичная последовательность обновления вовлекает обновление ведомого устройства до 5.6, а уже затем ведущее устройство обновляется до 5.6. Относительно другого отношения YEAR(2) в MySQL 5.6.6, последовательность обновления приводит к проблеме: предположите, что ведомое устройство было обновлено, но ведущее пока нет. Тогда составление таблицы, содержащей столбец YEAR(2) на ведущем устройстве приводит к таблице, содержащей столбец YEAR(4) на ведомом. Следовательно, у этих операций будет различный результат на ведущем и ведомом устройствах, если Вы будете использовать основанную на запросе репликацию:

  • Числовая вставка 0. У получающегося значения есть внутреннее значение 2000 на ведущем устройстве, но 0000 на ведомом.

  • Преобразование YEAR(2) в строку. Эта работа использует значение отображения YEAR(2) на ведущем устройстве, но YEAR(4) на ведомом.

Чтобы избежать таких проблем, измените все столбцы YEAR(2) на ведущем устройстве к to YEAR(4) перед обновлением. Используйте ALTER TABLE, как описано ранее. Тогда Вы можете обычно обновлять (ведомое устройство сначала, ведущее позже), не представляя никаких различий между ведущим устройством и ведомым в YEAR(2).

Одного метода перемещения нужно избежать: не выводите свои данные с mysqldump с перезагрузкой файла дампа после обновления. У этого есть потенциал, чтобы изменить значения YEAR(2).

Перемещение от YEAR(2) к YEAR(4) должно также вовлечь код программы для возможности измененного исследования поведения при условиях:

  • Код, который ожидает столбец YEAR, чтобы произвести точно две цифры.

  • Код, который не составляет различную обработку для вставок числовых 0: вставка 0 в YEAR(2) или YEAR(4) во внутреннем значении обрабатывается как 2000 или 0000, соответственно.

12.3.5. Автоматическая инициализация и обновление для TIMESTAMP и DATETIME

Столбцы TIMESTAMP и DATETIME могут быть автоматически инициализированы и обновлены к текущей дате и времени (то есть, timestamp).

Для любого столбца TIMESTAMP или DATETIME в таблице Вы можете назначить текущий timestamp в качестве значения по умолчанию, значения автообновления или обоих:

  • Автоинициализированный столбец установлен в текущий timestamp для вставленных строк, которые не определяют значения для столбца.

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

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

Чтобы определить автоматические свойства, используйте предложения DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP в определениях столбца. Порядок не имеет значения. Если оба присутствуют в определении столбца, любой может быть первым. Любой из синонимов для CURRENT_TIMESTAMP имеет то же самое значение как CURRENT_TIMESTAMP : NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP и LOCALTIMESTAMP() .

Использование DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP является определенным для TIMESTAMP и DATETIME. Предложение DEFAULT также может использоваться, чтобы определить постоянное (не автоматическое) значение по умолчанию, например, DEFAULT 0 или DEFAULT '2000-01-01 00:00:00'.

Следующее использует в качестве примера DEFAULT 0, значение по умолчанию, которое может произвести предупреждения или ошибки в зависимости от того, включен ли строгий режим SQL или NO_ZERO_DATE. Знайте, что режим SQL TRADITIONAL включает строгий режим и NO_ZERO_DATE. См. раздел 6.1.8.

Определения столбцов TIMESTAMP или DATETIME могут определить текущий timestamp для обоих значений (по умолчанию и автообновления), для одного, но не другого, или ни для одного. У различных столбцов могут быть различные комбинации автоматических свойств. Следующие правила описывают возможности:

  • С обоими DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP столбец имеет текущий timestamp для его значения по умолчанию и автоматически обновлен к текущемк timestamp.

    CREATE TABLE t1 (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE
                     CURRENT_TIMESTAMP,
                     dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE
                     CURRENT_TIMESTAMP);
    
  • С DEFAULT без ON UPDATE CURRENT_TIMESTAMP столбец имеет данное значение по умолчанию и автоматически не обновлен.

    Значение по умолчанию зависит от того, определяет ли DEFAULT CURRENT_TIMESTAMP или постоянную величину. С CURRENT_TIMESTAMP значение по умолчанию будет текущим timestamp.

    CREATE TABLE t1 (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                     dt DATETIME DEFAULT CURRENT_TIMESTAMP);
    

    С константой значение по умолчанию данное значение. В этом случае у столбца нет никаких автоматических свойств вообще.

    CREATE TABLE t1 (ts TIMESTAMP DEFAULT 0, dt DATETIME DEFAULT 0);
    
  • С ON UPDATE CURRENT_TIMESTAMP и константой в DEFAULT столбец автоматически обновлен к текущему timestamp и имеет данное постоянное значение по умолчанию.
    CREATE TABLE t1 (ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,
                     dt DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP);
    
  • С ON UPDATE CURRENT_TIMESTAMP и без DEFAULT столбец автоматически обновлен к текущему timestamp, но не имеет текущего timestamp для его значения по умолчанию.

    Значение по умолчанию в этом случае зависит от типа. TIMESTAMP имеет значение по умолчанию 0, если не определено с NULL, тогда значение по умолчанию NULL.

    CREATE TABLE t1 (ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- default 0
                     ts2 TIMESTAMP NULL ON UPDATE
                     CURRENT_TIMESTAMP -- default NULL);
    

    DATETIME имеет значение по умолчанию NULL, если не определено с NOT NULL, тогда значение по умолчанию 0.

    CREATE TABLE t1 (dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- default NULL
                     dt2 DATETIME NOT NULL ON UPDATE
                     CURRENT_TIMESTAMP -- default 0);
    

Столбцы TIMESTAMP и DATETIME не имеют никаких автоматических свойств, если они не определены явно, с этим исключением: по умолчанию первый столбец TIMESTAMP имеет оба DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP , если ни один не определен явно. Подавить автоматические свойства для первого столбца TIMESTAMP можно, используя одну из этих стратегий:

  • Включите переменну. explicit_defaults_for_timestamp. Если эта переменная включена, DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP, которые определяют автоматическую инициализацию и обновление, доступны, но не назначены ни на какой столбец TIMESTAMP, если явно не включены в определение столбца.

  • Альтернативно, если explicit_defaults_for_timestamp выключена (по умолчанию), сделайте любое из следующего:
    • Определите столбец с DEFAULT, который определяет постоянное значение по умолчанию.

    • Определите признак NULL. Это также заставляет столбец разрешать значения NULL, что означает, что Вы не можете назначить текущий timestamp, устанавливая столбец в NULL. Назначение NULL устанавливает столбец именно в NULL .

Рассмотрите эти табличные определения:

CREATE TABLE t1 (ts1 TIMESTAMP DEFAULT 0,
                 ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                 ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t2 (ts1 TIMESTAMP NULL,
                 ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                 ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t3 (ts1 TIMESTAMP NULL DEFAULT 0,
                 ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                 ON UPDATE CURRENT_TIMESTAMP);

У таблиц есть эти свойства:

  • В каждом табличном определении первый столбец TIMESTAMP не имеет никакой автоматической инициализации или обновления.

  • Таблицы отличаются в том, как столбец ts1 обрабатывает NULL. Для t1 ts1 NOT NULL и назначение ему NULL установит его в текущий timestamp. Для t2 и t3 ts1 допускает NULL и назначение им NULL установит их в NULL.
  • t2 и t3 отличаются по значению по умолчанию для ts1. Для t2 ts1 определен, чтобы разрешить NULL, таким образом, значение по умолчанию также NULL в отсутствии явного DEFAULT. Для t3 ts1 допускает NULL, но имеет явное значение по умолчанию 0.

Если определение столбца TIMESTAMP или DATETIME включает явное дробное значение точности секунд где угодно, то же самое значение должно использоваться всюду по определению столбца. Это разрешено:

CREATE TABLE t1 (ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6)
                 ON UPDATE CURRENT_TIMESTAMP(6));

А вот это нет:

CREATE TABLE t1 (ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP
                 ON UPDATE CURRENT_TIMESTAMP(3));

Инициализация TIMESTAMP и атрибут NULL

По умолчанию столбцы TIMESTAMP NOT NULL, не могут содержать NULL, и назначение NULL реально назначает текущий timestamp. Чтобы разрешить столбцу TIMESTAMP содержать NULL, явно объявите его с атрибутом NULL. В этом случае значение по умолчанию также становится NULL, если не переопределено в DEFAULT, который определяет иное значение по умолчанию. DEFAULT NULL может использоваться, чтобы явно определить NULL как значение по умолчанию. Для столбцов TIMESTAMP, не объявленных с атрибутом NULL, DEFAULT NULL недопустим. Если столбец TIMESTAMP разрешает NULL, назначение ему NULL установит именно NULL, а не текущий timestamp.

Следующая таблица содержит несколько столбцов TIMESTAMP, которые разрешают значения NULL:

CREATE TABLE t (ts1 TIMESTAMP NULL DEFAULT NULL,
                ts2 TIMESTAMP NULL DEFAULT 0,
                ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP);

Столбец TIMESTAMP, который разрешает NULL НЕ берет текущий timestamp во время вставки, кроме как при одном из следующих условий:

  • Его значение по умолчанию определено как CURRENT_TIMESTAMP , и никакое значение не определено для столбца.

  • CURRENT_TIMESTAMP или любой ее синоним, вроде NOW(), явно вставлена в столбец.

Другими словами, столбец TIMESTAMP , определенный, чтобы разрешить значения NULL, автоинициализируется, только если его определение включает DEFAULT CURRENT_TIMESTAMP:

CREATE TABLE t (ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP);

Если столбец TIMESTAMP разрешает значения NULL, но его определение не включает DEFAULT CURRENT_TIMESTAMP, Вы должны явно вставить значение, соответствующее текущей дате и времени. Предположите, что таблицы t1 и t2 имеют эти определения:

CREATE TABLE t1 (ts TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00');
CREATE TABLE t2 (ts TIMESTAMP NULL DEFAULT NULL);

Установить столбец TIMESTAMP в любой таблице к текущему timestamp во время вставки можно, явно назначив такое значение. Например:

INSERT INTO t1 VALUES (NOW());
INSERT INTO t2 VALUES (CURRENT_TIMESTAMP);

12.3.6. Дробные доли секунд во временных значениях

У MySQL 8.0 есть поддержка дробных секунд для значений TIME, DATETIME и TIMESTAMP с точностью до микросекунд (6 цифр):

  • Чтобы определить столбец, который включает дробную часть секунд, используйте синтаксис type_name(fsp), где type_name TIME, DATETIME или TIMESTAMP, а fsp дробная точность секунд. Например:

    CREATE TABLE t1 (t TIME(3), dt DATETIME(6));
    

    Значение fsp, если есть, должно быть в диапазоне от 0 до 6. Значение 0 показывает, что нет никакой дробной части. Если опущено, точность значения по умолчанию 0. Это отличается от стандартного значения по умолчанию SQL 6, для совместимости с предыдущими версиями MySQL.

  • Вставка значения TIME, DATE или TIMESTAMP с дробной частью секунд в столбец того же самого типа, но имеющий меньше дробных цифр приводит к округлению, как показано в этом примере:
    mysql> CREATE TABLE fractest(c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2));
    Query OK, 0 rows affected (0.33 sec)
    
    mysql> INSERT INTO fractest VALUES
         > ('17:51:04.777', '2014-09-08 17:51:04.777',
         >  '2014-09-08 17:51:04.777');
    Query OK, 1 row affected (0.03 sec)
    
    mysql> SELECT * FROM fractest;
    +-------------+------------------------+------------------------+
    | c1          | c2                     | c3                     |
    +-------------+------------------------+------------------------+
    | 17:51:04.78 | 2014-09-08 17:51:04.78 | 2014-09-08 17:51:04.78 |
    +-------------+------------------------+------------------------+
    1 row in set (0.00 sec)
    

    Никакое предупреждение или ошибка не даны, когда такое округление происходит. Это поведение следует стандарту SQL и не затронуто параметром sql_mode.

  • Функции, которые берут временные параметры, принимают значения с дробными секундами. Возвращаемые значения от временных функций включают дробные секунды. Например, NOW() без параметра возвращает текущую дату и время без дробной части, но берет дополнительный параметр от 0 до 6, чтобы определить, что возвращаемое значение включает дробную часть секунд.
  • Синтаксис для временных литералов производит временные значения: DATE 'str', TIME 'str' и TIMESTAMP 'str', а также эквиваленты ODBC-синтаксиса. Получающееся значение включает дробную часть секунд, если определено. Ранее временное ключевое слово типа было проигнорировано, и эти конструкции произвели строковое значение.

12.3.7. Преобразование между типами даты и времени

До некоторой степени Вы можете преобразовать значение одного временного типа в другой. Однако, может быть некоторое изменение значения или потеря информации. Во всех случаях преобразование между временными типами подвергается диапазону допустимых значений для получающегося типа. Например, хотя все значения DATE , DATETIME и TIMESTAMP могут быть определены, используя тот же самый набор форматов, нет того же самого диапазона. Значения TIMESTAMP не могут быть ранее 1970 UTC или позже '2038-01-19 03:14:07' UTC. Это означает что такая дата, как '1968-01-01', допустимая как DATE или DATETIME, недопустима в TIMESTAMP и преобразована в 0.

Преобразование значения DATE:

  • Преобразование в DATETIME или TIMESTAMP добавляет часть времени '00:00:00', так как значение DATE не содержит информации времени.

  • Преобразование в TIME не полезно: результат '00:00:00'.

Преобразование DATETIME и TIMESTAMP:

  • Преобразование в DATE принимает дробные секунды во внимание и округляет часть времени. Например, '1999-12-31 23:59:59.499' станет '1999-12-31', тогда как '1999-12-31 23:59:59.500' станет '2000-01-01'.

  • Преобразование в TIME отказывается от части даты, потому что тип TIME не содержит информации о дате.

Для преобразования TIME к другим временным типам значение CURRENT_DATE() используется для части даты. TIME интерпретируется как прошедшее время (не время суток) и добавлено к дате. Это означает, что часть даты результата отличается от текущей даты, если временное значение вне диапазона от '00:00:00' до '23:59:59'.

Предположите, что текущая дата '2012-01-01'. Значения TIME '12:00:00', '24:00:00', и '-12:00:00', когда преобразованы в DATETIME или TIMESTAMP, приведут к '2012-01-01 12:00:00', '2012-01-02 00:00:00' и '2011-12-31 12:00:00', соответственно.

Преобразование TIME в DATE подобно, но отказывается от части времени результата: '2012-01-01', '2012-01-02' и '2011-12-31', соответственно.

Явное преобразование может использоваться, чтобы переопределить неявное преобразование. Например, по сравнению с DATE и DATETIME, значение DATE принуждено к типу DATETIME, добавляя часть времени '00:00:00'. Чтобы выполнить сравнение, игнорируя часть времени DATETIME вместо этого, используйте функцию CAST() следующим образом:

date_col = CAST(datetime_col AS DATE)

Преобразование TIME и DATETIME к числовой форме (например, добавляя +0) зависит от того, содержит ли значение дробную часть секунд. TIME(N) или DATETIME(N) преобразован в целое число, когда N = 0 (или опущено) и в DECIMAL с N десятичных цифр, когда N больше 0:

mysql> SELECT CURTIME(), CURTIME()+0, CURTIME(3)+0;
+-----------+-------------+--------------+
| CURTIME() | CURTIME()+0 | CURTIME(3)+0 |
+-----------+-------------+--------------+
| 09:28:00  | 92800       | 92800.887    |
+-----------+-------------+--------------+

mysql> SELECT NOW(), NOW()+0, NOW(3)+0;
+---------------------+----------------+--------------------+
| NOW()               | NOW()+0        | NOW(3)+0           |
+---------------------+----------------+--------------------+
| 2012-08-15 09:28:00 | 20120815092800 | 20120815092800.889 |
+---------------------+----------------+--------------------+

12.3.8. Годы с двумя цифрами в датах

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

Для DATETIME, DATE и TIMESTAMP MySQL интерпретирует даты, определенные с неоднозначными значениями года, используя эти правила:

  • Год в диапазоне 00-69 преобразован в 2000-2069.

  • Год в диапазоне 70-99 преобразован в 1970-1999.

Для YEAR правила те же самые, с этим исключением: число 00, вставленное в YEAR(4) станет 0000, вместо 2000. Определить ноль для YEAR(4) и интерпретировать его как 2000 можно, указав строку '0' или '00'.

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

ORDER BY должным образом сортирует значения YEAR, у которых есть год с двумя цифрами.

Функции вроде MIN() и MAX() конвертирует YEAR к числу. Это означает, что значение с годом с двумя цифрами не работает должным образом с этими функциями. Затруднительное положение в этом случае должно преобразовать YEAR к формату года из четырех знаков.

12.4. Строковые типы

Строковые типы CHAR, VARCHAR, BINARY, VARBINARY, BLOB, TEXT, ENUM и SET. Этот раздел описывает, как эти типы работают и как использовать их в Ваших запросах. Для требований хранения строковых типов см. раздел 12.8.

12.4.1. Типы CHAR и VARCHAR

Типы CHAR и VARCHAR подобны, но отличаются по способу, которым они сохранены и получены. Они также отличаются по максимальной длине и по тому, сохранены ли конечные пробелы.

Типы CHAR и VARCHAR объявлены с длиной, которая указывает на максимальное количество символов, которые Вы хотите сохранить. Например, CHAR(30) может содержать до 30 символов.

Длина столбца CHAR установлена к длине, которую Вы объявляете, когда составляете таблицу. Длина может быть любым значением от 0 до 255. Когда значения CHAR сохранены, они дополнены справа пробелами к указанной длине. Когда значения CHAR получены, конечные пробелы не удалены, если включен режим SQL PAD_CHAR_TO_FULL_LENGTH.

Значения в столбцах VARCHAR строки переменной длины. Длина может быть определена как значение от 0 до 65535. Эффективная максимальная длина VARCHAR зависит от максимального размера строки (65535 байтов, которые совместно использованы всеми столбцами), и используемого набора символов. См. раздел C.10.4 .

В отличие от CHAR, значения VARCHAR сохранены как 1 или 2-байтовая приставка длины плюс данные. Приставка длины указывает на число байтов в значении. Столбец использует длину в один байт, если значения требуют не больше, чем 255 байтов, и два байта, если значения могут потребовать больше 255 байтов.

Если строгий режим SQL не включен, и Вы назначаете значение CHAR или VARCHAR, которое превышает максимальную длину столбца, значение является усеченным, чтобы соответствовать размеру, и предупреждение произведено. Для усечения непробелов Вы можете вызвать ошибку (а не предупреждение) и подавить вставку значения при использовании строгого режима SQL. См. раздел 6.1.8.

Для VARCHAR конечные пробелы сверх длины столбца усечены до вставки, и предупреждение произведено, независимо от режима SQL. Для CHAR усечение лишних конечных пробелов вставленных значений выполнено тихо, независимо от режима SQL.

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

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

ЗначениеCHAR(4) Необходимое место VARCHAR(4) Необходимое место
'''' 4 байта''1 байт
'ab''ab' 4 байта'ab'3 байта
'abcd''abcd' 4 байта'abcd'5 байт
'abcdefgh''abcd' 4 байта'abcd'5 байт

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

Для форматов строк COMPACT, DYNAMIC и COMPRESSED в InnoDB CHAR обработан как тип переменной длины, если длина значения столбца больше или равна 768 байтам, что может произойти, если максимальная длина байта набора символов больше 3, как с utf8mb4. Когда обработано как тип переменной длины, значение столбца CHAR может быть выбрано для хранения вне страницы. Для получения дополнительной информации см. раздел 16.10.

Если данное значение сохранено в столбцах CHAR(4) и VARCHAR(4), значения, полученные из столбцов, являются не всегда тем же самым, потому что конечные пробелы удалены из CHAR после извлечения. Следующий пример иллюстрирует это различие:

mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO vc VALUES ('ab', 'ab');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
+---------------------+---------------------+
| CONCAT('(', v, ')') | CONCAT('(', c, ')') |
+---------------------+---------------------+
| (ab)                | (ab)                |
+---------------------+---------------------+
1 row in set (0.06 sec)

Значения в CHAR и VARCHAR отсортированы и сравнены согласно сопоставлению набора символов, назначенному на столбец.

Все сопоставления MySQL имеют тип PADSPACE. Это означает, что все значения CHAR, VARCHAR и TEXT в MySQL сравнены без отношения с любыми конечными пробелами. В этом контексте сравнение не включает оператор LIKE , для которого конечные пробелы являются существенными. Например:

mysql> CREATE TABLE names (myname CHAR(10));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO names VALUES ('Monty');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT myname = 'Monty', myname = 'Monty' FROM names;
+------------------+------------------+
| myname = 'Monty' | myname = 'Monty' |
+------------------+------------------+
| 1                | 1                |
+------------------+------------------+
1 row in set (0.00 sec)

mysql> SELECT myname LIKE 'Monty', myname LIKE 'Monty' FROM names;
+---------------------+---------------------+
| myname LIKE 'Monty' | myname LIKE 'Monty' |
+---------------------+---------------------+
| 1                   | 0                   |
+---------------------+---------------------+
1 row in set (0.00 sec)

Это истина для всех версий MySQL, и не затронуто режимом SQL.

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

12.4.2. Типы BINARY и VARBINARY

Типы BINARY и VARBINARY похожи на CHAR и VARCHAR за исключением того, что они содержат двоичные строки. Таким образом, они содержат строки байт, а не символов. Это означает, что они имеют набор символов и сопоставление binary, а сравнение и сортировка основаны на числовых значениях байтов.

Допустимая максимальная длина та же самая для BINARY и VARBINARY, как для CHAR и VARCHAR, за исключением того, что длина для for BINARY и VARBINARY в байтах, а не в символах.

Типы BINARY и VARBINARY отличны от CHAR BINARY и VARCHAR BINARY. Для последних типов атрибут BINARY не заставляет столбец быть обработанным как двоичный строковый столбец. Вместо этого это вызывает двоичное (_bin) сопоставление для набора символов столбца, который будет использоваться, а сам столбец содержит недвоичные строки символов, а не двоичные строки байтов. Например, CHAR(5) BINARY обработан как CHAR(5) CHARACTER SET latin1 COLLATE latin1_bin, считая, что набор символов по умолчанию latin1. Это отличается от BINARY(5), который хранит 5-байтовые двоичные строки, которые имеют набор символов и сопоставление binary. Для информации о различиях между двоичными строками и двоичными сопоставлениями для недвоичных строк см. раздел 11.1.8.5.

Если строгий режим SQL не включен, и Вы назначаете значение столбцу BINARY или VARBINARY, которое превышает максимальную длину столбца, значение усечено, чтобы соответствовать, и предупреждение произведено. Для случаев усечения Вы можете вызвать ошибку (а не предупреждение) и подавить вставку значения при использовании строгого режима SQL. См. раздел 6.1.8.

Когда значения BINARY сохранены, они дополнены справа значением заполнителя до указанной длины. Значение заполнителя 0x00 (нулевой байт). Значения дополнены при вставке, и никакие байтах не удалены при получении. Все байты являются существенными в сравнениях, включая ORDER BY и DISTINCT. Байты 0x00 и пробелы отличаются в сравнениях, причем 0x00 < пробела.

Пример: Для столбца BINARY(3) 'a ' становится 'a \0', когда вставлено. 'a\0' становится 'a\0\0', когда вставлено. Оба вставленных значения остаются неизменными, когда выбраны.

Для столбца VARBINARY нет никакого дополнения на вставке, и никакие байты не отсекаются при выборке. Все байты являются существенными в сравнениях, включая ORDER BY и DISTINCT. Байты 0x00 и пробелы отличаются в сравнениях, 0x00 < пробела.

Для тех случаев, где байты дополнения отрезаны или сравнения игнорируют их, если у столбца будет индексирование, которое требует уникальных значений, вставляя в значения столбцов, которые отличаются только по числу байтов дополнения, это приведет к ошибке дубликата ключа. Например, если таблица содержит 'a', попытка сохранить 'a\0' вызывает ошибку дубликата ключа.

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

mysql> CREATE TABLE t (c BINARY(3));
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SET c = 'a';
Query OK, 1 row affected (0.01 sec)

mysql> SELECT HEX(c), c = 'a', c = 'a\0\0' from t;
+--------+---------+-------------+
| HEX(c) | c = 'a' | c = 'a\0\0' |
+--------+---------+-------------+
| 610000 | 0       | 1           |
+--------+---------+-------------+
1 row in set (0.09 sec)

Если полученное значение должно быть тем же самым, как значение, определенное для хранения без дополнения, может быть предпочтительно использовать VARBINARY или один из типов данных BLOB вместо этого.

12.4.3. Типы BLOB и TEXT

BLOB это binary large object, большой двоичный объект, который может содержать переменный объем данных. Есть четыре типа BLOB: TINYBLOB, BLOB, MEDIUMBLOB и LONGBLOB. Они отличаются только по максимальной длине значений, которые они могут содержать. Им соответствуют четыре типа TEXT: TINYTEXT, TEXT, MEDIUMTEXT и LONGTEXT. У них есть те же самые максимальные длины и требования хранения. См. раздел 12.8.

Значения BLOB обработаны как двоичные строки байтов. Они имеют набор символов и сопоставление binary, сравнение и сортировка основаны на числовых значениях байтов в значениях столбцов. Значения TEXT обработаны как недвоичные строки (строки символов). У них есть набор символов не binary, значения отсортированы и сравнены основывясь на сопоставлении набора символов.

Если строгий режим SQL не включен, и Вы назначаете значение на столбец BLOB или TEXT, которое превышает максимальную длину столбца, значение усечено, чтобы соответствовать размеру, и предупреждение произведено. Для усечения непробелов Вы можете вызвать ошибку (а не предупреждение) и подавить вставку значения при использовании строгого режима SQL. См. раздел 6.1.8.

Усечение лишних конечных пробелов от значений, которые будут вставлены в столбцы TEXT всегда производит предупреждение, независимо от режима SQL.

Для столбцов TEXT и BLOB нет никакого дополнения при вставке, и никакие байты не отрезаны при выборке.

Если TEXT индексирован, индексная запись сравнивается с пробелами в конце. Это означает, что, если индексирование требует уникальных значений, ошибка дубликата ключа произойдет для значений, которые отличаются только по числу конечных пробелов. Например, если таблица содержит 'a', попытка сохранить 'a ' вызывает ошибку дубликата ключа. Это не истина для столбцов BLOB.

В большинстве отношений Вы можете расценить BLOB как VARBINARY, который может быть столь большим, как Вам нравится. Точно так же Вы можете расценить TEXT как VARCHAR. BLOB и TEXT отличаются от VARBINARY и VARCHAR следующим:

  • Для индексов на BLOB и TEXT Вы должны определить длину префикса. Для CHAR и VARCHAR длина префикса является дополнительной. См. раздел 9.3.4.

  • BLOB и TEXT не могут иметь значения DEFAULT.

Если Вы используете признак BINARY с TEXT, столбцу назначают сопоставление _bin набора символов столбца.

LONG и LONG VARCHAR отобразятся на MEDIUMTEXT. Это особенность совместимости.

MySQL Connector/ODBC определяет значения BLOB как LONGVARBINARY, а TEXT как LONGVARCHAR.

Так как BLOB и TEXT могут быть чрезвычайно длинными, Вы можете столкнуться с некоторыми ограничениями в их использовании:

  • Только первые max_sort_length байт столбца используются, сортируя. Значение по умолчанию max_sort_length 1024. Вы можете сделать больше байтов существенными в сортировке или группировке, увеличивая значение max_sort_length. Любой клиент может изменить значение сеансовой переменной max_sort_length:

    mysql> SET max_sort_length = 2000;
    mysql> SELECT id, comment FROM t
        ->        ORDER BY comment;
    
  • Экземпляры столбцов BLOB или TEXT в результате запроса, который обработан, используя временную таблицу, заставляют сервер использовать таблицу на диске, а не в памяти потому, что механизм хранения MEMORY не поддерживает эти типы данных (см. раздел 9.4.4). Использование диска вносит накладные расходы по производительности, так что включение BLOB или TEXT в запрос, только если они действительно необходимы. Например, избегайте использования SELECT *, который выбирает все столбцы.
  • Максимальный размер BLOB или TEXT определен его типом, но самое большое значение, которое Вы фактически можете передать между клиентом и сервером, определено количеством доступной памяти и размером коммуникационных буферов. Вы можете изменить размер буфера сообщения, изменяя значение переменной max_allowed_packet , но Вы должны сделать так для сервера и для Вашей программы клиента. Например, mysql и mysqldump позволяют Вам изменить клиентское значение max_allowed_packet . См. разделы 6.1.1, 5.5.1 и 5.5.4. Вы можете также хотеть сравнить пакетные размеры и размер объектов данных, которые Вы храните, см. раздел 12.8.

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

В некоторых случаях может быть желательно сохранить двоичные данные, такие как медиа-файлы в BLOB или TEXT. Вы можете счесть строковые функции обработки MySQL полезными для работы с такими данными. См. раздел 13.5. Для безопасности и других причин, обычно предпочтительно использовать код программы вместо того, чтобы дать пользователям приложения привилегию FILE. Вы можете обсудить специфические особенности для различных языков и платформ на форумах MySQL ( http://forums.mysql.com/).

12.4.4. Тип ENUM

ENUM строковый объект со значением, выбранным из списка разрешенных значений, которые перечислены явно в спецификации столбца при создании таблицы. У этого есть преимущества:

  • Компактное хранение данных в ситуациях, где у столбца есть ограниченный набор возможных значений. Строки, которые Вы определяете как входные значения, автоматически закодированы как числа. См. раздел 12.8 для требований хранения для ENUM.

  • Читаемые запросы и вывод. Числа преобразованы назад в соответствующие строки в результатах запроса.

Обратите внимание на следующее:

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

  • Использование столбцов ENUM в ORDER BY требуют дополнительной заботы.

Создание и применение ENUM

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

CREATE TABLE shirts (name VARCHAR(40),
       size ENUM('x-small', 'small', 'medium', 'large', 'x-large'));
INSERT INTO shirts (name, size)
       VALUES ('dress shirt','large'), ('t-shirt','medium'),
              ('polo shirt','small');
SELECT name, size FROM shirts WHERE size = 'medium';
+---------+--------+
| name    | size   |
+---------+--------+
| t-shirt | medium |
+---------+--------+
UPDATE shirts SET size = 'small' WHERE size = 'large';
COMMIT;

Вставка 1 миллиона строк в эту таблицу со значением 'medium' потребовала бы 1 миллиона байтов хранения, в противоположность 6 миллионам байтов, если бы Вы сохранили фактическую строку 'medium' в столбец VARCHAR.

Значения индекса для литералов перечисления

У каждого значения перечисления есть индекс:

  • Элементы, перечисленные в спецификации столбца, являются назначенными индексами, начиная с 1.

  • Индексное значение пустой строки с ошибкой 0. Это означает, что Вы можете использовать следующий запрос, чтобы найти строки, в которых были назначены недопустимые значения ENUM:
    mysql> SELECT * FROM tbl_name
                       WHERE enum_col=0;
    
  • Индекс значения NULL NULL.
  • Термин index здесь относится к позиции в пределах списка значений перечисления. Это не имеет никакого отношения к индексу таблицы.

Например, столбец, определенный как ENUM('Mercury', 'Venus', 'Earth') может иметь любое из значений, показанных здесь. Индекс каждого значения также показывают.

ЗначениеValueИндекс
NULL NULL
''0
'Mercury'1
'Venus'2
'Earth'3

У столбца ENUM может быть максимум 65535 различных элементов.

Если Вы получаете значение ENUM в числовом контексте, возвращается индекс значения столбца. Например, Вы можете получить числовые значения из ENUM так:

mysql> SELECT enum_col+0 FROM tbl_name;

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

Обработка литералов перечисления

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

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

Если Вы храните число в ENUM, оно обработано как индекс в возможных значениях, и сохраненное значение является участником перечисления с этим индексом. Однако, это НЕ работает с LOAD DATA, который обрабатывает весь ввод как строки. Если числовое значение заключено в кавычки, оно все еще интерпретируется как индекс, если нет никакой строки соответствия в списке значений перечисления. По этим причинам нежелательно определить столбец ENUM со значениями перечисления, которые похожи на числа, потому что это может легко стать запутывающим. Например, у следующего столбца есть участники перечисления со строковыми значениями '0', '1' и '2', но числовые индексы значений 1, 2 и 3:

numbers ENUM('0','1','2')

Если Вы сохраните 2, это интерпретируется как индекс и получится '1' (значение с индексом 2). Если Вы сохраните '2', это соответствует значению перечисления, таким образом, это сохранено как '2'. Если Вы сохраните '3', это не соответствует значению перечисления, таким образом, это обработано как индекс и становится '2' (значение с индексом 3).

mysql> INSERT INTO t (numbers) VALUES(2),('2'),('3');
mysql> SELECT * FROM t;
+---------+
| numbers |
+---------+
| 1       |
| 2       |
| 2       |
+---------+

Определить все возможные значения для столбца ENUM можно с помощью SHOW COLUMNS FROM tbl_name LIKE 'enum_col' и просмотра определения ENUM в столбце Type вывода.

В C API значения ENUM возвращены как строки. Для информации об использовании метаданных о наборе результатов, чтобы отличить их от других строк, см. раздел 25.8.5.

Пустые или NULL значения перечисления

Значение перечисления может также быть пустой строкой ('') или NULL при определенных обстоятельствах:

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

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

  • Если столбец ENUM разрешает NULL, значение NULL допустимое значение для столбца, и значение по умолчанию NULL. Если столбец ENUM объявлен как NOT NULL , его значение по умолчанию первый элемент списка разрешенных значений.

Сортировка перечисления

Значения ENUM отсортированы, основываясь на их индексах, которые зависят от порядка, в котором участники перечисления были перечислены в спецификации столбца. Например, 'b' будет перед 'a' для ENUM('b', 'a'). Пустые строки будут перед непустыми строками, а NULL перед всеми другими значениями перечисления.

Предотвратить неожиданные результаты, используя ORDER BY на столбце ENUM можно так:

  • Определите список ENUM в алфавитном порядке.

  • Удостоверьтесь, что столбец сортирован лексически, а не индексом, кодируя ORDER BY CAST(col AS CHAR) или ORDER BY CONCAT(col).

Ограничения перечисления

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

Например, CREATE TABLE НЕ работает, потому что CONCAT не может использоваться, чтобы создать значение перечисления:

CREATE TABLE sizes (size ENUM('small', CONCAT('med','ium'), 'large'));

Вы также не можете использовать пользовательскую переменную как значение перечисления. Эта пара запросов НЕ работает:

SET @mysize = 'medium';
CREATE TABLE sizes (size ENUM('small', @mysize, 'large'));

Мы сильно рекомендуем, чтобы Вы НЕ использовали числа как значения перечисления, потому что это не экономит на хранении по сравнении с соответствующим типом TINYINT или SMALLINT, зато легко перепутать строки и основные значения числа (которые могут не быть тем же самым), если Вы заключаете в кавычки значения ENUM неправильно. Если Вы действительно используете число в качестве значения перечисления, всегда задавайте это в кавычках. Если кавычки опущены, число расценено как индекс.

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

12.4.5. Тип SET

SET строковый объект, у которого может быть ноль или больше значений, каждое из которых должно быть выбрано из списка разрешенных значений, определенных, когда таблица составлена. Значения столбцов SET, которые состоят из многих участников набора, определены перечнем участников, отделенных запятыми (,). Последствие этого: членские значения SET не должны сами содержать запятые.

Например, столбец, определенный как SET('one', 'two') NOT NULL может иметь любое из этих значений:

''
'one'
'two'
'one,two'

У столбца SET может быть максимум 64 различных участника.

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

Конечные пробелы автоматически удалены из членов SET в табличном определении, когда таблица составлена.

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

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

mysql> SELECT set_col+0 FROM tbl_name;

Если число сохранено в столбец SET, биты, которые установлены в двоичном представлении числа, определяют участников набора в значении столбца. Для столбца, определенного как SET('a','b','c','d'), у участников есть следующие десятичные и двоичные значения:

Член SET Десятичное значениеДвоичное значение
'a'1 0001
'b'2 0010
'c'4 0100
'd'8 1000

Если Вы назначаете значение 9 этому столбцу, оно является 1001 в двоичном виде, таким образом, первый и четвертый члены SET 'a' и 'd' выбраны и получающееся значение 'a,d'.

Для значения, содержащего больше чем один элемент SET, не имеет значения порядок их перечисления. Также не имеет значения, сколько раз данный элемент перечислен в значении. Когда значение получено позже, каждый элемент в значении появляется однажды, с элементами, перечисленными согласно порядку, в котором они были определены в табличном определении. Например, предположите, что столбец определен как SET('a','b','c','d'):

mysql> CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));

Если Вы вставляете значения 'a,d', 'd,a', 'a,d,d', 'a,d,a' и 'd,a,d':

mysql> INSERT INTO myset (col) VALUES
    ->        ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0

Тогда все эти значения появляются как 'a,d':

mysql> SELECT col FROM myset;
+------+
| col  |
+------+
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
+------+
5 rows in set (0.04 sec)

Если Вы устанавливаете столбец SET к неподдержанному значению, значение проигнорировано, и предупреждение создано:

mysql> INSERT INTO myset (col) VALUES ('a,d,d,s');
Query OK, 1 row affected, 1 warning (0.03 sec)

mysql> SHOW WARNINGS;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column 'col' at row 1 |
+---------+------+------------------------------------------+
1 row in set (0.04 sec)

mysql> SELECT col FROM myset;
+------+
| col  |
+------+
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
+------+
6 rows in set (0.01 sec)

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

Значения SET отсортированы в цифровой форме. NULL будет перед не-NULL членами SET.

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

Обычно Вы ищете значения SET, используя функцию FIND_IN_SET() или оператор LIKE:

mysql> SELECT * FROM tbl_name WHERE
                   FIND_IN_SET('value', set_col) >0;
mysql> SELECT * FROM tbl_name WHERE
                   set_col LIKE '%value%';

Первый запрос находит строки, где set_col содержит участника набора value. Второй подобен, но не то же самое: находит строки, где set_col содержит value где угодно, как подстроку другого участника набора.

Следующие запросы также разрешены:

mysql> SELECT * FROM tbl_name WHERE
                   set_col & 1;
mysql> SELECT * FROM tbl_name WHERE
                   set_col = 'val1, val2';

Первый из этих запросов ищет значения, содержащие первого участника набора. Второй ищет точное совпадение. Будьте осторожны со сравнениями второго типа. Сравнение набора оценивая 'val1,val2' возвращает различные результаты, чем сравнение значений 'val2,val1'. Вы должны определить значения в том же самом порядке, в каком они перечислены в определении столбца.

Определить все возможные значения для SET можно, применив SHOW COLUMNS FROM tbl_name LIKE set_col и изучив определение SET в столбце Type вывода.

В C API значения SET возвращены как строки. Для информации об использовании метаданных о наборе результатов, чтобы отличить их от других строк, см. раздел 25.8.5.

12.5. Расширения для пространственных данных

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

Open Geospatial Consortium издает OpenGIS Implementation Standard for Geographic information - Simple feature access - Part 2: SQL option, документ, который предлагает несколько концептуальных путей к распространению SQL RDBMS, чтобы поддержать пространственные данные. Эта спецификация доступна с OGC Web site http://www.opengeospatial.org/standards/sfs.

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

Пространственные расширения MySQL включают производство, хранение и анализ географических особенностей:

  • Типы данных для того, чтобы представить пространственные значения.

  • Функции для того, чтобы управлять пространственными значениями.
  • Пространственная индексация для улучшения времени доступа к пространственным столбцам.

Типы данных и функции доступны для таблиц MyISAM, InnoDB и ARCHIVE. Для того, чтобы индексировать пространственные столбцы, MyISAM и InnoDB поддерживают индексы SPATIAL и не-SPATIAL. Другие механизмы хранения поддерживают не-SPATIAL индексы, как описано в раздел 14.1.12.

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

  • Объект. Например, гора, водоем, город.

  • Пространство. Например, городской район, тропики.
  • Определимое местоположение. Например, перекресток, как особое место, где две улицы пересекаются.

Некоторые документы используют термин geospatial feature, чтобы обратиться к географическим особенностям.

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

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

Следующий материал затрагивает эти темы:

  • Пространственные типы данных осуществлены в модели MySQL.

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

Соответствие и совместимость MySQL GIS

MySQL не реализует следующие опции GIS:

  • Дополнительные представления метаданных.

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

  • Функция OpenGIS Length() на LineString и MultiLineString должна быть вызвана в MySQL как ST_Length().

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

Дополнительные ресурсы

  • The Open Geospatial Consortium издает OpenGIS Implementation Standard for Geographic information - Simple feature access - Part 2: SQL option, документ, который предлагает несколько концептуальных путей к распространению SQL RDBMS, чтобы поддержать пространственные данные. The Open Geospatial Consortium (OGC) поддерживает Web-сайт http://www.opengeospatial.org/. Спецификация доступна там на http://www.opengeospatial.org/standards/sfs. Это содержит дополнительную информацию, относящуюся к материалам здесь.

  • Если у Вас есть вопросы или проблемы по поводу использования пространственных расширений MySQL, Вы можете обсудить их на форуме GIS: http://forums.mysql.com/list.php?23.

12.5.1. Пространственные типы данных

У MySQL есть типы данных, которые соответствуют классам OpenGIS. Некоторые из этих типов содержат единственные значения геометрии:

  • GEOMETRY

  • POINT
  • LINESTRING
  • POLYGON

GEOMETRY может сохранить значения геометрии любого типа. Другие типы единственного значения (POINT, LINESTRING и POLYGON) ограничивают их значения особым типом геометрии.

Другие типы данных содержат наборы значений:

  • MULTIPOINT

  • MULTILINESTRING
  • MULTIPOLYGON
  • GEOMETRYCOLLECTION

GEOMETRYCOLLECTION может сохранить набор объектов любого типа. Другие типы (MULTIPOINT, MULTILINESTRING, MULTIPOLYGON и GEOMETRYCOLLECTION) ограничивают участников набора теми, которые имеют особый тип геометрии.

У пространственных типов данных MySQL есть своя основа в модели геометрии OpenGIS, описанной в разделе 12.5.2. Для примеров, показывающих, как использовать пространственные типы данных в MySQL, см. раздел 12.5.3.

12.5.2. Модель геометрии OpenGIS

Набор типов геометрии, предложенных OGC's SQL with Geometry Types, основан на OpenGIS Geometry Model. В этой модели у каждого геометрического объекта есть следующие общие свойства:

  • Это связано с пространственной ссылочной системой, которая описывает координатное пространство, в котором определен объект.

  • Это принадлежит некоторому классу геометрии.

12.5.2.1. Иерархия классов геометрии

Классы геометрии определяют иерархию следующим образом:

  • Geometry (noninstantiable)

    • Point (instantiable)

    • Curve (noninstantiable)

      • LineString (instantiable)

        • Line

        • LinearRing

    • Surface (noninstantiable)

      • Polygon (instantiable)

    • GeometryCollection (instantiable)

      • MultiPoint (instantiable)

      • MultiCurve (noninstantiable)

        • MultiLineString (instantiable)

      • MultiSurface (noninstantiable)

        • MultiPolygon (instantiable)

Невозможно создать объекты в noninstantiable классах. Возможно создать объекты в instantiable классах. У всех классов есть свойства, у instantiable классов могут также быть утверждения (правила, которые определяют допустимые экземпляры класса).

Geometry базовый класс. Это абстрактный класс. instantiable подклассы Geometry ограничены 0, 1 и 2-мерными геометрическими объектами, которые существуют в двумерном координатном пространстве. Все instantiable классы геометрии определены так, чтобы допустимые экземпляры класса геометрии были топологически закрыты (то есть, все определенные конфигурации включают свою границу).

У базового класса Geometry есть подклассы для Point, Curve, Surface и GeometryCollection:

  • Point представляет нуль-мерные объекты.

  • Curve представляет одномерные объекты и имеет подкласс LineString с подподклассами Line и LinearRing.
  • Surface разработан для двумерных объектов и имеет подкласс Polygon.
  • GeometryCollection имеет специальные ноль-, одно- и двумерные классы набора, названные MultiPoint, MultiLineString и MultiPolygon для того, чтобы смоделировать конфигурации, соответствующие наборам Points, LineStrings и Polygons, соответственно. MultiCurve и MultiSurface введены как абстрактные суперклассы, которые обобщают интерфейсы набора, чтобы обработать Curves и Surfaces.

Geometry, Curve, Surface, MultiCurve и MultiSurface определены как noninstantiable классы. Они определяют единый набор методов для их подклассов и включены для расширяемости.

Point, LineString, Polygon, GeometryCollection, MultiPoint, MultiLineString и MultiPolygon instantiable классы.

12.5.2.2. Класс геометрии

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

Свойства геометрии

У значения геометрии есть следующие свойства:

  • Его тип. Каждая геометрия принадлежит одному из instantiable классов в иерархии.

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

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

  • Его координаты в его пространственной ссылочной системе, представленной как числа двойной точности (8 байтов). Все непустые конфигурации включают по крайней мере одну пару (X,Y) координат. Пустые конфигурации не содержат координат.

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

  • Ее интерьер, граница и внешность.

    Каждая геометрия занимает некоторую позицию в пространстве. Внешность геометрии все место, не занятое геометрией. Интерьер место, занятое геометрией. Граница интерфейс между интерьером геометрии и внешностью.

  • Его MBR (минимальный ограничительный прямоугольник) или конверт. Это геометрия ограничения, сформированная минимумом и максимумом (X, Y) координат:
    ((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
    
  • Значение простое или непростое. Значения геометрии типов (LineString, MultiPoint, MultiLineString) просты или непросты. Каждый тип определяет свои собственные утверждения для того, чтобы быть простым или непростым.
  • Закрыто ли значение или не закрыто. Значения геометрии типов (LineString, MultiString) закрыты или не закрыты. Каждый тип определяет свои собственные утверждения для того, чтобы быть закрытым или не закрытым.
  • Пусто значение или непусто, геометрия пуста, если у нее нет никаких пунктов. Внешность, интерьер и граница пустой геометрии не определены (то есть, они представлены значением NULL). Пустая геометрия определена, чтобы быть всегда простой и имеет область 0.
  • Его измерение. У геометрии может быть измерение -1, 0, 1 или 2:

    • -1 для пустой геометрии.

    • 0 для геометрии без длины и области.
    • 1 для геометрии с длиной отличной от нуля и нулевой областью.
    • 2 для геометрии с областью отличной от нуля.

    Объекты Point имеют измерение 0. У объектов LineString есть измерение 1. У объектов Polygon есть измерение 2. Измерения объектов MultiPoint, MultiLineString и MultiPolygon такие же, как измерения элементов, из которых они состоят.

12.5.2.3. Класс Point

Point геометрия, которая представляет единственное местоположение в координатном пространстве.

Примеры Point:

  • Вообразите крупномасштабную карту мира со многими городами. Объект Point может представить каждый город.

  • На городской карте объект Point может представить автобусную остановку.

Свойства Point:

  • Значение X-координаты.

  • Значение Y-координаты.
  • Point определен как 0-мерная геометрия.
  • Граница a Point пустой набор.

12.5.2.4. Класс Curve

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

Свойства Curve:

  • Curve имеет координаты его пунктов.

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

12.5.2.5. Класс LineString

LineString это Curve с линейной интерполяцией между пунктами.

Примеры LineString:

  • На мировой карте объекты LineString могут представить реки.

  • В городской карте объекты LineString могут представить улицы.

Свойства LineString:

  • LineString имеет координаты сегментов, определенных каждой последовательной парой пунктов.

  • LineString это Line, если это состоит точно из двух пунктов.
  • LineString это LinearRing, если это закрыто и просто.

12.5.2.6. Класс Surface

Surface двумерная геометрия. Это noninstantiable класс. Его единственный instantiable подкласс Polygon.

Свойства Surface:

  • Surface определен как двумерная геометрия.

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

12.5.2.7. Класс Polygon

Polygon это плоское представление Surface мультипримкнутой геометрии. Это определено единственной внешней границей и нолем или большим количеством внутренних границ, где каждая внутренняя граница определяет отверстие в Polygon.

Примеры Polygon:

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

Утверждения Polygon:

  • Граница Polygon состоит из ряда объектов LinearRing (то есть, объектов LineString, которые просты и закрыты), которые составляют его внешние и внутренние границы.

  • Polygon не имеет никаких колец, которые пересекаются. Кольца в границе Polygon могут пересечься в Point, но только как тангенс.
  • Polygon не имеет никаких линий, шипов или проколов.
  • Polygon имеет интерьер, который является соединенным набором пунктов.
  • Polygon может иметь отверстия. Внешность Polygon с отверстиями не соединена. Каждое отверстие определяет соединенный компонент внешности.

Предыдущие утверждения делают Polygon простой геометрией.

12.5.2.8. Класс GeometryCollection

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

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

  • Тип элемента (например, MultiPoint может содержать только Point).

  • Измерение.
  • Ограничения на степень пространственного перекрытия между элементами.

12.5.2.9. Класс MultiPoint

MultiPoint набор геометрии, составленный из Point. Пункты не соединены или упорядочены в любом случае.

Примеры MultiPoint:

  • На мировой карте MultiPoint может представить цепочку небольших островов.

  • На городской карте MultiPoint может представить билетные кассы.

Свойства MultiPoint:

  • MultiPoint геометрия 0-мерная.

  • MultiPoint просто, если никакие два Point не равны (имеют идентичные координатные значения).
  • Граница MultiPoint пустой набор.

12.5.2.10. Класс MultiCurve

MultiCurve набор геометрии, составленный из Curve. MultiCurve noninstantiable класс.

Свойства MultiCurve:

  • MultiCurve одномерная геометрия.

  • MultiCurve просто, если и только если все его элементы просты: единственные пересечения между любыми двумя элементами происходят в пунктах, которые находятся на границах обоих элементов.
  • Граница MultiCurve получена, применяя mod 2 union rule (также известно как odd-even rule ): пункт находится в границе MultiCurve, если это находится в границах нечетного числа элементов Curve.
  • MultiCurve закрыт, если все его элементы закрыты.
  • Граница закрытого MultiCurve всегда пуста.

12.5.2.11. Класс MultiLineString

MultiLineString это набор геометрии MultiCurve из элементов LineString.

Примеры MultiLineString:

  • На карте области MultiLineString может представить речную или магистральную систему.

12.5.2.12. Класс MultiSurface

MultiSurface набор геометрии, составленный из поверхностных элементов. MultiSurface noninstantiable класс. Его единственный instantiable подкласс MultiPolygon.

Утверждения MultiSurface:

  • Поверхности в пределах MultiSurface не имеют никаких интерьеров, которые пересекаются.

  • Поверхности в пределах MultiSurface имеют границы, которые пересекаются самое большее в конечном числе точек.

12.5.2.13. Класс MultiPolygon

MultiPolygon это объект MultiSurface из элементов Polygon.

Примеры MultiPolygon:

  • На карте области MultiPolygon может представить систему озер.

Утверждения MultiPolygon:

  • MultiPolygon не имеет никаких двух элементов Polygon с интерьерами, которые пересекаются.

  • MultiPolygon не имеет никаких двух элементов Polygon, которые пересекаются (пересечение также запрещено предыдущим утверждением), или которые заходят в бесконечное число пунктов.
  • MultiPolygon возможно, не сократил строки, шипы или проколы. MultiPolygon закрытый набор пунктов.
  • MultiPolygon имеет больше одного Polygon, имеющий интерьер, который не соединен. Число соединенных компонентов интерьера MultiPolygon равно числу значений Polygon values in the в MultiPolygon.

Свойства MultiPolygon:

  • У MultiPolygon двумерная геометрия.

  • Граница MultiPolygon ряд закрытых кривых (значения LineString), соответствующих границам элементов Polygon .
  • Каждый Curve в границе MultiPolygon находится в границе точно одного Polygon.
  • Каждый Curve в границе Polygon находится в границе MultiPolygon.

12.5.3. Использование пространственных данных

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

12.5.3.1. Поддержанные пространственные форматы данных/h4>

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

  • Well-Known Text (WKT).

  • Well-Known Binary (WKB).

Внутренне MySQL хранит значения геометрии в формате, который не идентичен ни одному из них.

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

12.5.3.1.1. Формат Well-Known Text (WKT)

Well-Known Text (WKT) разработан для того, чтобы обменяться информациями геометрии в форме ASCII. Спецификация OpenGIS обеспечивает грамматику Backus-Naur, которая определяет формальные производственные правила для того, чтобы написать значения WKT (см. раздел 12.5).

Примеры представлений WKT объектов геометрии:

  • Point:

    POINT(15 20)
    

    Координаты пункта определены без отделения запятой. Это отличается от синтаксиса для функции SQL Point() , которая требует запятой между координатами. Заботьтесь, чтобы использовать синтаксис, соответствующий контексту данной пространственной работы. Например, следующие запросы оба извлекают X-координату из Point. Первый вернет объект, непосредственно используя функцию Point(). Второй применит представление WKT, преобразованное в Point через GeomFromText().

    mysql> SELECT ST_X(Point(15, 20));
    +---------------------+
    | ST_X(POINT(15, 20)) |
    +---------------------+
    | 15                  |
    +---------------------+
    
    mysql> SELECT ST_X(ST_GeomFromText('POINT(15 20)'));
    +---------------------------------------+
    | ST_X(ST_GeomFromText('POINT(15 20)')) |
    +---------------------------------------+
    | 15                                    |
    +---------------------------------------+
    
  • LineString с четырьмя пунктами:

    LINESTRING(0 0, 10 10, 20 25, 50 60)
    

    Пары координат пунктов отделены запятыми.

  • Polygon с одним внешним и одним внутренним кольцом:
    POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))
    
  • MultiPoint с тремя Point:
    MULTIPOINT(0 0, 20 20, 60 60)
    

    В MySQL 8.0 такие пространственные функции, как ST_MPointFromText() и ST_GeomFromText(), принимая представленные в WKT-формате значения MultiPoint, разрешают отдельным пунктам в пределах значений быть окруженными круглыми скобками. Например, оба из следующих вызовов функции допустимы:

    ST_MPointFromText('MULTIPOINT (1 1, 2 2, 3 3)')
    ST_MPointFromText('MULTIPOINT ((1 1), (2 2), (3 3))')
    
  • MultiLineString с двумя LineString:
    MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
    
  • MultiPolygon с двумя Polygon:
    MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
    
  • GeometryCollection состоящая из двух Point и одного LineString:
    GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
    
12.5.3.1.2. Формат Well-Known Binary (WKB)

Well-Known Binary (WKB) используется для того, чтобы обменяться информациями геометрии как двоичными потоками, представленными значениями BLOB, содержащими геометрическую информацию WKB. Этот формат определен спецификацией OpenGIS (см. раздел 12.5). Это также определено в ISO SQL/MM Part 3: Spatial.

WKB использует 1-байтовые unsigned integer, 4-байтовые unsigned integer и 8-байтовые числа двойной точности (формат IEEE 754). Байт составляет восемь битов.

Например, значение WKB, которое соответствует POINT(1 1) состоит из этой последовательности 21 байта, каждый представлен двумя шестнадцатеричными цифрами:

0101000000000000000000F03F000000000000F03F

Последовательность состоит из этих компонентов:

Byte order: 01
WKB type: 01000000
X coordinate: 000000000000F03F
Y coordinate: 000000000000F03F

Составляющее представление следующие:

  • Порядок байтов 1 или 0, чтобы указать тип хранения little-endian или big-endian. Типы хранения также известны как Network Data Representation (NDR) и External Data Representation (XDR), соответственно.

  • Тип WKB код, который указывает на тип геометрии. Значения от 1 до 7 указывают Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon и GeometryCollection.
  • Значение Point имеет координаты X и Y, каждая представлена как значение двойной точности.

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

12.5.3.2. Создание пространственных столбцов

MySQL обеспечивает стандартный способ создать пространственные столбцы для типов геометрии, например, с CREATE TABLE или ALTER TABLE . Пространственные столбцы поддержаны для таблиц MyISAM, InnoDB, NDB и ARCHIVE.

  • Используйте CREATE TABLE , чтобы составить таблицу с пространственным столбцом:

    CREATE TABLE geom (g GEOMETRY);
    
  • Используйте ALTER TABLE, чтобы добавить или удалить пространственный столбец существующей таблицы:
    ALTER TABLE geom ADD pt POINT;
    ALTER TABLE geom DROP pt;
    

12.5.3.3. Заполнение пространственных столбцов

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

Значения должны быть сохранены во внутреннем формате геометрии, но Вы можете преобразовать их в этот формат из Well-Known Text (WKT) или Well-Known Binary (WKB). Следующие примеры демонстрируют, как вставить значения геометрии в таблицу, преобразовывая значения WKT во внутренний формат геометрии:

  • Выполните преобразование непосредственно в INSERT:

    INSERT INTO geom VALUES (ST_GeomFromText('POINT(1 1)'));
    SET @g = 'POINT(1 1)';
    INSERT INTO geom VALUES (ST_GeomFromText(@g));
    
  • Выполните преобразование до INSERT:
    SET @g = ST_GeomFromText('POINT(1 1)');
    INSERT INTO geom VALUES (@g);
    

Следующие примеры вставляют более сложные конфигурации в таблицу:

SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

Предыдущее использование в качестве примера ST_GeomFromText() . Вы можете также использовать определенные для типа функции:

SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_PointFromText(@g));

SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_LineStringFromText(@g));

SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (ST_PolygonFromText(@g));

SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomCollFromText(@g));

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

  • Вставить значение POINT(1 1) с шестнадцатеричным литералом:

    mysql> INSERT INTO geom VALUES
        -> (ST_GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));
    
  • Приложение ODBC может послать представление WKB, связывая это с заполнителем, используя параметр типа BLOB :
    INSERT INTO geom VALUES (ST_GeomFromWKB(?))
    

    Другие программные интерфейсы могут поддержать подобный механизм заполнителя.

  • В программе на C Вы можете экранировать двоичное значение, применив mysql_real_escape_string_quote() и включив результат в строку запроса, которую посылают в сервер. См. раздел 25.8.7.56.

12.5.3.4. Установка пространственных данных

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

  • Установка пространственных данных во внутреннем формате:

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

    CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;
    
  • Установка пространственных данных в формате WKT:

    Функция ST_AsText() преобразовывает геометрию из внутреннего формата в строку WKT.

    SELECT ST_AsText(g) FROM geom;
    
  • Установка пространственных данных в формате WKB:

    Функция ST_AsBinary() преобразовывает геометрию из внутреннего формата в WKB BLOB.

    SELECT ST_AsBinary(g) FROM geom;
    

12.5.3.5. Оптимизация пространственного анализа

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

  • Запросы пункта, которые ищут все объекты, которые содержат данный пункт.

  • Запросы области, которые ищут все объекты, которые перекрывают данную область.

MySQL использует R-Trees с квадратным разделением для индексов SPATIAL на пространственных столбцах. Индекс SPATIAL создан, используя минимальный ограничительный прямоугольник (MBR) геометрии. Для большинства конфигураций MBR минимальный прямоугольник, который окружает конфигурации. Для горизонтального или вертикального linestring MBR прямоугольник, деградировавший в linestring. Для point MBR прямоугольник, деградировавший в point.

Также возможно создать нормальный индекс на пространственных столбцах. В не-SPATIAL индексе Вы должны объявить префикс для любого пространственного столбца за исключением POINT.

MyISAM и InnoDB поддерживают индексы SPATIAL и не-SPATIAL. Другие механизмы хранения поддерживают индексы не-SPATIAL, как описано в раздел 14.1.12.

12.5.3.6. Пространственное создание индексов

Для таблиц MyISAM и InnoDB MySQL может создать пространственный индекс, используя синтаксис, подобный этому для того, чтобы создать регулярный индекс, но применяя ключевое слово SPATIAL. Столбцы в пространственном индексе должны быть объявлены NOT NULL. Следующие примеры демонстрируют, как создать пространственный индекс:

  • С CREATE TABLE:

    CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;
    
  • С ALTER TABLE:
    ALTER TABLE geom ADD SPATIAL INDEX(g);
    
  • С CREATE INDEX:
    CREATE SPATIAL INDEX sp_index ON geom (g);
    

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

Чтобы удалить пространственный индекс, надо использовать ALTER TABLE или DROP INDEX:

Пример: Предположите что таблица geom содержит больше 32000 конфигураций, которые сохранены в столбце g типа GEOMETRY. Таблица также имеет AUTO_INCREMENT столбец fid для того, чтобы сохранить значения идентификаторов объекта.

mysql> DESCRIBE geom;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| fid   | int(11)  |      | PRI | NULL    | auto_increment |
| g     | geometry |      |     |         |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> SELECT COUNT(*) FROM geom;
+----------+
| count(*) |
+----------+
| 32376    |
+----------+
1 row in set (0.00 sec)

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

mysql> ALTER TABLE geom ADD SPATIAL INDEX(g) ENGINE=MyISAM;
Query OK, 32376 rows affected (4.05 sec)
Records: 32376 Duplicates: 0 Warnings: 0

12.5.3.7. Использование пространственного индекса

Оптимизатор занимается расследованиями, может ли доступный пространственный индекс быть вовлечен в поиск запросов, которые используют такую функцию, как MBRContains() или MBRWithin() в предложении WHERE. Следующий запрос находит все объекты, которые находятся в данном прямоугольнике:

mysql> SET @poly =
    -> 'Polygon((30000 15000, 31000 15000, 31000 16000, 30000 16000,
                    30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom WHERE
    ->        MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g)                                                  |
+-----+---------------------------------------------------------------+
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... |
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.00 sec)

Используйте EXPLAIN, чтобы проверить путь, которым этот запрос выполнен:

mysql> SET @poly =
    -> 'Polygon((30000 15000, 31000 15000, 31000 16000,
                    30000 16000, 30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM geom WHERE
    ->         MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1. row ***************************
 id: 1
select_type: SIMPLE
table: geom
 type: range
possible_keys: g
key: g
key_len: 32
ref: NULL
 rows: 50
Extra: Using where
1 row in set (0.00 sec)

Проверьте то, что произошло бы без пространственного индекса:

mysql> SET @poly =
    -> 'Polygon((30000 15000, 31000 15000, 31000 16000,
                    30000 16000, 30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM g IGNORE INDEX (g) WHERE
    ->         MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1. row ***************************
 id: 1
select_type: SIMPLE
table: geom
 type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
 rows: 32376
Extra: Using where
1 row in set (0.00 sec)

Выполнение SELECT без пространственного индекса выдаст тот же самый результат, но время выполнения повышается с 0.00 до 0.46 секунды:

mysql> SET @poly =
    -> 'Polygon((30000 15000, 31000 15000, 31000 16000,
                    30000 16000, 30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom IGNORE INDEX (g) WHERE
    ->        MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g)                                                  |
+-----+---------------------------------------------------------------+
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.46 sec)

12.6. Тип данных JSON

MySQL поддерживает тип данных JSON, который включает эффективный доступ к данным в документах JSON (JavaScript Object Notation). Тип данных JSON обеспечивает эти преимущества перед хранением строк JSON-формата в строковом столбце:

  • Автоматическая проверка допустимости документов JSON в столбцах JSON. Недопустимые документы производят ошибку.

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

Размер документов JSON в столбцах JSON ограничен значением переменной max_allowed_packet. В то время, как сервер управляет значением JSON внутренне в памяти, это может быть больше: предел применяется, когда сервер хранит его.

Столбцы JSON не могут иметь значения по умолчанию.

Столбцы JSON, как столбцы других двоичных типов, не индексированы непосредственно: вместо этого, Вы можете создать индекс на произведенном столбце, который извлекает скалярное значение из JSON. См. раздел 14.1.15.6.

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

Следующее обсуждение затрагивает эти темы:

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

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

Создание значений JSON

Массив JSON содержит список значений, отделенных запятыми и приложенный в пределах символов [ и ]:

["abc", 10, null, true, false]

Объект JSON содержит ряд пар ключа/значения, отделенных запятыми и приложенный в пределах символов { и }:

{"k1": "value", "k2": 10}

Массивы и объекты JSON могут содержать скалярные значения, которые являются строками или числами, литералом JSON null или литералами JSON boolean true или false. Ключи в объектах JSON должны быть строками. Временные (date, time или datetime) скалярные значения также разрешены:

["12:18:29.000000", "2015-07-29", "2015-07-29 12:18:29.000000"]

Вложение разрешено в пределах элементов массива и значений ключа объекта JSON:

[99, {"id": "HK500", "cost": 75.99}, ["hot", "cold"]]
{"k1": "value", "k2": [10, 20]}

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

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

  • Попытка вставить значение в столбец JSON преуспевает, если значение допустимое значение JSON, но терпит неудачу, если это не так:

    mysql> CREATE TABLE t1 (jdoc JSON);
    Query OK, 0 rows affected (0.20 sec)
    
    mysql> INSERT INTO t1 VALUES('{"key1": "value1", "key2": "value2"}');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> INSERT INTO t1 VALUES('[1, 2,');
    ERROR 3140 (22032) at line 2: Invalid JSON text: "Invalid value."
    at position 6 in value (or column) '[1, 2,'.
    

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

  • Функция JSON_TYPE() ожидает параметр JSON и попытается разобрать это в значение JSON. Это возвращает значение типа JSON, если это допустимо и производит ошибку иначе:
    mysql> SELECT JSON_TYPE('["a", "b", 1]');
    +----------------------------+
    | JSON_TYPE('["a", "b", 1]') |
    +----------------------------+
    | ARRAY                      |
    +----------------------------+
    
    mysql> SELECT JSON_TYPE('"hello"');
    +----------------------+
    | JSON_TYPE('"hello"') |
    +----------------------+
    | STRING               |
    +----------------------+
    
    mysql> SELECT JSON_TYPE('hello');
    ERROR 3146 (22032): Invalid data type for JSON data in argument 1
    to function json_type; a JSON string or JSON type is required.
    

MySQL обрабатывает строки, используемые в контексте JSON, используя набор символов utf8mb4 и сопоставление utf8mb4_bin. Строки в других наборах символов преобразованы в utf8mb4 по мере необходимости. Для строк в наборах символов ascii или utf8 никакое преобразование не необходимо потому, что ascii и utf8 подмножества utf8mb4.

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

mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW())|
+----------------------------------------+
| ["a", 1, "2015-07-27 09:43:47.000000"] |
+----------------------------------------+

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

mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc');
+---------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc') |
+---------------------------------------+
| {"key1": 1, "key2": "abc"}|
+---------------------------------------+

JSON_MERGE() берет два или больше документа JSON и возвращает объединенный результат:

mysql> SELECT JSON_MERGE('["a", 1]', '{"key": "value"}');
+--------------------------------------------+
| JSON_MERGE('["a", 1]', '{"key": "value"}') |
+--------------------------------------------+
| ["a", 1, {"key": "value"}]                 |
+--------------------------------------------+

Значения JSON могут быть назначены на определяемые пользователем переменные:

mysql> SET @j = JSON_OBJECT('key', 'value');
mysql> SELECT @j;
+------------------+
| @j               |
+------------------+
| {"key": "value"} |
+------------------+

Однако, определяемые пользователем переменные не могут иметь тип JSON, так хотя @j в предыдущем примере похоже на значение JSON и имеет тот же самый набор символов и сопоставление как значение JSON, это НЕ имеет тип данных JSON. Вместо этого результат JSON_OBJECT() преобразован в строку, когда назначен переменной.

У строк, произведенных, преобразовывая значения JSON, есть набор символов utf8mb4 и сопоставление utf8mb4_bin:

mysql> SELECT CHARSET(@j), COLLATION(@j);
+-------------+---------------+
| CHARSET(@j) | COLLATION(@j) |
+-------------+---------------+
| utf8mb4     | utf8mb4_bin   |
+-------------+---------------+

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

mysql> SELECT JSON_ARRAY('x') = JSON_ARRAY('X');
+-----------------------------------+
| JSON_ARRAY('x') = JSON_ARRAY('X') |
+-----------------------------------+
| 0                                 |
+-----------------------------------+

Чувствительность к регистру также относится к литералам JSON null, true и false, которые всегда должны писаться в нижнем регистре:

mysql> SELECT JSON_VALID('null'), JSON_VALID('Null'), JSON_VALID('NULL');
+--------------------+--------------------+--------------------+
| JSON_VALID('null') | JSON_VALID('Null') | JSON_VALID('NULL') |
+--------------------+--------------------+--------------------+
| 1                  | 0                  | 0                  |
+--------------------+--------------------+--------------------+

mysql> SELECT CAST('null' AS JSON);
+----------------------+
| CAST('null' AS JSON) |
+----------------------+
| null                 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT CAST('NULL' AS JSON);
ERROR 3141 (22032): Invalid JSON text in argument 1 to function
cast_as_json: "Invalid value." at position 0 in 'NULL'.

Чувствительность к регистру литералов JSON отличается от тех же самых литералов из SQL NULL, TRUE и FALSE, которые могут быть написаны в любом регистре:

mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL);
+--------------+--------------+--------------+
| ISNULL(null) | ISNULL(Null) | ISNULL(NULL) |
+--------------+--------------+--------------+
| 1            | 1            | 1            |
+--------------+--------------+--------------+

Нормализация, слияние и автообертывание значений JSON

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

mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def');
+------------------------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def') |
+------------------------------------------------------+
| {"key1": 1, "key2": "abc"}                           |
+------------------------------------------------------+

Нормализация, выполненная MySQL, также сортирует ключи объекта JSON (с целью создания более эффективных поисков). Результат этого упорядочивания подвержен изменениям и не гарантируется, что будет последовательным. Кроме того, от дополнительных пробелов между ключами, значениями или элементами в оригинале документа отказываются.

Функции MySQL, которые производят значения JSON (см. раздел 13.16.2) всегда возвращают нормализованные значения.

В контекстах, которые комбинируют многократные массивы, массивы слиты в единственный массив, добавляя массивы, названные позже, в конец первого массива. В следующем примере JSON_MERGE() сливает параметры в единственный массив:

mysql> SELECT JSON_MERGE('[1, 2]', '["a", "b"]', '[true, false]');
+-----------------------------------------------------+
| JSON_MERGE('[1, 2]', '["a", "b"]', '[true, false]') |
+-----------------------------------------------------+
| [1, 2, "a", "b", true, false]                       |
+-----------------------------------------------------+

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

mysql> SELECT JSON_MERGE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}');
+----------------------------------------------------+
| JSON_MERGE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}') |
+----------------------------------------------------+
| {"a": [1, 4], "b": 2, "c": 3}                      |
+----------------------------------------------------+

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

mysql> SELECT JSON_MERGE('1', '2');
+----------------------+
| JSON_MERGE('1', '2') |
+----------------------+
| [1, 2]               |
+----------------------+

Значения массива и объекта слиты, автообертывая объект как массив и сливая два массива:

mysql> SELECT JSON_MERGE('[10, 20]', '{"a": "x", "b": "y"}');
+------------------------------------------------+
| JSON_MERGE('[10, 20]', '{"a": "x", "b": "y"}') |
+------------------------------------------------+
| [10, 20, {"a": "x", "b": "y"}]                 |
+------------------------------------------------+

Поиск и модификация значений JSON

Выражение пути JSON выбирает значение в пределах документа JSON.

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

mysql> SELECT JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name');
+---------------------------------------------------------+
| JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name') |
+---------------------------------------------------------+
| "Aztalan"                                               |
+---------------------------------------------------------+

Синтаксис пути использует символ $, чтобы представить документ JSON на рассмотрении, произвольно сопровождаемый селекторами, которые указывают на последовательно более определенные части документа:

  • Период, сопровождаемый ключевым именем, называет участника в объекте с данным ключом. Ключевое имя должно быть определено в пределах двойных кавычек, если имя без кавычек не является законным в пределах выражений пути (например, если это содержит пробел).

  • [N] добавленный к пути, который выбирает массив, называет значение в позиции N в пределах массива. Позиции массива целые числа, начинающиеся с ноля.
  • Пути могут содержать подстановочные знаки * или **:

    • .[*] оценивается к значениям всех участников в объекте JSON.

    • [*] оценивается к значениям всех элементов в массиве JSON.
    • prefix**suffix оценивается ко всем путям, которые начинаются с названной приставки и заканчиваются названным суффиксом.

  • Путь, который не существует в документе (ведет к несуществующим данным) оценивает к NULL.

$ ссылается на этот массив JSON с тремя элементами:

[3, {"a": [5, 6], "b": 10}, [99, 100]]

Тогда:

  • $[0] 3.

  • $[1] {"a": [5, 6], "b": 10}.
  • $[2] [99,100].
  • $[3] NULL (это обращается к четвертому элементу массива, который не существует).

Поскольку $[1] и $[2] оцениваются к нескалярным значениям, они могут использоваться в качестве основания для более определенных выражений пути, которые выбирают вложенные значения. Примеры:

  • $[1].a [5,6].

  • $[1].a[1] 6.
  • $[1].b 10.
  • $[2][0] 99.

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

{"a fish": "shark", "a bird": "sparrow"}

Ключи содержат пробел и должны быть заключены в кавычки:

  • $."a fish" shark.

  • $."a bird" sparrow.

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

mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*') |
+---------------------------------------------------------+
| [1, 2, [3, 4, 5]]                                       |
+---------------------------------------------------------+

mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]');
+------------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]') |
+------------------------------------------------------------+
| [3, 4, 5]                                                  |
+------------------------------------------------------------+

В следующем примере путь $**.b оценивается к разнообразным путям ($.a.b и $.c.b) и производит массив соответствующих значений пути:

mysql> SELECT JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b') |
+---------------------------------------------------------+
| [1, 2]                                                  |
+---------------------------------------------------------+

Вы можете использовать column ->path с идентификатором столбца и выражением пути JSON как синоним для JSON_EXTRACT(column , path). См. разделы 13.16.3 и 14.1.15.6 .

Некоторые функции берут существующий документ JSON, изменяют это в некотором роде и возвращают получающийся измененный документ. Выражения пути указывают, где в документе произвести изменения. Например, функции JSON_SET(), JSON_INSERT() и JSON_REPLACE() берут документ JSON плюс одна или более пар пути/значения, которые описывают, где изменить документ и какие значения использовать. Функции отличаются по тому, как они обрабатывают существующие и несуществующие значения в пределах документа.

Рассмотрите этот документ:

mysql> SET @j = '["a", {"b": [true, false]}, [10, 20]]';

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

mysql> SELECT JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+--------------------------------------------+
| JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+--------------------------------------------+
| ["a", {"b": [1, false]}, [10, 20, 2]]      |
+--------------------------------------------+

В этом случае путь $[1].b[0] выбирает существующее значение (true), которое заменено значением после параметра пути (1). Путь $[2][2] не существует, таким образом, соответствующее значение (2) добавлено к значению, выбранному $[2].

JSON_INSERT() добавляет новые значения, но не заменяет существующие:

mysql> SELECT JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+-----------------------------------------------+
| JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+-----------------------------------------------+
| ["a", {"b": [true, false]}, [10, 20, 2]]      |
+-----------------------------------------------+

JSON_REPLACE() заменяет существующие значения и игнорирует новые:

mysql> SELECT JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+------------------------------------------------+
| JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+------------------------------------------------+
| ["a", {"b": [1, false]}, [10, 20]]             |
+------------------------------------------------+

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

JSON_REMOVE() берет документ JSON и один или более путей, которые определяют значения, которые будут удалены из документа. Возвращаемое значение: оригинал документа минус значения, выбранные путями, которые существуют в пределах документа:

mysql> SELECT JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]');
+---------------------------------------------------+
| JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]') |
+---------------------------------------------------+
| ["a", {"b": [true]}]                              |
+---------------------------------------------------+

Пути имеют эти эффекты:

  • $[2] соответствует [10, 20] и удаляет это.

  • Первый экземпляр $[1].b[1] соответствует false в элементе b и удаляет это.
  • Второй экземпляр $[1].b[1] ничему не соответствует: этот элемент был уже удален, путь больше не существует и не имеет никакого эффекта.

Сравнение и упорядочивание значений JSON

Значения JSON могут быть сравнены, используя операторы =, <, <=, >, >=, <>, != и <=>.

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

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

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

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

BLOB
BIT
OPAQUE
DATETIME
TIME
DATE
BOOLEAN
ARRAY
OBJECT
STRING
INTEGER, DOUBLE
NULL

Для значений JSON того же самого приоритета правила сравнения определены для типа:

  • BLOB

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

  • BIT

    Аналогично BLOB.

  • OPAQUE

    Аналогично BLOB. Значения OPAQUE не классифицированы как один из других типов.

  • DATETIME

    Значение, которое представляет более ранний момент времени, упорядочено перед значением, которое представляет более поздний момент времени. Если два значения первоначально прибывают из типов MySQL DATETIME и TIMESTAMP, соответственно, они равны, если они представляют тот же самый момент времени.

  • TIME

    Меньшее из двух временных значений упорядочено перед большим.

  • DATE

    Более ранняя дата упорядочена перед более свежей датой.

  • ARRAY

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

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

    Пример:

    [] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"]
    
  • BOOLEAN

    JSON-литерал false меньше true.

  • OBJECT

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

    Пример:

    {"a": 1, "b": 2} = {"b": 2, "a": 1}
    

    Порядок двух объектов, которые не равны, является неуказанным, но детерминированным.

  • STRING

    Строки упорядочены лексически на первых N байтах представления utf8mb4 двух сравниваемых строк, где N длина более короткой строки. Если первые N байт двух строк идентичны, более короткую строку считают меньшей чем более длинная строка.

    Пример:

    "a" < "ab" < "b" < "bc"
    

    Это упорядочивание эквивалентно упорядочиванию строк SQL с сопоставлением utf8mb4_bin. Поскольку utf8mb4_bin двоичное сопоставление, сравнение значений JSON является чувствительным к регистру:

    "A" < "a"
    
  • INTEGER, DOUBLE

    Значения JSON могут содержать числа точного значения и числа приблизительной точности. Для общего обсуждения этих типов чисел см. раздел 10.1.2.

    Правила для того, чтобы сравнить числовые типы MySQL обсуждены в разделе 13.2, но правила для того, чтобы сравнить числа в пределах значений JSON несколько отличаются:

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

    • С другой стороны, если запрос сравнивает два столбца JSON, содержащие числа, неизвестно заранее, будут ли числа integer или double. Чтобы обеспечить самое последовательное поведение через все строки, MySQL преобразовывает числа приблизительной точности в числа точного значения. Получающееся упорядочивание последовательно и не теряет точность для чисел точного значения. Например, учитывая скаляры 9223372036854775805, 9223372036854775806, 9223372036854775807 и 9.223372036854776e18, порядок таков как этот:
      9223372036854775805 < 9223372036854775806 < 9223372036854775807
      < 9.223372036854776e18 = 9223372036854776000 < 9223372036854776001
      

    Если сравнения JSON используют числовые правила сравнения не-JSON, непоследовательное упорядочивание могло произойти. Обычные правила сравнения MySQL для чисел приводят к этим упорядочиваниям:

    • Сравнения Integer:

      9223372036854775805 < 9223372036854775806 < 9223372036854775807
      

      (не определено для 9.223372036854776e18).

    • Сравнения Double:
      9223372036854775805 = 9223372036854775806 = 9223372036854775807 = 9.223372036854776e18
      

Для сравнения любого JSON с SQL NULL результат UNKNOWN.

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

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

Таблица 12.1. Правила конвертации JSON

другой тип CAST(другой тип AS JSON) CAST(JSON AS другой тип)
JSONБез измененийБез изменений
Тип символа utf8 (utf8mb4, utf8, ascii). Строка разобрана в значение JSON. Значение JSON преобразовано в последовательную форму в строку utf8mb4.
Другие символьные типы Другие кодировки символов неявно преобразованы в utf8mb4 и и обработаны как описано для utf8. Значение JSON преобразовано в последовательную форму в строку utf8mb4, затем приводится к другой кодировке символов. Результат, возможно, не является значащим.
NULL Результаты в значении NULL типа JSON. Неприменим.
Типы геометрии. Значение геометрии преобразовано в документ JSON вызовом ST_AsGeoJSON(). Недопустимо. Обходное решение: передайте результат CAST(json_val AS CHAR) в ST_GeomFromGeoJSON() .
Все другие типы Результаты в документе JSON, состоящем из единственного скалярного значения. Преуспевает, если документ JSON состоит из единственного скалярного значения целевого типа и скалярное значение может быть конвертировано к целевому типу. Иначе возвращает NULL и производит предупреждение.

ORDER BY и GROUP BY для JSON работают согласно этим принципам:

  • Упорядочивание скаляра значения JSON использует те же самые правила, как в предыдущем обсуждении.

  • Для сортировок по возрастанию SQL NULL будет перед всеми значениями JSON, включая буквальный нуль JSON. Для сортировок по убыванию наоборот.
  • Ключи сортировки для значений JSON ограничены значением переменной max_sort_length, таким образом, ключи, которые отличаются только после первых max_sort_length байт сравниваются как равные.
  • Сортировка нескалярных значений в настоящее время не поддерживается, и предупреждение происходит.

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

ORDER BY CAST(JSON_EXTRACT(jdoc, '$.id') AS UNSIGNED)

Если есть произведенный столбец, определенный, чтобы использовать то же самое выражение в ORDER BY, оптимизатор MySQL признает это и рассматривает использование индексирования для плана выполнения запроса. См. раздел 9.3.9.

Агрегирование значений JSON

Для агрегирования значений JSON SQL NULL проигнорированы, как для других типов данных. Не-NULL преобразованы в числовой тип и соединены, за исключением MIN(), MAX() и GROUP_CONCAT(). Преобразование в число должно привести к значащему результату для значений JSON, которые являются числовыми скалярами, хотя (в зависимости от значений) усечение и потеря точности могут произойти. Преобразование в число других значений JSON, возможно, не приводит к значащему результату.

12.7. Значения по умолчанию

Предложение DEFAULT value в спецификации типа данных указывает на значение по умолчанию для столбца. С одним исключением: значение по умолчанию должно быть константой, это не может быть функция или выражение. Это означает, например, что Вы не можете установить значение по умолчанию для столбца даты в значение такой функции, как NOW() или CURRENT_DATE. Исключение: Вы можете определить CURRENT_TIMESTAMP как значение по умолчанию для столбцов TIMESTAMP и DATETIME. См. раздел 12.3.5.

Столбцам BLOB, TEXT, GEOMETRY и JSON нельзя назначить значение по умолчанию.

Если определение столбца включает неявное значение DEFAULT, MySQL определяет значение по умолчанию следующим образом:

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

Если столбец не может взять NULL как значение, MySQL определяет столбец без явного DEFAULT. Исключение: Если столбец определен как часть PRIMARY KEY, но не явно как NOT NULL, MySQL создает это как NOT NULL (потому что PRIMARY KEY должны быть NOT NULL).

Для ввода данных в столбец NOT NULL, который имеет неявное предложение DEFAULT, если запрос INSERT или REPLACE не включает значения для столбца, или UPDATE устанавливает столбец в NULL, MySQL обрабатывает столбец согласно режиму SQL в это время:

  • Если строгий режим SQL включен, ошибка происходит для транзакционных таблиц, и запрос откатывается до прежнего уровня. Для нетранзакционных таблиц ошибка происходит, но если это происходит для второй или последующей строки запроса с многими строками, предыдущие строки будут вставлены.

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

Предположите что таблица t определена следующим образом:

CREATE TABLE t (i INT NOT NULL);

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

INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));

Для данной таблицы Вы можете использовать SHOW CREATE TABLE, чтобы видеть, у каких столбцов есть явное предложение DEFAULT.

Неявные значения по умолчанию определены следующим образом:

  • Для числовых типов значение по умолчанию 0, за исключением того, что для целого числа или типов с плавающей запятой, объявленных с атрибутом AUTO_INCREMENT, значение по умолчанию это следующее значение в последовательности.

  • Для типов даты и времени, но не для TIMESTAMP, значение по умолчанию соответствующее нулевое значение для типа. Это также истина для TIMESTAMP, если системная переменная explicit_defaults_for_timestamp включена (см. раздел 6.1.5). Иначе для первого столбца TIMESTAMP значение по умолчанию это текущая дата и время. См. раздел 12.3.
  • Для строковых типов, кроме ENUM, значение по умолчанию пустая строка. Для ENUM значение по умолчанию первое значение перечисления.

SERIAL DEFAULT VALUE в определении столбца целого числа это псевдоним для NOT NULL AUTO_INCREMENT UNIQUE.

12.8. Требования хранения типов данных

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

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

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

У внутреннего представления таблицы есть максимальный размер строки в 65535 байтов, даже если механизм хранения способен к поддержке более крупных строк. Это число исключает столбцы BLOB или TEXT, которые вносят только 9-12 байт к этому размеру. Для BLOB и TEXT информация хранится внутренне в иной области памяти, чем буфер строки. Различные механизмы хранения обрабатывают распределение и хранение этих данных по-разному, согласно методу, который они используют для того, чтобы обработать соответствующие типы. Для получения дополнительной информации см. главу 17 и раздел C.10.4.

Требования хранения для таблиц InnoDB

См. раздел 16.8.2 для информации о требованиях хранения для таблиц InnoDB.

Требования хранения для числовых типов

Тип Сколько надо места
TINYINT 1 байт
SMALLINT 2 байта
MEDIUMINT 3 байта
INT, INTEGER4 байта
BIGINT 8 байт
FLOAT(p) 4 байта, если 0 <= p <= 24, 8 байт, если 25 <= p <= 53
FLOAT 4 байт
DOUBLE [PRECISION], REAL 8 байт
DECIMAL(M,D ), NUMERIC(M,D) Переменно (см. ниже)
BIT(M) примерно (M+7)/8 байт

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

Крайние слева цифры Число байт
00
11
21
32
42
53
63
74
84

Требования хранения для типов даты и времени

Для столбцов TIME, DATETIME и TIMESTAMP место, требуемое для таблиц, составленных до MySQL 5.6.4, отличается от таблиц, составленных в 5.6.4 и выше. Это происходит из-за изменения в 5.6.4, который разрешает этим типам иметь дробную часть, которая требует от 0 до 3 байтов.

Тип данных Сколько надо места до MySQL 5.6.4 Сколько надо места в MySQL 5.6.4 и выше
YEAR 1 byte1 байт
DATE 3 bytes3 байта
TIME 3 bytes3 байта + дробное хранение секунд
DATETIME 8 bytes5 байт + дробное хранение секунд
TIMESTAMP 4 bytes4 байта + дробное хранение секунд

С MySQL 5.6.4 место для YEAR и DATE остается неизменным. Однако, TIME, DATETIME и TIMESTAMP представлены по-другому. DATETIME упакован более эффективно, требуя 5 а не 8 байтов для целой части, и у всех трех частей есть дробная часть, которая требует от 0 до 3 байтов, в зависимости от точности дробной части секунд сохраненных значений.

Точности дробной части секунд Сколько надо места
0Не надо
1, 21 байт
3, 42 байта
5, 63 байта

Например, TIME(0), TIME(2), TIME(4) и TIME(6) используют 3, 4, 5 и 6 байтов, соответственно. TIME и TIME(0) эквивалентны и требуют того же самого места.

Для деталей о внутреннем представлении временных значений см. MySQL Internals: Important Algorithms and Structures.

Требования хранения для строковых типов

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

Тип данныхСколько надо места
CHAR(M) M/w байт, 0 <= M <= 255, где w число байтов, требуемых для символа максимальной длины в наборе символов. См. раздел 16.8.2 для информации о требованиях хранения типа данных CHAR в таблицах InnoDB .
BINARY(M) M байт, 0 <=M <= 255
VARCHAR(M), VARBINARY(M) L + 1 байт, если значения столбцов требуют 0-255 байт, L + 2 байта, если значения могут потребовать больше 255 байтов
TINYBLOB, TINYTEXTL + 1 байт, где L < 28
BLOB, TEXTL + 2 байта, где L < 216
MEDIUMBLOB, MEDIUMTEXT L + 3 байта, где L < 224
LONGBLOB, LONGTEXT L + 4 байта, где L < 232
ENUM('value1', 'value2',...) 1 или 2 байта, в зависимости от числа значений перечисления (максимум значений 65535 штук)
SET('value1', 'value2',...) 1, 2, 3, 4 или 8 байт, в зависимости от числа участников набора (максимум 64)

Строковые типы переменной длины сохранены, используя приставку длины плюс данные. Приставка длины требует от одного до четырех байтов в зависимости от типа данных, и значение приставки L (байт длины строки). Например, хранение для MEDIUMTEXT требует L байт, чтобы сохранить значение плюс три байта, чтобы сохранить длину значения.

Вычисляя число байтов для хранения значения столбца CHAR, VARCHAR или TEXT, Вы должны принять во внимание набор символов, используемый для этого столбца и содержит ли значение мультибайтные символы. В частности, используя набор символов Unicode utf8, Вы должны иметь в виду, что не все символы используют то же самое число байтов. Наборы символов utf8mb3 и utf8mb4 могут потребовать до трех и четырех байтов на символ, соответственно. См. подробности в разделе 11.1.9.

Типы VARCHAR, VARBINARY, BLOB и TEXT это типы переменной длины. Для каждого из них требования хранения зависят от этих факторов:

  • Фактическая длина значения столбца.

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

Например, столбец VARCHAR(255) может содержать строку максимальной длиной 255 символов. Предположим, что столбец использует набор символов latin1 (один байт на символ), тогда фактически требуемое место является длиной строки (L) плюс один байт, чтобы сделать запись длины строки. Для строки 'abcd' L 4 и требуемое место составляет пять байтов. Если тот же самый столбец вместо этого использует двухбайтный набор символов ucs2, требование хранения составляет 10 байтов: длина 'abcd' восемь байтов, и столбец требует, чтобы два байта сохранили длину, потому что максимальная длина больше 255 (до 510 байтов).

InnoDB рассматривает CHAR как тип переменной длины, если таблица составлена, используя формат строки COMPACT, DYNAMIC или COMPRESSED, значение столбца CHAR больше или равна 768 байтам, что может произойти, если максимальная длина символа набора больше 3 байт, как с utf8mb4, например.

Эффективное максимальное количество байтов, которые могут быть сохранены в столбце VARCHAR или VARBINARY ограничено максимальным размером строки в 65535 байтов, которые совместно использованы всеми столбцами. Для VARCHAR , который хранит мультибайтные символы, эффективное максимальное количество символов меньше. Например, символы utf8mb4 могут потребовать до четырех байтов на символ, таким образом, столбец VARCHAR, который использует набор символов utf8mb4 может хранить максимум 16383 символа. См. раздел C.10.4.

Размер объекта ENUM определен числом различных значений перечисления. Один байт используется для перечислений с 255 возможными значениями. Два байта используются для наличия перечислений между 256 и 65535 возможными значениями. См. раздел 12.4.4.

Размер объекта SET определен числом различных участников набора. Если размер набора N, объект занимает (N+7)/8 байт, округленныфе вверх до 1, 2, 3, 4 или 8 байт. SET может иметь максимум 64 участника. См. раздел 12.4.5.

12.9. Выбор правильного типа для столбца

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

Все основные вычисления (+, -, * и /) со столбцами DECIMAL сделаны с точностью 65 десятичных цифр. См. раздел 12.1.1.

Если точность не слишком важна или если скорость самый высокий приоритет, тип DOUBLE тип может быть достаточно хорошим. Для высокой точности Вы можете всегда преобразовывать в тип фиксированной точки, сохраненный в BIGINT. Это позволяет Вам сделать все вычисления с 64-битовыми целыми числами и затем преобразовать результаты назад в значения с плавающей запятой по мере необходимости.

PROCEDURE ANALYSE может использоваться, чтобы получить предложения для оптимальных типов данных столбца. Для получения дополнительной информации см. раздел 9.4.2.4.

12.10. Применение типов данных из других баз данных

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

Тип из другой СУБДТип в MySQL
BOOL TINYINT
BOOLEAN TINYINT
CHARACTER VARYING(M) VARCHAR(M)
FIXED DECIMAL
FLOAT4 FLOAT
FLOAT8 DOUBLE
INT1 TINYINT
INT2 SMALLINT
INT3 MEDIUMINT
INT4 INT
INT8 BIGINT
LONG VARBINARY MEDIUMBLOB
LONG VARCHAR MEDIUMTEXT
LONG MEDIUMTEXT
MIDDLEINT MEDIUMINT
NUMERIC DECIMAL

Отображение типа данных происходит во время создания таблицы, после которого отказываются от оригинальных технических требований типа. Если Вы составляете таблицу с типами, используемыми другими разработчиками и затем выполняете DESCRIBE tbl_name, MySQL сообщает о структуре таблицы, используя эквивалентные типы MySQL. Например:

mysql> CREATE TABLE t (a BOOL, b FLOAT8, c LONG VARCHAR, d NUMERIC);
Query OK, 0 rows affected (0.00 sec)

mysql> DESCRIBE t;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| a     | tinyint(1)    | YES  |     | NULL    |       |
| b     | double        | YES  |     | NULL    |       |
| c     | mediumtext    | YES  |     | NULL    |       |
| d     | decimal(10,0) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru