Глава 12. Типы данных
MySQL поддерживает много типов данных SQL
в нескольких категориях: числовые типы, типы даты и времени, строка
(символ и байт), пространственные типы и
JSON .
Эта глава обеспечивает краткий обзор этих типов данных, более подробное
описание свойств типов в каждой категории и резюме требований хранения типа
данных. Начальный краткий обзор преднамеренно краток. С более подробными
описаниями позже в главе нужно консультироваться для дополнительной
информации об особых типах данных, таких как допустимые форматы, в которых Вы
можете определить значения.
Описания типа данных используют эти соглашения:
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 , используя строку.
В этом случае, 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) |
TINYINT | 1 |
-128 | 127 |
| | 0 |
255 |
SMALLINT | 2 |
-32768 | 32767 |
| | 0 |
65535 |
MEDIUMINT | 3 |
-8388608 | 8388607 |
| | 0 |
16777215 |
INT | 4 |
-2147483648 | 2147483647 |
| | 0 |
4294967295 |
BIGINT | 8 |
-9223372036854775808 | 9223372036854775807
|
| | 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 интерпретирует значения года с двумя цифрами,
используя эти правила:
- Преобразование значений из одного временного типа в другой происходит
согласно правилам в разделе
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 .
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 во множестве форматов:
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) автоматически:
Обновление 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) на ведомом.
Следовательно, у этих операций будет различный результат на ведущем и ведомом
устройствах, если Вы будете использовать основанную на запросе репликацию:
Чтобы избежать таких проблем, измените все столбцы
YEAR(2) на ведущем устройстве к
to YEAR(4) перед обновлением.
Используйте ALTER TABLE ,
как описано ранее. Тогда Вы можете обычно обновлять (ведомое устройство
сначала, ведущее позже), не представляя никаких различий между ведущим
устройством и ведомым в YEAR(2) .
Одного метода перемещения нужно избежать: не выводите свои данные с
mysqldump
с перезагрузкой файла дампа после обновления. У этого есть потенциал, чтобы
изменить значения YEAR(2) .
Перемещение от YEAR(2) к
YEAR(4) должно также вовлечь код
программы для возможности измененного исследования поведения при условиях:
12.3.5.
Автоматическая инициализация и обновление для TIMESTAMP и DATETIME
Столбцы TIMESTAMP и
DATETIME могут быть
автоматически инициализированы и обновлены к текущей дате и времени
(то есть, timestamp).
Для любого столбца TIMESTAMP
или DATETIME в таблице Вы
можете назначить текущий 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 выключена
(по умолчанию), сделайте любое из следующего:
Рассмотрите эти табличные определения:
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
или 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 во время вставки, кроме как при одном из следующих условий:
Другими словами, столбец 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 :
Преобразование в 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
интерпретирует даты, определенные с неоднозначными значениями года,
используя эти правила:
Для 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 следующим:
Если Вы используете признак 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
Значение перечисления должно быть заключенной в кавычки буквальной
строкой. Например, Вы можете составить таблицу с 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 можно так:
Ограничения перечисления
Значение перечисления не может быть выражением, даже то, которое
оценивается как строковое значение.
Например, 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 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.
Иерархия классов геометрии
Классы геометрии определяют иерархию следующим образом:
Невозможно создать объекты в noninstantiable классах. Возможно создать
объекты в instantiable классах. У всех классов есть свойства, у
instantiable классов могут также быть утверждения (правила, которые
определяют допустимые экземпляры класса).
Geometry базовый класс. Это абстрактный класс. instantiable
подклассы Geometry ограничены 0, 1 и 2-мерными геометрическими
объектами, которые существуют в двумерном координатном пространстве.
Все instantiable классы геометрии определены так, чтобы допустимые экземпляры
класса геометрии были топологически закрыты (то есть, все определенные
конфигурации включают свою границу).
У базового класса Geometry есть подклассы для
Point , Curve , Surface и
GeometryCollection :
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:
Значение X-координаты.
- Значение Y-координаты.
Point определен как 0-мерная геометрия.
- Граница a
Point пустой набор.
12.5.2.4. Класс Curve
Curve одномерная геометрия, обычно представляемая
последовательностью пунктов. Особые подклассы Curve определяют
тип интерполяции между пунктами. Curve noninstantiable класс.
Свойства Curve:
12.5.2.5. Класс LineString
LineString это Curve
с линейной интерполяцией между пунктами.
Примеры LineString:
Свойства LineString:
12.5.2.6. Класс Surface
Surface двумерная геометрия. Это noninstantiable класс. Его
единственный instantiable подкласс Polygon .
Свойства Surface:
12.5.2.7. Класс Polygon
Polygon это плоское представление Surface
мультипримкнутой геометрии. Это определено единственной внешней границей и
нолем или большим количеством внутренних границ, где каждая внутренняя
граница определяет отверстие в Polygon .
Примеры Polygon:
Утверждения Polygon:
Граница Polygon состоит из ряда объектов
LinearRing (то есть, объектов LineString , которые
просты и закрыты), которые составляют его внешние и внутренние границы.
Polygon не имеет никаких колец, которые пересекаются.
Кольца в границе Polygon могут пересечься в Point ,
но только как тангенс.
Polygon не имеет никаких линий, шипов или проколов.
Polygon имеет интерьер, который является
соединенным набором пунктов.
Polygon может иметь отверстия. Внешность
Polygon с отверстиями не соединена. Каждое отверстие определяет
соединенный компонент внешности.
Предыдущие утверждения делают Polygon простой геометрией.
12.5.2.8. Класс
GeometryCollection
GeometryCollection геометрия, которая является набором из
одной или более конфигураций любого класса.
Все элементы в GeometryCollection должны быть в той же самой
пространственной ссылочной системе (то есть, в той же самой системе
координат). Нет никаких других ограничений на элементы
GeometryCollection , хотя подклассы
GeometryCollection в следующих разделах могут ограничить
членство. Ограничения могут быть основаны на:
12.5.2.9. Класс MultiPoint
MultiPoint набор геометрии, составленный из
Point . Пункты не соединены или упорядочены в любом случае.
Примеры MultiPoint:
Свойства MultiPoint:
12.5.2.10. Класс MultiCurve
MultiCurve набор геометрии, составленный из
Curve . MultiCurve noninstantiable класс.
Свойства MultiCurve:
12.5.2.11. Класс MultiLineString
MultiLineString это набор геометрии MultiCurve
из элементов LineString .
Примеры MultiLineString:
12.5.2.12. Класс MultiSurface
MultiSurface набор геометрии, составленный из поверхностных
элементов. MultiSurface noninstantiable класс. Его единственный
instantiable подкласс MultiPolygon .
Утверждения MultiSurface :
12.5.2.13. Класс MultiPolygon
MultiPolygon это объект MultiSurface
из элементов Polygon .
Примеры MultiPolygon :
Утверждения MultiPolygon :
Свойства 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 ограничен значением
переменной
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 в
пределах массива. Позиции массива целые числа, начинающиеся с ноля.
- Пути могут содержать подстановочные знаки
* или
** :
Путь, который не существует в документе (ведет к несуществующим
данным) оценивает к 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]}] |
+---------------------------------------------------+
Пути имеют эти эффекты:
Сравнение и упорядочивание значений 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
к некоторому другому типу 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 ,
INTEGER | 4 байта
|
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 цифр требуют четырех байтов, и
крайние слева цифры требуют какой-то части четырех байтов.
Хранение, требуемое для этих лишних цифр, дано следующей таблицей.
Крайние слева цифры |
Число байт |
0 | 0 |
1 | 1 |
2 | 1 |
3 | 2 |
4 | 2 |
5 | 3 |
6 | 3 |
7 | 4 |
8 | 4 |
Требования хранения для типов даты и времени
Для столбцов 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 byte | 1 байт |
DATE |
3 bytes | 3 байта |
TIME |
3 bytes | 3 байта + дробное хранение секунд |
DATETIME
| 8 bytes | 5 байт + дробное хранение секунд |
TIMESTAMP
| 4 bytes | 4 байта + дробное хранение секунд |
С MySQL 5.6.4 место для YEAR
и DATE остается неизменным.
Однако, TIME ,
DATETIME и
TIMESTAMP представлены
по-другому. DATETIME
упакован более эффективно, требуя 5 а не 8 байтов для целой части, и у всех
трех частей есть дробная часть, которая требует от 0 до 3 байтов, в
зависимости от точности дробной части секунд сохраненных значений.
Точности дробной части секунд |
Сколько надо места |
0 | Не надо |
1, 2 | 1 байт |
3, 4 | 2 байта |
5, 6 | 3 байта |
Например, 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 ,
TINYTEXT | L
+ 1 байт, где L < 28 |
BLOB ,
TEXT | L
+ 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.
Отображение типа данных происходит во время создания таблицы, после
которого отказываются от оригинальных технических требований типа.
Если Вы составляете таблицу с типами, используемыми другими разработчиками
и затем выполняете 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)
|
|