1. Знайомство з типами даних у SQL
На відміну від мови JavaScript, у мові SQL є строга типізація. У кожній таблиці кожна колонка має свій власний жорстко фіксований тип даних.
Типів даних дуже багато, але на відміну від мови Java, тут їх так багато не тому, що є типи даних на всі випадки життя. Бази даних дуже залежать від розміру даних, тому багато типів даних відрізняються один від одного лише довжиною.
Загалом типи даних можна розбити на 5 груп:
- Числові типи
- Строкові типи
- Типи для зберігання дати та часу
- Об'єкти: зазвичай представлені як набір байт
- Транспортні: JSON та XML
Зазвичай різні СУБД мають власні типи даних. Кожна СУБД має свою спеціалізацію, тому додавання нових типів даних — дуже поширена річ.
Інша справа — просто додати новий тип даних недостатньо: потрібно додати й функції, які будуть з ним працювати, а також зробити цю роботу зручною та швидкою.
Якщо ти працюватимеш на якійсь промисловій (enterprise) СУБД, то швидше за все тобі доведеться розбиратися з її типами даних та її функціями. Для чого потрібно буде прочитати 2-5 хороших книжок.
Ми в рамках знайомства з SQL розглянемо три основні групи типів даних:
- Числа
- Рядки
- Дати
2. Кількісні типи в 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 | -263 | 263-1 |
Типи даних дуже схожі на типи даних у Java, проте тут є ще один тип integer довжиною три байти. Так зроблено для можливості заощаджувати на розмірі.
Далі йдуть типи з плаваючою комою. Як і в Java, їх лише два:
# | Ім'я типу | Довжина в байтах | Аналог з Java | Мінімальне значення | Максимальне значення |
---|---|---|---|---|---|
1 | FLOAT | 4 | float | -3.40E+38 | +1.18E+38 |
2 | DOUBLE | 8 | double | -1.79E+308 | +1.79E+308 |
Знову ж таки, нічого нового. Все як і в Java. Однак, на відміну від Java, у SQL є ще один спеціальний тип — дійсне число з фіксованою комою. Називається воно DECIMAL.
Зазвичай цей тип використовується для зберігання сум грошей. Коли пишеться назва цього типу, після нього як правило вказується, скільки в кількості десяткових знаків до коми і після коми. Загальний формат має такий вигляд:
DECIMAL(всього_знаків, після_коми)
І невеликий приклад:
salary DECIMAL(5,2)
Так ми описали те, що колонка salary може містити цілі числа (максимум 3 знаки до коми) і дробову частину — 2 знаки після коми.
Максимальна кількість символів, яка підтримує тип DECIMAL — 65.
3. Рядкові типи в 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 вимагає на один байт більше за тієї ж довжини, оскільки він змушений додатково зберігати довжину рядка.
4. Тимчасові типи в 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.
5. Зберігання об'єктів у SQL
Для зберігання об'єктів або текстів великої довжини є спеціальні типи. Особливо їх розбирати не будемо, але я все ж таки їх перерахую:
# | Ім'я типу | Пояснення |
---|---|---|
1 | TEXT | Використовується для зберігання текстів великої довжини. При порівнянні та сортуванні цього поля використовуються лише перші 100 символів. |
2 | BLOB | Назва розшифровується як Byte Large Object. Зберігається у вигляді набору байт. Можна використовувати, щоб, наприклад, зберігати в базі даних зображення. |
3 | CLOB | Назва розшифровується як Char Large Object. Використовується для збереження великої довжини текстів. |
4 | ENUM | Дозволяє встановити фіксований набір значень і зберігати як значення одне з них. |
5 | SET | Дозволяє встановити фіксований набір значень і зберігати як значення будь-яку їхню підмножину. Зазвичай зберігає їх як бінарну маску. |
Теоретично ти можеш серіалізувати будь-який Java-об'єкт у вигляді набору байт та зберегти його в базі даних у типі BLOB. Зберегти об'єкт — не проблема. Як із ним працювати далі?
Припустимо, таблиця зберігає мільйон об'єктів у серіалізованому вигляді. Як ти виконуватимеш пошук за ними? СУБД лише тоді підтримує певний тип даних, коли надає великий набір функцій для роботи з ним.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