Skip to main content

Типы данных и наборы символов

Наборы символов:

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

SHOW CHARACTER SET;

По умолчанию utf 8mb4
varchar(20) character set latinl : при создании таблицы другой набор

набор по-умолчанию для всей таблицы 

create database european_sales character set latinl;

Общая информация

  • M максимальное количество. Для целых - кол-во цифр, для дробных - общее кол-во цифр, для строк макс. кол-во символов
  • D кол-во цифр после запятой, должно быть не больше M-2
  • fsp применимо к дате/времени, определяет точность (кол-во дробной части секунды)
  • при strict mode перебор значения вызывает исключение, при restrictive - максимально возможное значение
Тип Доп. информация

char(255 символов)

varchar(65535)

char(20) 20 символов

char фиксировано, при хранении добавляет справа PAD символы

tinytext(255)

text(65535)

mediumtext(16 млн)

longtext(4 млр)

если больше, то обрежутся
конечные пробелы считаются
при сортировке первые 1024 байта, но можно увеличить
tinytext, text - можно не использовать

tinyint(1)

smallint(2)

mediumint

int

bigint(8)

указано кол-во байтов

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

CREATE TABLE employees (salary INTEGER(5) UNSIGNED);

int максимум 10, поэтому это преобразуется в int(11) 

CREATE TABLE employees (id INT(255));

ZEROFILL заполняет 0 слева. 

CREATE TABLE documents (document_no INT(5) ZEROFILL);
DECIMAL = NUMERIC

фиксированное кол-во цифр. Равно int с коэффициентом деления.

Первая цифра - общее кол-во цифр (M), вторая - кол-во цифр после запятой. Знак неявно добавляется. Т.е. от -9.99 до 9.99 

CREATE TABLE taxes (tax_rate DECIMAL(3, 2));

M < 65, по-умолчанию 10
при переборе ошибка, при выходе за пределы точности - округление по математическим правилам
способ вывода больших чисел с игнором младших цифр 

select truncate(tax_rate * 1000, 0) from taxes;

в агрегатных функциях работает общее ограничение на 64 цифры, вычисление точное. 

float, double

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

CREATE TABLE typed_numbers(
  id TINYINT, 
  float_values FLOAT, 
  decimal_values DECIMAL(3, 2));
INSERT INTO typed_numbers VALUES
  (1, 1.1, 1.1), 
  (2, 1.1, 1.1), 
  (3, 1.1, 1.1);
SELECT * FROM typed_numbers;
	| id | float_values | decimal_values |
	+------+--------------+------------------+
	| 1 | 1.1 | 1.10 |
	| 2 | 1.1 | 1.10 |
	| 3 | 1.1 | 1.10 |
SELECT SUM(float_values), SUM(decimal_values) FROM typed_numbers;
	| SUM(float_values) | SUM(decimal_values) |
	+--------------------+---------------------+
	| 3.3000000715255737 | 3.30 |

 Нельзя напрямую сравнивать в агрегатах, нужно сравнивать разницу ABS(v1 - v2) > 0.1 

SELECT id, SUM(col1) as v1, SUM(col2) as v2 
FROM temp 
GROUP BY id 
HAVING v1 <> v2;

нельзя, внешне одинаковые числа будут разными

битовый тип

column_name BIT(M) 

CREATE TABLE bit_values (val BIT(7));
INSERT INTO bit_values VALUES(b'1011'); - равно VALUES(b'0001011'), в этой нотации b и B равны. 
INSERT INTO bit_values VALUES(0b1011);
INSERT INTO bit_values VALUES(2); - автоматическое преобразование числа в битовую маску

select выводит в виде 0x0A
select bin(...) - без 0 слева
select lpad(bin(...), 7, '0') - привычный вид с 0 слева

date

datetime

timestamp

year

time

00-00-0000 вместо NULL, не отображается 

%а Краткое имя дня недели - Sun, Mon, ...
%b Краткое имя месяца — Jan, Feb, ...
%с Числовое значение месяца (0..11)
%d Числовое значение дня месяца (00..31)
%f Число микросекунд (000000..999999)
%Н Час дня в 24-часовом формате (00..23)
%h Час дня в 12-часовом формате (01..12)
%i Минуты в часе (00..59)
%j День года (001..366)
%М Полное имя месяца (January..December)
%m Числовое значение месяца
%р AM или РМ
%s Число секунд (00..59)
%W Полное имя дня недели (Sunday..Saturday)
%w Числовое значение дня недели (0=Sunday..6=Saturday)
%Y Значение года (четыре цифры)

timestamp зависит от time_zone 

CREATE TABLE datetime_temp(ts TIMESTAMP, dt DATETIME);
INSERT INTO datetime_temp VALUES(NOW(), NOW());
SELECT ts, dt FROM datetime_temp;
	| 2017-10-14 18:10:25 | 2017-10-14 18:10:25 |
SET time_zone = '+03:00';
SELECT ts, dt FROM datetime_temp;
	| 2017-10-14 21:10:25 | 2017-10-14 18:10:25 |

Если сервер MAXDB mode, TIMESTAMP = DATETIME

column_name TIME; 

838:59:59 to 838:59:59 + 6 цифр миллисекунд
некорректное в 00:00:00, нельзя отличить от корректно добавленного 00:00:00