Типи даних, interbase, статті, програмування - програмування c, delphi, c #

Незважаючи на те, що типи даних докладно описані в документації (див. [1, гл. 4]), необхідно розглянути ряд понять, які будуть часто використовуватися в наступних розділах книги. Крім викладу відомостей загального характеру будуть розглянуті також приклади використання типів даних в базах даних InterBase та викладені рекомендації по їх використанню і перетворенню. Також детально розглянемо відмінності в типах даних, існуючі 1-м і 3-м діалектах бази даних InterBase.

Типи даних - це базові елементи будь-якої мови програмування або будь-якого сервера СУБД, і InterBase не виняток. Коли ми говоримо, що в базі даних зберігається якась інформація, то повинні завжди чітко усвідомлювати, що ця інформація не може бути повалена в одну велику купу; навпаки, дані повинні бути розсортовані і розкладені по "поличках". Типи даних визначають, що можна покласти на відповідну "поличку", а що не можна. Під "поличками" розуміються насамперед поля таблиць в базі даних (див. Розділ "Таблиці. Первинні ключі і генератори" (ч. 1)), а також змінні всередині тригерів, збережених процедур і т. Д.
Кожен тип даних має набір операцій, які можна виконувати над значеннями цього типу, тому необхідно правильно вибрати тип даних при проектуванні бази даних, що допоможе уникнути багатьох проблем при розробці клієнтських програм.
У InterBase існує 12 типів даних, які здатні задовольнити практично будь-які потреби розробника в зберіганні даних. Ці типи умовно поділяються на 6 наступних груп:

  • для зберігання цілих чисел - INTEGER і SMALLINT;
  • для зберігання дійсних чисел - FLOAT і DOUBLE PRECISION;
  • для чисел з фіксованою точністю - NUMERIC і DECIMAL;
  • для зберігання дати, часу і дати / часу - DATE, TIME і TIMESTAMP;
  • для зберігання символів - CHARACTER (скорочено CHAR) і VARYING CHARACTER (VARCHAR);
  • Для зберігання динамічно розгортаються даних - BLOB.

Також можна поставити діагноз масиви значень елементарних типів, тобто всіх перерахованих типів, крім BLOB.
Більшість типів даних InterBase відповідають типам, визначеним у стандарті SQL92, однак, крім цього, є і власні "родзинки" - масиви елементарних типів даних і BLOB.
Масиви в InterBase можуть містити безліч даних одного типу в одному полі, наприклад можна визначити масив значень типу INTEGER. Причому масиви можуть мати кілька розмірностей!
Тип даних BLOB - це динамічно розширюваний тип даних, назва якого часто розшифровується як Binary Large OBject - "великі двійкові об'єкти". Треба сказати, що BLOB - це винахід розробників InterBase, яке пізніше поширилося і прижилося в усіх сучасних SQL-серверах.

Синтаксис визначення типів даних

Типи даних використовуються для опису полів в таблицях, змінних в тригерах і збережених процедурах. Нижче представлений загальний синтаксис визначення всіх можливих в InterBase типів даних.

Детально властивості типів даних, такі, як розмір, точність і діапазон можливих значень, описані в табл. 4.1 в [1], тому повторюватися тут не будемо. Далі коротко розглянемо основні особливості типів даних і зосередимося на їх можливе застосування.

До цілочисельним типам ставляться SMALLINT і INTEGER. Треба сказати, що SMALLINT є урізану версію INTEGER і має довжину 2 байта, на відміну від 4 байт, що виділяються для зберігання INTEGER. Зазвичай економити на дисковому просторі не слід, і тому загальною рекомендацією буде використовувати для зберігання цілих значень тип INTEGER.
Область застосування цілочисельних типів очевидна: вони потрібні для полів, що містять тільки цілі числа - для зберігання лічильників, кількості і т.д. Зазвичай тип INTEGER мають також поля, що містять первинні ключі.

Речові типи даних

До речовим типам (їх ще називають типами чисел з плаваючою точкою) відносяться FLOAT і DOUBLE PRECISION. Відразу слід застерегти читача від використання типу FLOAT - його точність недостатня для зберігання більшості дрібних значень. Особливо не рекомендується зберігати в ньому грошові величини - в змінних типу FLOAT дуже швидко наростають помилки округлення, що може сильно здивувати бухгалтера при підведенні підсумків.
Якщо в базі даних передбачається зберігати числа з плаваючою точкою (наприклад, в бухгалтерських системах або в системах для наукових розрахунків), то кращим вибором буде тип DOUBLE PRECISION.

Треба відзначити, що в 3-му діалекті InterBase для зберігання грошових величин існує механізм зберігання типів з фіксованою точкою довжиною 64 біта. Використання цих типів забезпечує найкращу точність.

Типи даних з фіксованою точкою

До цих типів даних відносяться NUMERIC і DECIMAL. Часто можна почути запитання, чим NUMERIC відрізняється від DECIMAL. Обидва цих типу мають однакову розрядність - від 1 до 18 знаків, однакову точність - від нуля до розрядності.

Нагадаємо, що розрядність - це загальне число цифр в числі, а точність - число знаків після коми

