Створення бази даних на порожньому місці

Після того як ви розібралися, як повязані поля в базі даних, логічно було б навчитися обєднувати поля в базу даних, чи не так Звичайно, саме цього ви й домагаєтеся Зрештою, все, що вам треба зробити, – це вибрати каталог бази даних, встановити коректне імя, додати кілька полів і встановити властивість Active в true, правда Дійсно, ви не так далекі від правди Напевно трапиться ситуація, коли вам знадобиться створювати базу даних відповідно до вимог користувача, які не можна дізнатися заздалегідь Вилов помилок, перевірка баз даних та інші типи додатків вимагають від вас надання користувачу права визначати бази даних у тому вигляді, в якому вони повинні фігурувати в додатку, замість того виду, який постулював якийсь програміст (або, не дай Бог, проектувальник баз даних) Звичайно, вам як і раніше доведеться пізніше писати код для завантаження поля з даними, але, принаймні, сам процес створення CBuilder може зробити блискавичним

У новому прикладі ми створимо додаток, що дозволить вам, виступаючому в ролі користувача, визначати схему бази даних Поля будуть додавати ся в таблицю, імя та каталог встановлюватися, база даних створюватися – і все в декількох десятках рядках коду При цьому велика частина цих рядків належить швидше до інтерфейсу з користувачем, ніж до створення бази

На рис 73 показана форма, яку ми будемо використовувати для створення баз даних Зверніть увагу на кілька важливих моментів По-перше, на формі немає компонентів, що сприймають дані (якщо вам так вже цікаво, зазначу, що сітка, що лежить на формі, відноситься до TStringGrid) Немає їх тому, що ми не збираємося використовувати основоположні керуючі елементи для баз даних CBuilder в інтерфейсі цієї форми Все, що ми будемо робити, буде робитися на низькому рівні доступу до баз даних Крім того, як можна бачити, на формі немає обєкта TTable Ми будемо використовувати TTable для створення бази даних, але в цьому прикладі ми його створимо динамічно, щоб ви зрозуміли, як це робиться

Ми повинні додати в код форми ту ж саму таблицю опис / код, що і в попередньому прикладі У тому останньому прикладі, якщо ви памятаєте, обєкт field definitions використовувався для вказівки користувачеві на опис полів У теперішньому прикладі ми збираємося використовувати опис полів для того, щоб користувач міг вибрати з них тип поля, А ми потім могли поставити йому у відповідність тип дійсного (фізичної) поля для безпосереднього опису поля в таблиці Отже, додайте наступний код в початок вихідного файлу Unit1cpp

Рис 73 Форма додатка створення баз даних

typedef struct

{

Db::TFieldType nCode char *strDesc

} DbFieldType

DbFieldType sFieldTypes[] =

