Что такое decimal в mysql
Что такое decimal в mysql
MySQL 5.1 обеспечивает поддержку для точной математики: числовая обработка значения, которая приводит к чрезвычайно точным результатам, и высокой степени контроль над недопустимыми значениями. Точность основана на этих двух свойствах:
SQL-режимы, которые управляют тем, как строг сервер относительно принятия или отклонения недопустимых данных.
MySQL-библиотека для арифметики с фиксированной запятой.
Эти свойства имеют несколько импликаций для числовых операций:
Четкое поведение округления : для чисел высокой точности результат ROUND() зависит только от параметра, а не от относящихся к окружению факторах типа того, как основная библиотека C работает.
Независимость от платформы : операции на точных числовых значениях дают тот же самый результат на различных платформах, типа Windows и Unix.
Важный результат этих свойств: MySQL 5.1 обеспечивает высокую степень согласия со стандартом SQL.
Следующее обсуждение покрывает несколько аспектов того, как работает высокая точность (включая возможные несовместимости со старыми прикладными программами). В конце есть некоторые примеры.
1.1. Типы числовых значений
Контекст математической точности для операций с точным значением включает типы данных с точным значением ( DECIMAL и целочисленные типы) и числовые литералы с точным значением. Типы данных с приблизительным значением и числовые литералы все еще обработаны как числа с плавающей запятой.
Два числа, которые выглядят одинаково, могут не быть оба точными или приблизительными. Например, 2.34 представляет собой число с точным значением (с фиксированной запятой), в то время как 2.34E0 задает число с приблизительным значением (с плавающей запятой).
1.2. Изменения типа данных DECIMAL
Этот раздел обсуждает характеристики типа данных DECIMAL (и синонимов) в MySQL 5.1, со специфическим отношением к следующим темам
Максимальное число цифр
Требования к памяти
Ненормативное MySQL расширение к верхнему диапазону столбцов DECIMAL
Возможные несовместимости с прикладными программами, которые написаны для старых версий MySQL, отмечены в этом разделе.
M : максимальное число цифр (точность). Это имеет диапазон от 1 до 65. Старые версии MySQL позволяли диапазон от 1 до 254.
Максимальное значение 65 для M означает, что вычисления на значениях DECIMAL точны до 65 цифр. Это ограничение точности в 65 цифр также применяется к числовым литералам с точным значением, так что оно задает максимальный диапазон таких литералов. В старых версиях MySQL десятичные значения могли иметь до 254 цифр. Однако, вычисления были выполнены, используя числа с плавающей запятой и таким образом были приблизительны, не точны.
Значения для столбцов DECIMAL в MySQL 5.1 сохранены, используя двоичный формат, который упаковывает девять десятичных цифр в четыре байта. Требования к памяти для целочисленных и дробных частей каждого значения определены отдельно. Каждые девять цифр требуют четырех байт, и любые цифры сверх этого требуют некоторой доли четырех байтов. Например, DECIMAL(18,9) имеет девять цифр с обеих сторон десятичной точки, так что целочисленная и дробная части требуют четырех байтов каждая. Столбец DECIMAL(20,10) имеет по десять цифр с обеих сторон десятичной точки. Каждая часть требует четырех байтов для девяти из цифр и одного байта для остающейся цифры.
Память, требуемая для остающихся цифр, показана в следующей таблице:
Остающиеся цифры | Число байтов |
0 | 0 |
1 | 1 |
2 | 1 |
3 | 2 |
4 | 2 |
5 | 3 |
6 | 3 |
7 | 4 |
8 | 4 |
9 | 4 |
1.3. Обработка выражений
Обработка числового выражения зависит от значений, которое выражение содержит:
Если любые приблизительные значения присутствуют, выражение оценено приблизительно, используя арифметику с плавающей запятой.
Если никакие приблизительные значения не присутствуют, выражение содержит только точные значения. Если любое точное значение содержит дробную часть (значение после десятичной точки), выражение оценено, используя точную арифметику DECIMAL и имеет точность 65 цифр.
Иначе, выражение содержит только целочисленные значения. Выражение точно и оценено, используя целочисленную арифметику и имеет точность BIGINT (64 бита).
Если числовое выражение содержит любые строки, они преобразованы в значения с плавающей запятой двойной точности, и выражения приблизительны.
Если число вставлено в столбец точного типа ( DECIMAL или целое число), оно вставлено с точным значением, если находится внутри диапазона столбца.
Если значение имеет слишком много цифр в дробной части, происходит округление, и будет сгенерировано предупреждение. Округление выполнено как описано в разделе » 1.4. Поведение округления».
Если значение имеет слишком много цифр в целочисленной части, оно слишком большое и обработано следующим образом:
Если строгий режим не допускается, значение усечено к самому близкому допустимому значению, и сгенерировано предупреждение.
Если строгий режим допускается, происходит ошибка переполнения.
По умолчанию, деление на нуль производит результат NULL и никакого предупреждения. С включенным режимом SQL ERROR_FOR_DIVISION_BY_ZERO MySQL обрабатывает деление на нуль по-другому:
Если строгий режим не допускается, происходит предупреждение.
Если строгий режим допускается, вставки и модификации, включающие деление на нуль, запрещены, и происходит ошибка.
Другими словами, вставки и модификации, включающие выражения, которые выполняют деление на нуль, могут обрабатываться как ошибки, но это требует ERROR_FOR_DIVISION_BY_ZERO в дополнение к строгому режиму.
Предположим, что мы имеем эту инструкцию:
Это что случается для комбинации строгого режима и ERROR_FOR_DIVISION_BY_ZERO :
Для вставок строк в числовые столбцы, преобразование из строки в число обработано следующим образом, если строка имеет нечисловое содержание:
Строка, которая не начинается с числа, не может использоваться как число, и производит ошибку в строгом режиме или предупреждение в любом другом. Это включает пустую строку.
Строка, которая начинается с числа, может быть преобразована, но конечная нечисловая часть усечена. Если усеченная часть содержит что-нибудь другое, чем пробелы, это производит ошибку в строгом режиме или предупреждение в любом другом.
1.4. Поведение округления
Этот раздел обсуждает точность математического округления для функции ROUND() и для вставок в столбцы с типами с точным значением.
Функция ROUND() работает по-разному в зависимости от того, является ли параметр точным или приблизительным числом:
Для числа приблизительного значения результат зависит от библиотеки C. На многих системах это означает, что значение с любой дробной частью округлено ROUND() к самому близкому четному целому числу.
Следующий пример показывает, как округление отличается для точных и приблизительных значений:
Для вставок в DECIMAL или целочисленный столбец, если адресат представляет собой точный тип данных, используется метод «округления половины» независимо от того, является ли значение, которое будет вставлено, точным или приблизительным:
1.5. Примеры математической точности
Этот раздел обеспечивает некоторые примеры, которые показывают запросы с математической точностью в MySQL 5.1.
Для значений с плавающей запятой, результаты неточны:
Сумма для d и f логически должна быть 1, но это истинно только для десятичного вычисления. Вычисление с плавающей запятой представляет маленькие ошибки:
Поведение округления (например, с функцией ROUND() ) независимо от реализации основной библиотеки C, что означает, что результаты непротиворечивы на разных платформах.
Округление для столбцов с точным значением использует округление половины, как показано здесь:
Однако, округление для значений с плавающей запятой использует библиотеку C, которая на многих системах использует другую логику работы:
Однако, условие переполнения происходит, если включен строгий режим:
В нестрогом режиме деление на нуль имеет результат NULL :
Однако, деление на нуль выдает ошибку, если соответствующие SQL-режимы активны:
Начиная с MySQL 5.0.3, литерал с приблизительным значением все еще преобразован в значение с плавающей запятой, но литерал с точным значением обработан как DECIMAL :
Результаты до MySQL 5.0.3:
Результат двойной точности, независимо от типа параметра. А вот результаты в MySQL 5.0.3 и выше:
Результат двойной точности только для параметра с плавающей запятой. Для параметров точных типов, результатом будет также точный тип.
Типы данных MySQL. Чем руководствоваться при выборе типа данных
Опубликовано: 23 Апреля 2019
Выбирая тип данных для столбца, прежде всего стоит определить общий класс данных, который лучше использовать для столбца: числовые, строковые или временные;
Далее необходимо выбрать конкретный тип данных из представленных в классе. Многие типы данных MySQL позволяют хранить данные одного и тот же вида, но с разным диапазоном значений, точностью или требуемым физическим пространством (на диске или в памяти). Некоторые типы обладают специальным поведением или свойствами.
Например, в столбцах DATETIME и TIMESTAMP можно хранить один и тот же тип данных: дату и время, с точностью до секунды. Однако тип TIMESTAMP требует вдвое меньше места, позволяет работать с часовыми поясами и обладает специальными средствами автоматического обновления. С другой стороны, диапазон допустимых значений для него намного уже.
На что обратить внимание при выборе типа данных:
Скорость при соединении столбцов типа VARCHAR и ENUM:
Соединение VARCHAR с VARCHAR
Соединение VARCHAR с ENUM
Соединение ENUM с VARCHAR
Соединение ENUM с ENUM
В целях совместимости MySQL поддерживает различные псевдонимы, например INTEGER, BOOL — это псевдонимы (синонимы) одного и того же типа данных. Данный факт может сбить с толку, но не оказывает влияния на производительность.
Числовые типы
Хранение целых чисел
СУБД MySQL позволяет указывать для целых чисел «размер», например INT(11). Для большинства приложений это не имеет значения: диапазон возможных значений этим не ограничивается. Однако данный параметр говорит некоторым интерактивным инструментам MySQL, сколько позиций необходимо зарезервировать для вывода числа. С точки зрения хранения и вычисления INT(1) и INT(20) идентичны.
Знаковые и беззнаковые типы требуют одинакового пространства и обладают одинаковой производительностью.
Необязательный атрибут ZEROFILL заполнит нулями свободные позиции слева. Например с TINYINT(3) ZEROFILL, величина 2 будет записана, как 002.
Тип данных | Бит | По умолчанию | UNSIGNED |
---|---|---|---|
TINYINT | 8 | -128 — 127 | 0 — 255 |
SMALLINT | 16 | -32768 — 32767 | 0 — 65535 |
MEDIUMINT | 24 | -8388608 — 8388607 | 0 — 16777215 |
INT | 32 | -2147483648 — 2147483647 | 0 — 4294967295 |
BIGINT | 64 | -9223372036854775808 — 9223372036854775807 | 0 — 18446744073709551615 |
Хранение дробных чисел
Все типы допускают приближенные математические вычисления с плавающей точкой, но в случае с FLOAT и DOUBLE операции выполняются быстрее, так как процессор выполняет их естественным для него образом.
M — количество отводимых под число символов. D — количество символов дробной части.
Для типов с плавающей точкой можно указать максимально разрешенное количество цифр до и после десятичной запятой. В случае с DECIMAL это влияет на объем пространства, требуемого для хранения данных столбца. При указании точности, в некоторых случаях, MySQL незаметно для пользователя может выбирать другой тип данных или будет округлять значения при сохранении. Поэтому рекомендуют указывать желаемый тип, но не точность.
FLOAT и DOUBLE могут иметь параметр UNSIGNED, запрещающий отрицательные числа, но диапазон значений от этого не изменится.
Число типа DECIMAL в MySQL 5.0 и более новых версиях может содержать до 65 цифр. В более ранних версиях MySQL тип DECIMAL имел предел 254 цифры и хранил значения в виде неупакованных строк (один байт на цифру). Однако эти версии СУБД не умели использовать такие большие числа в вычислениях, поскольку тип DECIMAL был просто форматом хранения. При выполнении каких-либо операций значения DECIMAL преобразовывались в тип DOUBLE.
Строковые типы
В типах CHAR и VARCHAR строки рассматриваются как последовательности символов, поэтому, при использовании многобайтных кодировок, например UNICODE, размер строки в байтах будет больше, чем в символах.
При создании таблицы нельзя комбинировать столбцы типов CHAR и VARCHAR. Если такое произойдет, то MySQL изменит тип столбцов CHAR на тип VARCHAR.
Представим что строковый тип применяется для хранения значений Y и N. В случае использования CHAR(1) значение займет один байт, тогда как для типа VARCHAR(1) потребуется два байта из-за наличия дополнительного байта длины строки.
Значение | CHAR(4) | Требуется хранилище | VARCHAR(4) | Требуется хранилище |
---|---|---|---|---|
» | ‘ ‘ | 4 байта | » | 1 байт |
‘ab’ | ‘ab ‘ | 4 байта | ‘ab’ | 3 байта |
‘abcd’ | ‘abcd’ | 4 байта | ‘abcd’ | 5 байт |
‘abcdefgh’ | ‘abcd’ | 4 байта | ‘abcd’ | 5 байт |
Двоичные строки
Для совместимости со старыми версиями MySQL введены два специальных типа данных: BINARY и VARBINARY, которые эквивалентны типам CHAR и VARHAR, однако строка в них рассматривается как последовательность байтов, а не символов. К BINARY строкам не применимы кодировки и сортируются они как обычные последовательности байтов. Эти типы могут быть полезны, когда нужно сохранять двоичные данные, и вы хотите, чтобы MySQL сравнивал значение как байты, а не как символы. При этом, двоичное сравнение может оказаться значительно проще и быстрее символьного.
Текстовые и бинарные типы
Предназначены для хранения больших объемов двоичных или символьных данных.
MySQL обрабатывает значения BLOB и TEXT как отдельные объекты. Единственное различие между семействами BLOB и TEXT заключается в том, что типы BLOB хранят двоичные данные без учета схемы упорядочения и кодировки, а с типами TEXT ассоциированы схемы упорядочения и кодировка.
Семейство TEXT используется для хранения непосредственно текста:
Cемейство BLOB — для хранения изображений, звука, электронных документов и т.д.:
MySQL не может индексировать данные этих типов по полной длине и не может использовать для сортировки индексы.
Подсистема хранения Memory не поддерживает типы BLOB и TEXT.
Decimal(P, S), Decimal32(S), Decimal64(S), Decimal128(S), Decimal256(S)
Знаковые дробные числа с сохранением точности операций сложения, умножения и вычитания. Для деления осуществляется отбрасывание (не округление) знаков, не попадающих в младший десятичный разряд.
Параметры
Диапазоны Decimal
Внутреннее представление
Внутри данные представляются как знаковые целые числа, соответсвующей разрядности. Реальные диапазоны, хранящиеся в ячейках памяти несколько больше заявленных. Заявленные диапазоны Decimal проверяются только при вводе числа из строкового представления.
Поскольку современные CPU не поддерживают 128-битные числа, операции над Decimal128 эмулируются программно. Decimal128 работает в разы медленней чем Decimal32/Decimal64.
Операции и типы результата
Результат операции между двумя Decimal расширяется до большего типа (независимо от порядка аргументов).
Для размера дробной части (scale) результата действуют следующие правила:
При операциях между Decimal и целыми числами результатом является Decimal, аналогичный аргументу.
Часть функций над Decimal возвращают Float64 (например, var, stddev). Для некоторых из них промежуточные операции проходят в Decimal.
Для таких функций результат над одинаковыми данными во Float64 и Decimal может отличаться, несмотря на одинаковый тип результата.
Проверка переполнений
При выполнении операций над типом Decimal могут происходить целочисленные переполнения. Лишняя дробная часть отбрасывается (не округляется). Лишняя целочисленная часть приводит к исключению.
Проверка переполнения приводит к замедлению операций. При уверенности, что типа результата хватит для его записи проверку переполнения можно отключить настройкой decimal_check_overflow. В этом случае при переполнении вернется неверное значение:
Переполнения происходят не только на арифметических операциях, но и на операциях сравнения. Отключать проверку стоит только при полной уверенности в корректности результата:
Стандартные типы данных (MySQL)
Примечания
Числа
DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
«Неупакованное» число с плавающей точкой. Ведет себя подобно столбцу CHAR, содержащему цифровое значение. Термин «неупакованное» означает, что число хранится в виде строки и при этом для каждого десятичного знака используется один символ. Разделительный знак десятичных разрядов, а также знак `-‘ для отрицательных чисел не учитываются в M (но место для них зарезервировано). Если атрибут D равен 0, величины будут представлены без десятичного знака, т.е. без дробной части. Максимальный интервал значений типа DECIMAL тот же, что и для типа DOUBLE, но действительный интервал для конкретного столбца DECIMAL может быть ограничен выбором значений атрибутов M и D. Если указан атрибут UNSIGNED, отрицательные значения недопустимы. Если атрибут D не указан, его значение по умолчанию равно 0. Если не указан M, его значение по умолчанию равно 10. В более ранних, чем MySQL 3.23, версиях параметр M должен содержать в себе место для знака числа и десятичного знака. DEC[(M[,D])] [UNSIGNED] [ZEROFILL] и NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL] являются синонимами для DECIMAL.
DECIMAL эквивалентно DECIMAL(10,0).
Время
DATE
Дата. Поддерживается интервал от ‘1000-01-01’ до ‘9999-12-31’. MySQL выводит значения DATE в формате ‘YYYY-MM-DD’, но можно установить значения в столбец DATE, используя как строки, так и числа.
DATETIME
Комбинация даты и времени. Поддерживается интервал от ‘1000-01-01 00:00:00’ до ‘9999-12-31 23:59:59’. MySQL выводит значения DATETIME в формате ‘YYYY-MM-DD HH:MM:SS’, но можно устанавливать значения в столбце DATETIME, используя как строки, так и числа.
TIMESTAMP[(M)]
Временная метка. Интервал от ‘1970-01-01 00:00:00’ до некоторого значения времени в 2037 году. MySQL выводит значения TIMESTAMP в форматах YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD или YYMMDD в зависимости от значений M: 14 (или отсутствующее), 12, 8, или 6; но можно также устанавливать значения в столбце TIMESTAMP, используя как строки, так и числа. Столбец TIMESTAMP полезен для записи даты и времени при выполнении операций INSERT или UPDATE, так как при этом автоматически вносятся значения даты и времени самой последней операции, если эти величины не введены программой. Можно также устанавливать текущее значение даты и времени, задавая значение NULL. Параметр M влияет только на способ вывода столбца TIMESTAMP; для хранения его значений всегда используется 4 байта. Следует учитывать, что столбцы TIMESTAMP(M), где M равно 8 или 14, представляют собой числа, в то время, как столбцы TIMESTAMP(M) с иным значением параметра M являются строками. Это убеждает, что можно надежно сделать дамп и восстановить таблицу с этими типами столбцов!
TIMESTAMP эквивалентно TIMESTAMP(14).
TIME
Время. Интервал от ‘-838:59:59’ до ‘838:59:59’. MySQL выводит значения TIME в формате ‘HH:MM:SS’, но можно устанавливать значения в столбце TIME, используя как строки, так и числа.
YEAR[(2|4)]
Год в двухзначном или четырехзначном форматах (по умолчанию формат четырехзначный). Допустимы следующие значения: с 1901 по 2155, 0000 для четырехзначного формата года и 1970-2069 при использовании двухзначного формата (70-69). MySQL выводит значения YEAR в формате YYYY, но можно задавать значения в столбце YEAR, используя как строки, так и числа (тип данных YEAR недоступен в версиях, предшествующих MySQL 3.22).
YEAR эквивалентно YEAR(4).
Символы
CHAR(M) [BINARY]
Строка фиксированной длины, при хранении всегда дополняется пробелами в конце строки до заданного размера. Диапазон параметра M составляет от 0 до 255 символов (от 1 до 255 в версиях, предшествующих MySQL 3.23). Концевые пробелы удаляются при выводе значения. Если не задан атрибут чувствительности к регистру BINARY, то величины CHAR сортируются и сравниваются как независимые от регистра в соответствии с установленным по умолчанию алфавитом. Атрибут NATIONAL CHAR (или его эквивалентная краткая форма NCHAR) представляет собой принятый в ANSI SQL способ указания, что в столбце CHAR должен использоваться установленный по умолчанию набор символов (CHARACTER). В MySQL это принято по умолчанию. CHAR является сокращением от CHARACTER. MySQL позволяет создавать столбец типа CHAR(0). В основном это полезно, если необходимо обеспечить совместимость с некоторыми старыми приложениями, которые зависят от наличия столбца, но реально эту величину не используют. Кроме того, такая возможность может очень пригодиться в случае, если необходим столбец, который может содержать только 2 значения, а именно CHAR(0) (т.е. столбец, который не определен как NOT NULL, занимает только один бит и принимает только 2 значения: NULL или «»).
CHAR эквивалентно CHAR(1).
VARCHAR(M)
Строка переменной длины. С версии 5.0.3 диапазон параметра M составляет от 0 до 65535 символов. Однако, нужно учесть, что это значение распределяется среди всех данных ряда, не считая BLOB и TEXT, которые идут отдельно. Для UTF-8 максимальная длина данных ряда будет приблизительно в три раза меньше, а именно: 21844.
Что такое decimal в mysql
This section discusses the characteristics of the DECIMAL data type (and its synonyms), with particular regard to the following topics:
Maximum number of digits
The nonstandard MySQL extension to the upper range of DECIMAL columns
M is the maximum number of digits (the precision). It has a range of 1 to 65.
If D is omitted, the default is 0. If M is omitted, the default is 10.
The maximum value of 65 for M means that calculations on DECIMAL values are accurate up to 65 digits. This limit of 65 digits of precision also applies to exact-value numeric literals, so the maximum range of such literals differs from before. (There is also a limit on how long the text of DECIMAL literals can be; see Section 12.22.3, “Expression Handling”.)
Values for DECIMAL columns are stored using a binary format that packs nine decimal digits into 4 bytes. The storage requirements for the integer and fractional parts of each value are determined separately. Each multiple of nine digits requires 4 bytes, and any remaining digits left over require some fraction of 4 bytes. The storage required for remaining digits is given by the following table.
For example, a DECIMAL(18,9) column has nine digits on either side of the decimal point, so the integer part and the fractional part each require 4 bytes. A DECIMAL(20,6) column has fourteen integer digits and six fractional digits. The integer digits require four bytes for nine of the digits and 3 bytes for the remaining five digits. The six fractional digits require 3 bytes.
For a full explanation of the internal format of DECIMAL values, see the file strings/decimal.c in a MySQL source distribution. The format is explained (with an example) in the decimal2bin() function.