Найцікавіше, що. незважаючи на те що в документації написано, що ці типи відрізняються максимальною розрядністю, насправді реалізовані вони практично однаково і різниці між ними ніякої немає! Ви легко можете це перевірити, запустивши утиліту isql і зробивши нижченаведену черговість дій.
Створюємо таблицю наступного виду:

SQL> CREATE TABLE test (
CON> Num_field NUMERIC (15,2),
CON> Dec_field DECIMAL (15,2));

Потім даємо команду показати структуру таблиці:

SQL> show tables test;

І спостерігаємо таку картину:

NUM_FIELD NUMERIC (15, 2) Nullable
DEC_FIELD NUMERIC (15, 2) Nullable

Як бачите. InterBase повідомляє про те. що обидва даних стовпці мають тип NUMERIC!
Причини такої поведінки лежать в реалізації типів даних з фіксованою точкою. Справа в тому, що InterBase має всього 3 механізму зберігання будь-якого цілочисельного виразу, і всі типи, як би вони не називалися, наводяться до цих варіантів реалізації.
Ось таблиця з [1], яка ілюструє, як зберігаються різні цілочисельні типи (табл. 1.1). Як бачите, зберігання даних в 3-м діалекті відрізняється для чисел з великою розрядністю:
Табл 1.1. Зберігання чисел з фіксованою точкою

Отже, тепер ми точно можемо сказати, чим відрізняються типи NUMERIC і DECIMAL: в разі визначення поля (змінної) з малою розрядністю (до чотирьох) перший зберігається у вигляді 2 байтового цілого числа SMALLINT, а другий - у вигляді 4 байтового INTEGER.
Таким чином, в разі розрядності, більшою чотирьох, типи DECIMAL і NUMERIC виявляться абсолютно еквівалентними!
Зверніть увагу на відмінність реалізації типів з великою розрядністю в 1-м і 3-м діалектах. У 1-му діалекті число з фіксованою точкою перетворювалося з цілого в реальне, до якого застосовувалися механізми округлення! У 3-му діалекті ця дивина була ліквідована - великі цілі числа зберігаються дійсно як цілі - з використанням механізму INT64, який може зберігати 64-бітові числа в діапазоні +/- 2 Л 32. Тому рекомендується зберігати дані про грошові кошти в базах даних, створених з використанням 3-го діалекту, - тільки при використанні механізму INT64 можна гарантувати збереження малих грошових залишків.

Типи для зберігання дати та часу

Типи для зберігання дати та часу змінилися в версії InterBase 6.x і його клонах в порівнянні з 4.x і 5.x. Щоб не плутатися в історичних хитросплетіннях з цими типами, розглянемо ситуацію саме в 6-й версії InterBase, а потім на основі цього коротко згадаємо про те, що було раніше, - це робиться для тих користувачів, хто все ще працює на ранніх версіях InterBase
Отже, в InterBase 6.x існує 3 типи для зберігання дати та часу - це DATE, TIME і ТГМЕ8ТАМР.

Як працювати з датами? Якщо мова йде про роботу на рівні сервера в збережених процедурах або тригерах, то все досить просто - ми завжди можемо оголосити змінну потрібного нам типу і привласнювати їй значення з таблиць і навпаки. Однак необхідно передавати дані з бази даних в додаток і назад. В цьому випадку є два підходи - або використовувати бібліотеки, які застосовують оригінальний формат дат InterBase для доступу до об'єктів цих типів і перетворять цей формат в звичні внутрімовні типи дати / часу (прикладом такої бібліотеки є FIBPlus), або використовувати механізм перетворення дат в рядки, вбудований в InterBase.
Що робити, якщо потрібно вирізати з повною дати тільки рік або місяць? Для цього використовується група функцій EXTRACT (доступна у всіх клонах InterBase 6.x), яка дозволяє виділити з дати тільки потрібну частину. Використовуються ці функції наступним чином:

EXTRACT (MONTH FROM DATE_FIELD)
EXTRACT (YEAR FROM DATE_FIELD)

Повний список параметрів в функції EXTRACT такий: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, WEEKDAY, YEARDAY. Їх призначення очевидно випливає з їх назви, тому не будемо наводити тут розшифровки.

Типи даних для зберігання тексту

У InterBase існує два типи, призначених для зберігання текстової інформації - CHAR і VARCHAR. Повні їх назви, - CHARACTER і CHARACTER VARYING, однак немає ніякої причини користуватися довгими іменами - навіть команда Show tables в утиліті isql видає короткі найменування типів.
Щоб визначити поле або змінну символьного типу, необхідно в дужках після імені типу або вказати число символів, яке буде використовуватися в обумовленому об'єкті, або опустити число символів - при цьому буде створено поле з довжиною 1 символ.

CREATE TABLE testCHARLen (
Fieldl CHAR (255),
Field2 CHAR);

В результаті створення цієї таблиці поле Fieldl матиме довжину 255 символів, a Field2 - 1 символ.
Типи CHAR і VARCHAR багато в чому схожі - обидва можуть містити до 32768 символів, проте є і відмінності. Хоча зберігаються ці два типи в базі даних однаково, але працює з ними InterBase по-різному. Це можна продемонструвати наступним прикладом:

SQL> create table testCHAR (cl char (10), c2 varchar (10));
SQL> insert into testCHAR (cl, c2) values ​​( 'Test', 'Test');
SQL> SELECT '

В результаті отримаємо наступний результат:

CREATE TABLE TestCHARSET (
Fieldl VARCHAR (255),
Field2 VARCHAR (255) CHARACTER SET winl251);

Тип даних BLOB

CREATE TABLE testBLOB (
myBlobField BLOB);

В результаті буде створено поле myBlobField, в якому можна зберігати дані великого розміру. Але незважаючи на те що поля BLOB за способом визначення ніяк не відрізняються від інших, реалізація їх усередині бази даних значно відрізняється. He-BLOB-поля розташовані на сторінці даних (див. Розділ "Структура бази даних InterBase" (ч. 4)) поруч один з одним, а в разі BLOB на сторінці даних зберігається тільки ідентифікатор BLOB, а сам BLOB розташовується на спеціальній сторінці. Саме така організація даних дозволяє зберігати дані нефіксованого розміру.
У типу BLOB є можливість визначати набір декількох підтипів і спеціальних процедур, які називаються фільтрами (BLOB filters), для роботи з цими підтипами. Існує кілька визначених підтипів BLOB, які вбудовані в InterBase. Всі ці підтипи мають невід'ємні номера, наприклад subtype 0 - це дані невизначеного типу, subtype 1 - текст, subtype 2 - BLR (Binary Language Representation, см. Глосарій і главу "Структура бази даних InterBase") і т. Д. Користувач також може визначати свої підтипи BLOB, які можуть мати негативні значення. Кожному типу може бути поставлений у відповідність фільтр, який перетворює поле цього підтипу в інший підтип.
Треба відзначити, що використання BLOB-полів зазвичай служить альтернативою зберігання зовнішніх щодо бази даних файлів. Що стосується фільтрів BLOB, то вони використовуються досить рідко через свою орієнтацію на вузький клас задач.

СУБД InterBase була однією з перших, в якій з'явилися масиви. Підтримка масивів в базі даних є розширенням традиційної реляційної моделі. Наявність масивів дозволяє спростити роботу з множинами даних одного типу.
Масив - це сукупність значень одного типу, що має загальне ім'я і дозволяє звернутися до будь-якого елементу масиву по його номеру. Масиви в InterBase можуть бути одновимірними і багатовимірними.
Для того щоб створити в таблиці поле типу масив чисел INTEGER, необхідно написати щось на кшталт такого:

CREATE TABLE test (
myOneDimArray INTEGER [12],
myTwoDimArray INTEGER [5,4],
myThreeDimArray INTEGER [2,10,8]);

При цьому створяться 3 поля типу масив: поле myOneDimArray, що містить одновимірний масив довжиною 12 чисел, myTwoDimArray, що містить двовимірний масив (матрицю) 5x4 чисел Integer, і поле myThreeDimArray - тривимірний масив 2x10x8. Треба відзначити, що при такому визначенні елементи масиву нумеруються починаючи з одиниці, т. Е. Перший елемент має номер 1, другий - номер 2 і т. Д. Якщо хтось хоче вказати межі масиву самостійно, наприклад з 0 до 5, то він повинен задати визначення поля так:

Масиви реалізовані на базі полів типу BLOB, тому не слід побоюватися, що багатовимірний масив "забруднить" вашу таблицю неймовірною кількістю даних: InterBase акуратно розмістить дані масиву на окремих сторінках, щоб оптимізувати операції введення-виведення в цих полях.
Як використовувати масиви? Вони надають зручний механізм для зберігання однотипних об'єктів. Однак в 80% випадків замість масивів розробники вважають за краще тримати множинні дані в підлеглих (detail) таблицях, тому масиви не так часто використовуються в клієнтських додатках СУБД InterBase. Цьому чимало сприяє те, що поставляються в комплекті з Delphi і C ++ Builder бібліотеки доступу, такі, як BDE і ГВХ, не мають можливості працювати з масивами. У документації по InterBase згадується про можливість працювати з масивами за допомогою препроцесора gpre, однак це не найзручніший спосіб для розробника Delphi / C-H-Builder. На щастя, в бібліотеці FIBPlus є підтримка полів-масивів в InterBase, про що докладно розказано в розділі "Спеціальні можливості FIBPlus". Клієнтська бібліотека IBProvider, що дозволяє створювати клієнтські програми для InterBase за допомогою засобів розробки компанії Microsoft, також підтримує роботу з масивами (див. Розділ "Розробка клієнтських додатків СУБД InterBase з використанням технології Microsoft OLE DB" (ч. 3)).

Треба відзначити, що неможливо розповісти про типи даних, які не забігаючи вперед, - настільки вони проникають в усі ключові області, пов'язані з розробкою додатків баз даних. Тому в процесі читання цієї книги варто використовувати дану главу як довідник, до якого можна звертатися щоразу, коли треба освіжити в пам'яті основи InterBase.

Схожі статті