{

{FtUnknown, Невідомо чи не визначено},

{FtString, Символьне або строкове поле},

{FtSmallint, 16-бітове ціле поле},

{FtInteger, 32-бітове ціле поле},

{FtWord, 16-бітове беззнаковое ціле поле},

{FtBoolean, Логічне поле},

{FtFloat, Поле чисел з плаваючою точкою},

{FtCurrency, Грошове поле},

{FtBCD, Двійково-кодоване десяткове поле},

{FtDate, Поле дати},

{FtTime, Поле часу}, Глава 7 • Робота з базами даних

{FtDateTime, Поле дати і часу},

{FtBytes, Фіксована кількість байт (двійкове подання)},

{FtVarBytes, Змінна кількість байт (двійкове подання},

{FtAutoInc, Автоматично збільшується 32-бітове ціле поле лічильника},

{FtBlob, Поле Binary Large Object (великий двійковий обєкт)},

{FtMemo, Поле memo (рядок необмеженої довжини)},

{FtGraphic, Поле растрового малюнка},

{FtFmtMemo, Поле форматованого memo},

{FtParadoxOle, Поле Paradox OLE},

{FtDBaseOle, Поле dBase OLE},

{FtTypedBinary, типізувати двійкове поле},

}

У додавання до списку ми також повинні знати, скільки ж у ньому елементів, для того щоб мати можливість додати його в комбінований список нижче в коді Ми могли б просто використовувати числове значення, рівне кількості елементів у списку (22), але це призведе до можливості появи в майбутньому помилок, повязаних з додаванням або видаленням елементів зі списку при незмінному числовому значенні На наше щастя препроцесор CBuilder дозволяє нам застосувати корисну хитрість Додайте наступний рядок коду прямо після масиву елементів структури:

#define NumberOfFieldTypes (sizeof(sFieldTypes)/sizeof\ (sFieldTypes[0]))

Можливо, вам доводилося бачити подібні рядки в коді, з яким ви працювали Можливо, ви колись самі писали щось подібне Оператор sizeof повертає розмір, в байтах, змінної, переданої йому як аргумент

У разі масиву елементів структури кожен елемент має свій специфичес кий розмір (зазвичай 8 байт, але це залежить від компілятора) Розмір специфичес кого елемента проте, якщо поділити на нього твір розмірів, дозволить отримати загальне кількість елементів Формула буде виглядати приблизно так:

int nTotalEntries = (nNumberOfEntries * nSizeOfOneEntry) / nSizeOfOneEntry

Цей код, як можуть засвідчити ті з вас, хто сильний в математиці, зводиться до тотожності nTotalEntries = nTotalEntries Це все, що ми використовуємо в блоці #define, Описаному вище, не піклуючись про те, чому дорівнюють nNumberOfEntries і nSizeOfOneEntry Чудова штука, цей оператор sizeof

Наступне, що нам треба зробити, – це навести порядок в системі Нам треба змінити конструктор форми, вставивши туди обєкт TTable, який ми будемо використовувати, а також дещо прибрати з цього обєкта, щоб його дійсно можна було використовувати для створення таблиці Додайте наступний код в конструктор обєкта Form1

Розбираємося у внутрішньому устрої базданних

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

Table = new Table(this) Table-&gtActive = false Table-&gtFieldDefs-&gtClear() Table-&gtIndexDefs-&gtClear()

}

Як видно з наведеного вище коду, ми створюємо обєкт TTable в конструкто ре форми Тоді це дозволить нам пізніше використовувати його безпосередньо Строго кажучи, виклики Clear для масивів описів полів та індексів не є тут необхідними, оскільки ці обєкти при створенні за замовчуванням є порожніми Однак хорошою практикою буде не покладатися ні на що при роботі з обєктами Точно так же обєкт TTable створюється з властивістю Active, Встановлений ним в false Все ж, щоб підстрахуватися і не залежати від передумов про вірність ініційованих за умовчанням значень, ми самі встановлюємо все, що потрібно в конструкторі

Ініціалізується все самі

Наступним кроком написання нашої програми буде ініціалізація сітки і комбінованого списку, щоб вони виглядали коректно прямо з моменту запуску програми Для цього додайте новий обробник для події форми OnCreate і у відповідний метод FormCreate додайте наступний код:

void __fastcall TForm1::FormCreate(TObject *Sender)

{

StringGrid-> ColCount = 5 StringGrid-> Cells [0] [0] = Поле; StringGrid-> Cells [1] [0] = Імя; StringGrid-> Cells [2] [0] = Тип; StringGrid-> Cells [3] [0] = Довжина;

StringGrid-> Cells [4] [0] = Обовязкове; StringGrid-> RowCount = 1

/ / Завантажуємо комбінований список

for (int i=0 i&ltNumberOfFieldTypes ++i) ComboBox-&gtItems-&gtAdd(sFieldTypes[i]strDesc)

}

}

