Знайомство з типами даних у SQL
На відміну від мови JavaScript, у мові SQL є сувора типізація. У кожній таблиці кожна колонка має свій власний жорстко фіксований тип даних.
Типів даних дуже багато, але на відміну від мови Java, їх так багато не тому, що є типи даних на всі випадки життя. Бази даних дуже залежить від розміру даних, тому багато типів даних відрізняються один від одного лише довжиною.
Усього типи даних можна розбити на 5 груп:
- Числові типи
- Строкові типи
- Типи для зберігання дати та часу
- Об'єкти: зазвичай представлені як набір байт
- Транспортні : JSON та XML
Зазвичай різні СУБД мають свої власні типи даних. Кожна СУБД має свою спеціалізацію, тому додавання нових типів даних – дуже поширена річ.
Інша справа, просто додати новий тип даних недостатньо, потрібно додати і функції, які працюватимуть з ним, а також зробити цю роботу зручною і швидкою.
Якщо ти працюватимеш на якійсь промисловій (enterprise) СУБД, то швидше за все тобі доведеться розбиратися з її типами даних та її функціями. Навіщо потрібно буде прочитати 2-5 хороших книжок.
Ми ж у рамках знайомства з SQL розглянемо три основні групи типів даних:
- Числа
- Рядки
- Дати
Числові типи в SQL
У мові SQL числові типи поділяються на три групи:
- Цілі типи
- Числа з фіксованою комою (фіксована кількість знаків після коми)
- Числа з плаваючою комою
Почнемо з цілих чисел . Їх лише 5, і вони можуть бути описані однією таблицею:
# | Ім'я типу | Довжина в байтах | Аналог з Java | Мінімальне значення | Максимальне значення |
---|---|---|---|---|---|
1 | TINYINT | 1 | byte | -128 | 127 |
2 | SMALLINT | 2 | short | -32,768 | 32,767 |
3 | MEDIUMINT | 3 | -8,388,608 | 8,388,607 | |
4 | INT | 4 | int | -2,147,483,648 | 2,147,483,647 |
5 | BIGINT | 8 | long | -2 63 | 2 63-1 |
Типи даних дуже схожі на типи даних в Java, проте тут є ще один тип integer довжиною три байти. Так зроблено задля можливості економити на розмірі.
Далі йдуть типи з плаваючою комою , як і в Java, їх всього два:
# | Ім'я типу | Довжина в байтах | Аналог з Java | Мінімальне значення | Максимальне значення |
---|---|---|---|---|---|
1 | FLOAT | 4 | float | -3.40E+38 | +1.18E+38 |
2 | DOUBLE | 8 | doble | -1.79E+308 | +1.79E+308 |
Знов-таки, нічого нового. Все, як і в Java. Однак, на відміну від Java, у SQL є ще один спеціальний тип – речове число з фіксованою комою. Називається воно DECIMAL.
Зазвичай цей тип використовується зберігання сум грошей. Коли пишеться назва цього типу, після нього зазвичай вказується, скільки в кількості десяткових знаків до коми і після коми. Загальний формат виглядає так:
DECIMAL(всього_знаків, після_комою)
І невеликий приклад:
salary DECIMAL(5,2)
Так ми описали те, що колонка salary може містити цілі числа (максимум 3 знаки до коми) і дрібну частину - 2 знаки після коми.
Максимальна кількість знаків, що підтримує тип DECIMAL, – 65.
Рядкові типи в SQL
Рядки у базі даних можуть зберігатися у двох видах:
- Рядки з фіксованою довжиною
- Рядки зі змінною довжиною
Рядки з фіксованою довжиною задаються типом CHAR :
CHAR(довжина)
Фіксована довжина означає, що всі значення цієї колонки будуть містити строго фіксовану кількість символів.
Приклад рядка з фіксованою довжиною:
country_code CHAR(2)
Рядки зі змінною довжиною задаються типом VARCHAR :
VARCHAR(макс_довжина)
Змінна довжина означає, що це значення даної колонки будуть містити текст будь-якої довжини, але з більше, ніж максимальна довжина.
Приклад рядка зі змінною довжиною:
phone VARCHAR(12)
У рядків із фіксованою довжиною є дуже велика перевага. Якщо клієнт попросив SQL-сервер повернути йому 1,000,000-й рядок з таблиці, а таблиці рядки фіксованої довжини, то, знаючи довжину рядка, можна легко обчислити байти, які стосуються шуканому рядку.
У випадку зі змінною довжиною рядків, так швидко знайти потрібний рядок таблиці не вийде. Згадай швидкість доступу до ArrayList і LinkedList, тут приблизно схожа ситуація.
Давай порівняємо, як зберігатимуться рядки різної довжини в таблиці, залежно від типу даних.
Рядок | CHAR(4) | Байт для зберігання | VARCHAR(4) | Байт для зберігання | |
---|---|---|---|---|---|
'' | '' | 4 | '' | 1 | |
'ab' | 'ab' | 4 | 'ab' | 3 | |
'abcd' | 'abcd' | 4 | 'abcd' | 5 | |
'abcdefgh' | 'abcd' | 4 | 'abcd' | 5 |
Примітка. Тип VARCHAR вимагає на один байт більше за тієї ж довжини, так як він змушений додатково зберігати довжину рядка.
Тимчасові типи в SQL
SQL також має спеціальні типи для зберігання дати та часу. Усього таких типів п'ять:
# | Ім'я типу | Аналог із Java DateTime API | приклад | Мінімальне значення | Максимальне значення |
---|---|---|---|---|---|
1 | DATE | LocalDate | '2022-06-30' | '1000-01-01' | '9999-12-31' |
2 | TIME | LocalTime | 'hh:mm:ss[.fraction]' | '-838:59:59.000000' | '838:59:59.000000' |
3 | DATETIME | LocalDateTime | '1000-01-01 00:00:00.000000' | '9999-12-31 23:59:59.999999' | |
4 | TIMESTAMP | Date | '1970-01-01 00:00:01.000000' | '2038-01-19 03:14:07.999999' | |
5 | YEAR | 1901 | 2155 |
Всі дані у запитах записуються у вигляді рядка – в одинарних лапках. Формат запису йде від більшого до меншого:
- Рік
- Місяць
- День
- Година
- Хвабона
- Секунда
- Частки секунди
Типи DATE, TIME і DATETIME можна вважати аналогами типів з Java DateTme API: LocalDate, LocalTime, LocalDateTime. Логіка приблизно та сама.
Тип TIMESTAMP зберігає дані як мілісекунд, минулих початку 1970 року (стандарт операційної системи UNIX). Саме в такому вигляді їх зберігає тип Date в мові Java.
Ну і нарешті є тип YEAR, довжина якого 1 байт і який зберігає значення від 1 до 255. Тому доступний йому діапазон років - це 1901-2155. Рік 1900 цей тип зберігати неспроможна, оскільки значення 0 використовується для кодування значення NULL.
Зберігання об'єктів у SQL
Для зберігання об'єктів чи текстів великої довжини є особливі типи. Особливо їх розбирати не будемо, але я все ж таки їх перерахую:
# | Ім'я типу | Пояснення |
---|---|---|
1 | TEXT | Використовується для збереження великої довжини текстів. При порівнянні та сортування цього поля використовується тільки перші 100 символів. |
2 | BLOB | Назва розшифровується як Byte Large Object. Зберігається як просто набору байт. Можна використовувати, щоб, наприклад, зберігати в базі даних зображення. |
3 | CLOB | Назва розшифровується як Char Large Object. Використовується для збереження великої довжини текстів. |
4 | ENUM | Дозволяє задати фіксований набір значень і зберігати як значення одне з них. |
5 | SET | Дозволяє задати фіксований набір значень і зберігати як значення будь-яке їхнє підмножина. Зазвичай зберігає їх як бінарну маску. |
Теоретично ти можеш будь-який Java об'єкт серіалізувати у вигляді набору байт і зберегти його в базі даних у тип BLOB. Зберегти об'єкт – не проблема. Як із ним працювати далі?
Припустимо, таблиця зберігає мільйон об'єктів у серіалізованому вигляді – як ти виконуватимеш по них пошук? СУБД лише тоді підтримує певний тип даних, коли надає великий набір функцій до роботи з ним.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