Все, що ми тут робимо, – це встановлюємо правильні заголовки стовпців, кількість стовпців і рядків (1 – для верхнього рядка) для сітки Після цього ми додаємо опису типів полів у комбінований список типів полів Описи ми беремо зі структури, яку додали в вихідний файл трохи раніше

Отже, ми можемо бачити перед собою форму, що містить порожню сітку і комбінований список описів типів полів, підтримуваних системою Сліду

ющее, що нам треба зробити, – це надати користувачеві можливість додавати поля в базу даних (і відображати їх за допомогою сітки)

Процес додавання нового поля в таблицю виглядає приблизно таким чином Спочатку користувач вводить імя поля і його розмір у відповідних полях введення і вибирає тип поля з комбінованого списку Після цього користувач натискає кнопку Додати, щоб поле було додано в таблицю Насправді з базою даних нічого не відбувається до тих пір, поки користувач не введе каталог бази даних і імя таблиці і не натисне кнопку Створити Однак, як ми скоро побачимо, закулісні події відбуваються і тоді, коли користувач додає одиничне поле в нову базу

Для додавання нового поля в базу нам треба дочекатися моменту, коли користувач натисне кнопку Додати Як тільки це відбудеться, ми починаємо діяти Додайте обробник події для кнопки Додати (Подія – натискання кнопки) У відповідний метод форми Button2Click додайте наступні рядки:

//————————————————————————————

void __fastcall TForm1::Button2Click(TObject *Sender)

{

char szBuffer[ 80 ]

strcpy (szBuffer, Edit2-&gtTextc_str())

unsigned short nSize = (unsigned short)atoi(szBuffer)

/ / Перевіряємо, чи потрібно здавати розмір

if (sFieldTypes[ComboBox1-&gtItemIndex]nCode = ftString) nSize = 0

/ / Встановлюємо опису полів

Table1-&gtFieldDefs-&gtAdd(Edit1-&gtText, sFieldTypes[ComboBox1-&gtItemIndex], nCode, nSize, CheckBox1-&gtChecked)

/ / Переходимо до наступного рядка

StringGrid1-&gtRowCount++

/ / Тепер заповнюємо сітку даними

int nRow = StringGrid1-&gtRowCount-1 StringGrid1-&gtCells[0][nRow] = AnsiString(nRow) StringGrid1-&gtCells[1][nRow] = Edit1-&gtText StringGrid1-&gtCells[2][nRow] = sFieldTypes[ComboBox1-&gtItemIndex]strDesc StringGrid1-&gtCells[3][nRow] = Edit2-&gtText

if (CheckBox1-&gtChecked) StringGrid1-&gtCells[4][nRow] = &quotYes" else

StringGrid1-&gtCells[4][nRow] = &quotNo"

}

У цьому коді ми спочатку отримуємо необхідну інформацію від різних елементів форми Поле редагування імені використовується безпосередньо при додаванні опису поля в базі Обраний елемент комбінованого списку (індекс якого можна знайти у властивості ItemIndex комбінованого списку) використовується для знаходження дійсного типу поля в структурі, що зберігає дані про відповідність типів полів їх описам А ось перетворення поля розміру на даний момент є досить сміливим експериментом

Є дві важливі речі, які треба відзначити при роботі з полем розміру По-перше, ніколи не передавайте текст для поля редагування прямо в функцію, навіть використовуючи метод c_str() обєкта TEdit При цьому небезпечно змінювати рядок прямо в поле обєкта TEdit З цієї причини ми копіюємо рядок у звичайний символьний буфер і використовуємо його для отримання розміру поля

Другим важливим аспектом, що стосуються додавання розміру полю, є дилема – дозволений розмір чи ні Для всіх полів, крім полів строкового (символьного) типу, розмір не тільки не використовується, а й Не дозволяється для використання Якщо ви дозволите користувачеві ввести розмір для НЕ строкового поля і передасте його в метод Add обєкта field definitions, То отримаєте помилку, сгенерированную обєктом, і метод не буде виконаний З цієї причини ми перевіряємо тип поля перед тим, як додати розмір, й у не строкових типів встановлюємо розмір (який, до речі, типу unsigned short, а не int) в 0

Після того як поле благополучно добавлено в структуру бази даних, інформація про нього відображається у сітці, і користувач може продовжувати вводити інші поля

Ми можемо дещо полегшити життя користувачу, перевіривши, допустимо для вибраного ним типу поля завдання розміру чи ні Давайте перевіримо це і опрацюємо результат, відповідно зробивши недоступним для редагування (disable) поле введення розміру для випадку вибору типу поля без розміру (числові та ін)

Додайте у форму новий обробник для події OnChange (При зміні) комбінованого списку Наступний код додайте в метод ComboBox1Change форми:

void __fastcall TForm1::ComboBox1Change(TObject *Sender)

{

if (sFieldTypes[ComboBox1-&gtItemIndex]nCode = ftString)

{

Edit2-&gtEnabled = false

}

else

Edit2-&gtEnabled = true

}

На даний момент користувач, швидше за все, вже додав в базу кілька полів і готовий створити базу даних на диску в каталозі і файлі, які він вибрав для нової таблиці Отже, все готово – прийшло час створити базу даних безпосередньо з програми Я знаю, що саме цього коду ви і чекали, затамувавши подих, і не буду більше мучити вас очікуванням

Додайте наступний код в метод Button1Click (Button1 – кнопка Створити, служить для створення бази даних):

void __fastcall TForm1::Button1Click(TObject *Sender)

{

/ / Встановлюємо назву бази даних і імя таблиці

Table1-&gtDatabaseName = Edit3-&gtText Table1-&gtTableName = Edit4-&gtText

/ / Встановлюємо тип таблиці в dBase Table1-> TableZType = ttDBase

/ / Створюємо таблицю

Table1-&gtCreateTable()

/ / Видаляємо обєкт

delete Table1

/ / Повідомляємо користувача MessageBox1 (NULL, База даних створена”, Підтвердження, MB_OK)

/ / Закриваємо додаток

Application-&gtTerminate()

}

Ви, мабуть, здивовані, як мало рядків коду залучено в процес створення бази Я, в усякому разі, був здивований, коли вперше спробував створити базу даних у своїй реальній програмі Моя програма була дещо довше, оскільки я напхав її обробкою помилок користувача, адже я не міг допустити, щоб система видала користувачеві повідомлення про помилку Але проте основний код був такий же, і при першому запуску працював він просто відмінно, та й при всіх наступних теж

Перший крок у процесі створення бази даних – це присвоєння імені бази даних і таблиці Це визначає, де ж насправді на диску буде створена база Ви можете ввести будь-яке припустиме назву каталогу і файлу, в тому числі і мережевий каталог Після присвоєння імен нам треба встановити тип створюваної бази даних Система CBuilder за замовчуванням вміє створювати таблиці dBase і Paradox З відповідною ODBC-драйвером ви можете створювати також

інші типи таблиць

Після того як база даних була успішно створена (зверніть увагу, що в коді прикладу немає перевірки можливих помилок, яку вам обовязково треба буде здійснювати в ваших додатках), обєкт TTable видаляється, щоб уникнути втрати памяті в системі, а користувач сповіщається про створення бази Після цього додаток закривається Теоретично, вам не обовязково припиняти роботу програми в цей момент Ви могли б створити і ініціалізувати новий обєкт TTable і дозволити користувачеві створювати багато баз даних за один запуск програми Однак для першого прикладу ми застосовуємо найпростіший метод виходу

От і все створення бази даних під час виконання програми Визначте поля, надайте шлях і імя файлу і дозвольте обєктам VCL CBuilder зробити всю іншу роботу Швидко і просто, що й було потрібно

Джерело: Теллес М – Borland C + + Builder Бібліотека програміста – 1998

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*