Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Перед тем как начинать писать программу создади...docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
934.6 Кб
Скачать

Перед тем как начинать писать программу создадим источник данных, с которым мы будем работать. Для этого в меню «Пуск» выбираем «Справка и поддержка». В появившемся окне напротив слова «Найти» пишем «ODBC» и нажимаем на кнопку со стрелкой.

Далее выбираем Использование компонента «Источник данных(ODBC)», затем «Источник данных (ODBC)».

В появившемся окне нажимаем кнопку «Добавить».

Далее выбираем «SQLServer» и нажимаем «Готово».

В следующем окне вводим имя источника данных и выбираем имя сервера, затем нажимаем «Далее».

В следующем окне мы оставляем все как есть и нажимаем «Далее».

Затем необходимо выбрать БД, если вы ничего не создавали, то по умолчанию используется БД master и нажимаем «Далее».

Следующее окно мы оставляем без изменения и нажимаем «Готово».

Нажимаем «OK».

Мы создали источник данных.

Создайте новый проект в Builder . Сохраните модуль формы в отдельном каталоге под именем uMyODBC, а проект - под именем ODBC. Имя формы myODBC.

Для нормальной работы с драйвером ODBC в наш проект необходимо подключить следующие библиотеки: odbc32.lib, odbccp32.lib. Для этого в главном меню выбираем «Project» / «Add to Project» и из списка файлов по очереди добавляем нужные нам библиотеки(библиотеки можно спросить у преподавателя или скачать самим из интернета).

Также в заголовочный файл модуля uMyODBC надо добавить следующие директивы препроцессора:

#include <sql.h>

и в uMyODBC.cpp:

#define WIN32

#include <sql.h>

#include <sqlext.h>

#include <odbcinst.h>

#include <sysutils.hpp>

#define SQL_API_SQLPARAMOPTION 33

#include <Grids.hpp>

В разделе «private» заголовочного файла модуля uMyODBC объявите структуру с двумя переменными типа String:

struct PolyaTab{

String pole1;

String pole2;

};

Для начала создадим несколько функций, которые помогут нам при работе с ODBC.

void Start(SQLHENV &hEnv,SQLHDBC &hDbc,TMemo * Memo) – создает идентификатор среды и соединения, инициализирует интерфейс ODBC, загружает драйвер базы данных и устанавливает соединение с источником данных.

Описание параметров для данной функции:

hEnv – идентификатор среды;

hDbc – идентификатор соединения;

DNS – имя источника данных;

Memo – многострочное поле для вывода сообщений о ходе работы программы.

Теперь создадим данную функцию. Для этого выделяем класс TmyODBC, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

void TmyODBC::Start(SQLHENV &hEnv,SQLHDBC &hDbc,char *DNS,TMemo * Memo)

{

char *USER = "SQL_NTS";

char *PASS = "SQL_NTS";

SQLRETURN Retcode;

Retcode=SQLAllocEnv(&hEnv);

if (Retcode == SQL_SUCCESS || Retcode == SQL_SUCCESS_WITH_INFO)

{

Memo->Lines->Add("Среда успешно создана");

Retcode = SQLAllocConnect(hEnv,&hDbc);

if(Retcode == SQL_SUCCESS || Retcode == SQL_SUCCESS_WITH_INFO)

{

Memo->Lines->Add("Соединение успешно создано");

Retcode=SQLConnect(hDbc,DNS,lstrlen(DNS),USER,lstrlen(USER),PASS,lstrlen(PASS));

if (Retcode == SQL_SUCCESS || Retcode == SQL_SUCCESS_WITH_INFO)

{

Memo->Lines->Add("Подконектилось успешно");

}else

Memo->Lines->Add("Подконектиться не получилось");

}

else

Memo->Lines->Add("Соединение не создано");

}

else

Memo->Lines->Add("Среда не создана");

}

void Stop(SQLHENV &hEnv,SQLHDBC &hDbc,TMemo * Memo) – закрывает соединение с источником данных, освобождает идентификатор соединения и всю связанную с ним память, освобождает идентификатор среды, а также всю назначенную ему память.

Параметры такие же, как и у предыдущей функции, только без DNS.

Теперь создадим данную функцию. Для этого выделяем класс TmyODBC, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

void TmyODBC::Stop(SQLHENV &hEnv,SQLHDBC &hDbc,TMemo * Memo)

{

SQLRETURN Retcode;

Retcode=SQLDisconnect(hDbc);

if (Retcode==SQL_SUCCESS)

Memo->Lines->Add("Дисконект успешно");

else

Memo->Lines->Add("Дисконект не успешно");

Retcode=SQLFreeConnect(hDbc);

if (Retcode==SQL_SUCCESS)

Memo->Lines->Add("Соединение удалилось успешно");

else

Memo->Lines->Add("Соединение не удалилось");

Retcode=SQLFreeEnv(hEnv);

if (Retcode==SQL_SUCCESS)

Memo->Lines->Add("Среда удалилась успешно");

else

Memo->Lines->Add("Среда не удалилась");

}

void SqlExecutePrepare(SQLHDBC hDbc,SQLHSTMT hStmt,String zapros,TMemo * Memo) – создает идентификатор оператора, выполняет SQL запрос и освобождает идентификатор оператора.

Описание параметров для данной функции:

hDbc – идентификатор соединения;

hStmt – идентификатор оператора;

zapros – SQL запрос;

Memo – многострочное поле для вывода сообщений о ходе работы программы.

Теперь создадим данную функцию. Для этого выделяем класс TmyODBC, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

void TmyODBC::SqlExecutePrepare(SQLHDBC hDbc,SQLHSTMT hStmt,String zapros,TMemo * Memo)

{

SQLRETURN Retcode;

Retcode=SQLAllocStmt(hDbc,&hStmt);

if (Retcode==SQL_SUCCESS)

{

Retcode=SQLPrepare(hStmt,zapros.c_str(),lstrlen(zapros.c_str()));

if (Retcode==SQL_SUCCESS)

{

Retcode=SQLExecute(hStmt);

if (Retcode==SQL_SUCCESS)

{

Memo->Lines->Add("Запрос : ");

Memo->Lines->Add(zapros);

Memo->Lines->Add("успешно выполнен");

}

else

{

Memo->Lines->Add("Запрос : ");

Memo->Lines->Add(zapros);

Memo->Lines->Add("не выполнен");

}

}

}

SQLFreeStmt(hStmt,SQL_CLOSE);

}

void SelectGetData(SQLHDBC hDbc,SQLHSTMT hStmt,String zapros,TMemo * Memo,TStringGrid *StringGrid) –выполняет выборку всех данных из таблицы для 9 столбцов и выводит результат в String Grid.

Описание параметров для данной функции:

hDbc – идентификатор соединения;

hStmt – идентификатор оператора;

zapros – SQL запрос;

Memo – многострочное поле для вывода сообщений о ходе работы программы;

StringGrid – таблица, содержащая строки.

Теперь создадим данную функцию. Для этого выделяем класс TmyODBC, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

void TmyODBC::SelectGetData(SQLHDBC hDbc,SQLHSTMT hStmt,String zapros,TMemo * Memo,TStringGrid *StringGrid)

{

int R, C;

for (R = 1; R < StringGrid->RowCount; R++)

{

for (C = 0; C < StringGrid->ColCount; C++)

StringGrid->Cells[C][R] = "";

}

StringGrid->RowCount=2;

StringGrid->ColCount=9;

SQLRETURN Retcode;

int j=1;

Retcode = SQLAllocStmt(hDbc,&hStmt);

SQLCHAR sqf1[50],sqf2[50],sqf4[50],sqf8[50],sqf9[50];

SQLCHAR sqf3;

SQLSMALLINT sqf5;

SQLREAL sqf6,sqf7;

SQLINTEGER ValueLenOrInd1 ,ValueLenOrInd2,ValueLenOrInd3,ValueLenOrInd4,ValueLenOrInd5,ValueLenOrInd6,ValueLenOrInd7,ValueLenOrInd8,ValueLenOrInd9;

Retcode = SQLExecDirect(hStmt, zapros.c_str(), SQL_NTS);

if (Retcode == SQL_SUCCESS) {

while (TRUE) {

Retcode = SQLFetch(hStmt);

if (Retcode == SQL_ERROR || Retcode == SQL_SUCCESS_WITH_INFO) {

}

if (Retcode == SQL_SUCCESS || Retcode == SQL_SUCCESS_WITH_INFO){

SQLGetData(hStmt, 1, SQL_C_CHAR, &sqf1, 50, &ValueLenOrInd1);

SQLGetData(hStmt, 2, SQL_C_CHAR, &sqf2, 50, &ValueLenOrInd2);

SQLGetData(hStmt, 3, SQL_C_DEFAULT, &sqf3, sizeof(sqf3),&ValueLenOrInd3);

SQLGetData(hStmt, 4, SQL_C_CHAR, &sqf4, 50, &ValueLenOrInd4);

SQLGetData(hStmt, 5, SQL_C_DEFAULT, &sqf5, sizeof(sqf5),&ValueLenOrInd5);

SQLGetData(hStmt, 6, SQL_C_FLOAT, &sqf6, sizeof(sqf6),&ValueLenOrInd6);

SQLGetData(hStmt, 7, SQL_C_FLOAT, &sqf7, sizeof(sqf7),&ValueLenOrInd7);

SQLGetData(hStmt, 8, SQL_C_CHAR, &sqf8, 50,&ValueLenOrInd8);

SQLGetData(hStmt, 9, SQL_C_CHAR, &sqf9, 50,&ValueLenOrInd9);

AnsiString a1,a2,a4,a5,a6,a7,a8,a9,a10;

a1.printf("%s",sqf1);

a2.printf("%s",sqf2);

a4.printf("%s",sqf4);

a5=IntToStr(sqf5);

a6=FloatToStr(sqf6);

a7=FloatToStr(sqf7);

a8.printf("%s",sqf8);

a9.printf("%s",sqf9);

Memo->Lines->Add("Из таблицы postov "+a1+" "+a2+ " "+sqf3+" "+a4+" "+a5+" "+a6+" "+a7+" "+a8+" "+a9);

StringGrid->Cells[0][j]=a1;

StringGrid->Cells[1][j]=a2;

StringGrid->Cells[2][j]=sqf3;

StringGrid->Cells[3][j]=a4;

StringGrid->Cells[4][j]=a5;

StringGrid->Cells[5][j]=a6;

StringGrid->Cells[6][j]=a7;

StringGrid->Cells[7][j]=a8;

StringGrid->Cells[8][j]=a9;

j++;

StringGrid->RowCount++;

} else {

break;

}

}

}

StringGrid->RowCount--;

SQLFreeStmt(hStmt,SQL_CLOSE);

}

TmyODBC::PolyaTab TmyODBC::SqlExecRetS(SQLHDBC hDbc,SQLHSTMT hStmt,String zapros,TMemo * Memo,TStringGrid *StringGrid) – предназначена для работы с курсором, возвращает структуру содержащую 2 переменные типа String - поля таблицы, ее первичный ключ.

Описание параметров для данной функции:

hDbc – идентификатор соединения;

hStmt – идентификатор оператора;

zapros – SQL запрос;

Memo – многострочное поле для вывода сообщений о ходе работы программы;

StringGrid – таблица, содержащая строки.

Теперь создадим данную функцию. Для этого выделяем класс TmyODBC, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

TmyODBC::PolyaTab TmyODBC::SqlExecRetS(SQLHDBC hDbc,SQLHSTMT hStmt,String zapros,TMemo * Memo,TStringGrid *StringGrid)

{

SQLRETURN Retcode;

PolyaTab s;

int j=1;

Retcode = SQLAllocStmt(hDbc,&hStmt);

SQLCHAR sqf1[50],sqf2[50],sqf4[50],sqf8[50],sqf9[50];

SQLCHAR sqf3;

SQLSMALLINT sqf5;

SQLREAL sqf6,sqf7;

SQLINTEGER ValueLenOrInd1 ,ValueLenOrInd2,ValueLenOrInd3,ValueLenOrInd4,ValueLenOrInd5,ValueLenOrInd6,ValueLenOrInd7,ValueLenOrInd8,ValueLenOrInd9;

Retcode = SQLExecDirect(hStmt, zapros.c_str(), SQL_NTS);

if (Retcode == SQL_SUCCESS) {

Memo->Lines->Add("Запрос "+zapros+" успешно выполнен");

while (TRUE) {

Retcode = SQLFetch(hStmt);

if (Retcode == SQL_ERROR || Retcode == SQL_SUCCESS_WITH_INFO) {

}

if (Retcode == SQL_SUCCESS || Retcode == SQL_SUCCESS_WITH_INFO){

SQLGetData(hStmt, 1, SQL_C_CHAR, &sqf1, 50, &ValueLenOrInd1);

SQLGetData(hStmt, 2, SQL_C_CHAR, &sqf2, 50, &ValueLenOrInd2);

AnsiString a1,a2,a4,a5,a6,a7,a8,a9,a10;

a1.printf("%s",sqf1);

a2.printf("%s",sqf2);

s.pole1=a1;

s.pole2=a2;

Memo->Lines->Add("Из таблицы postov SqlExecRetS "+s.pole1+" "+s.pole2);

j++;

} else {

break;

}

}

} else Memo->Lines->Add("Запрос "+zapros+" не выполнен");

SQLFreeStmt(hStmt,SQL_CLOSE);

return s;

}

void TmyODBC::SetCur(TmyODBC::PolyaTab h,TStringGrid * StringGrid) – устанавливает курсор таблицы String Grid на строку у которой значение первых двух столбцов (значение первичного ключа) совпадает со значением переменных структуры h.

Описание параметров для данной функции:

h – структура, содержащая две переменных типа String;

StringGrid – таблица, содержащая строки.

Теперь создадим данную функцию. Для этого выделяем класс TmyODBC, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

void TmyODBC::SetCur(TmyODBC::PolyaTab h,TStringGrid * StringGrid)

{

int nomer;

int count=StringGrid->RowCount;

for (int i=1;i<=count;i++){

if (StringGrid->Cells[0][i]==h.pole1 && StringGrid->Cells[1][i]==h.pole2)

nomer=i;

}

if (nomer<count)

StringGrid->Row=nomer;

}

Теперь добавим в проект новую форму. Сохраните модуль формы в том же каталоге, что и проект под именем uMainForm. Установите свойства главной формы в следующие значения:

Name – MainForm;

Caption - Выполнение операторов SQL в ODBC;

Position – poScreenCenter.

Эта форма должна будет появляться на экране при запуске программы. Для этого выберете в главном меню «Project»/«Options» закладка «Forms», в строке «Main form» впишите MainForm , далее перенесите myODBC из «Auto-create» forms в «Available forms», чтобы она не появлялась на экране при запуске программы.

Еще нам нужно подключить к новому модулю модуль uMyODBC. Для этого в заголовочном файле модуля uMainForm надо добавить следующую директиву препроцессора :

#include "uMyODBC.h". Теперь в разделе private добавляем следующее:

TmyODBC * MyODBC;

Также в заголовочный файл модуля uMainForm надо добавить следующие директивы препроцессора:

#include <sql.h>

и в uMainForm.cpp:

#define WIN32

#include <sql.h>

#include <sqlext.h>

#include <odbcinst.h>

#include <sysutils.hpp>

#define SQL_API_SQLPARAMOPTION 33

В разделе «private» заголовочного файла модуля uMyODBC объявите следующие переменные:

SQLHENV hEnv;

SQLHDBC hDbc;

SQLHSTMT hStmt;

SQLRETURN Retcode;

Int SelectedStroka;

На главную форму перенесите следующие компоненты:

StatusBar со страницы Win32;

Panel со страницы Standard.

Установите свойства компонента TPanel в следующие значения:

Align – alBottom;

Name – Panel;

Caption - .

На панельку со страницы Standard перенесите 12 компонентов Button.Установите их свойства в следующие значения:

1)Name – buStart;

Caption – Пуск;

2)Name – buSelect;

Caption – Выборка;

3) Name – buFirst;

Caption – Первая;

4)Name – buPrior;

Caption – Предыдущая;

5) Name – buNext;

Caption – Следующая;

6)Name – buLast;

Caption – Последняя;

7) Name – buDelete;

Caption – Удалить;

8)Name – buUpdate;

Caption – Модифицировать;

9)Name – buAdd;

Caption – Добавить;

10) Name – buInsert;

Caption – Вставить.

11) Name – buStop;

Caption – Стоп;

12)Name – buExit;

Caption – Выход;

На главную форму перенесите Memo со страницы Standard. Этот компонент будет нужен для отображения хода работы программы, что-то вроде журнала сообщений.

Установите свойства компонента Memo в следующие значения:

Align – alBottom;

Name – Memo, а также удалите все строки в свойстве Lines.

На главную форму перенесите еще одну панельку Panel со страницы Standard.

Установите свойства компонента Panel в следующие значения:

Align – alTop;

Name – Panel1;

Caption - .

На панельку со страницы Standard перенесите 1 компонент Button и 1 компонент ComboBox.Установите их свойства в следующие значения:

А)Для кнопки:

1)Name – buExec;

Caption – Выполнить ;

Б)Для ComboBox:

Name – cbZapros.

Добавим в cbZapros несколько запросов, которые нам понадобятся в дальнейшем. Для этого в свойстве Items этого компонента надо нажать на кнопку с тремя точками. В появившемся окне мы добавляем следующие строчки:

CREATE TABLE postov(p_name_firmy_postavchika VARCHAR(50) NOT NULL , p_name_firmy_potrebitelya VARCHAR(50) NOT NULL CONSTRAINT PK PRIMARY KEY (p_name_firmy_postavchika,p_name_firmy_potrebitelya) , p_tovarniy_kredit BIT , p_name_tovara VARCHAR(50) , p_kol_vo_ed_tovara SMALLINT CHECK (p_kol_vo_ed_tovara>0 AND p_kol_vo_ed_tovara<100), p_ves_ed_tovara FLOAT , p_cena_ed_tovara FLOAT , p_plategnye_rekvizity VARCHAR(50), p_data_otgruzky VARCHAR(50));

INSERT INTO postov (p_name_firmy_postavchika,p_name_firmy_potrebitelya, p_tovarniy_kredit,p_name_tovara,p_kol_vo_ed_tovara,p_ves_ed_tovara,p_cena_ed_tovara, p_plategnye_rekvizity,p_data_otgruzky)VALUES('ИВТ','АЛМАЗ',1,'Холодильник',90,100.5,60000,'Кураева 1а,1212232123','10/10/08');

INSERT INTO postov (p_name_firmy_postavchika,p_name_firmy_potrebitelya, p_tovarniy_kredit,p_name_tovara,p_kol_vo_ed_tovara,p_ves_ed_tovara,p_cena_ed_tovara, p_plategnye_rekvizity,p_data_otgruzky)VALUES('ИВТ','КРИСТАЛ',1,'Утюг',80,3.3,20000,'Кураева 1а,1212232123','10/10/08');

INSERT INTO postov (p_name_firmy_postavchika,p_name_firmy_potrebitelya, p_tovarniy_kredit,p_name_tovara,p_kol_vo_ed_tovara,p_ves_ed_tovara,p_cena_ed_tovara, p_plategnye_rekvizity,p_data_otgruzky)VALUES('ИВТ','РУБИН',0,'Пылесос',50,7.4,30000,'Кураева 1а,1212232123','10/10/08');

drop table postov

Необходимо, чтобы каждый запрос был на отдельной строчке.

Первая строчка и последняя – это запрос на создание и удаление таблицы, все остальные для вставки данных в таблицу.

На главную форму перенесите StringGrid со страницы Additional.

Установите свойства компонента StringGrid в следующие значения:

Align – alClient;

Name – StringGrid1;

Options/goRowSizing – true;

Options/goColSizing – true;

Options/goEditing – true;

Options/goRowSelect – true;

FixedCols – 0;

ColCount – 2;

RowCount – 2;

DefaultColWidth – 130.

Теперь переходим к написанию обработчиков событий. Выделите мышкой кнопку «Пуск», перейдите на страничку Events инспектора объектов и дважды щелкните по событию OnClick. В редакторе кода откроется пустой обработчик этого события, в который необходимо ввести операторы:

void __fastcall TMainForm::buStartClick(TObject *Sender)

{

MyODBC->Start(hEnv,hDbc,"my_source",Memo1);

buStart->Enabled=false;

buSelect->Enabled=true;

buFirst->Enabled=true;

buPrior->Enabled=true;

buNext->Enabled=true;

buLast->Enabled=true;

buDelete->Enabled=true;

buUpdate->Enabled=true;

buAdd->Enabled=true;

buInsert->Enabled=true;

buStop->Enabled=true;

buExit->Enabled=false;

buExec->Enabled=true;

}

Выделите мышкой кнопку «Стоп», перейдите на страничку Events инспектора объектов и дважды щелкните по событию OnClick. В редакторе кода откроется пустой обработчик этого события, в который необходимо ввести операторы:

void __fastcall TMainForm::buStopClick(TObject *Sender)

{

cbZapros->Text="";

int R, C;

for (R = 0; R < StringGrid1->RowCount; R++)

{

for (C = 0; C < StringGrid1->ColCount; C++)

StringGrid1->Cells[C][R] = "";

}

StringGrid1->RowCount=2;

StringGrid1->ColCount=2;

MyODBC->Stop(hEnv,hDbc,Memo1);

buStart->Enabled=true;

buSelect->Enabled=false;

buFirst->Enabled=false;

buPrior->Enabled=false;

buNext->Enabled=false;

buLast->Enabled=false;

buDelete->Enabled=false;

buUpdate->Enabled=false;

buAdd->Enabled=false;

buInsert->Enabled=false;

buStop->Enabled=false;

buExit->Enabled=true;

buExec->Enabled=false;

}

Выделите мышкой кнопку «Выход», перейдите на страничку Events инспектора объектов и дважды щелкните по событию OnClick. В редакторе кода откроется пустой обработчик этого события, в который необходимо ввести операторы:

void __fastcall TMainForm::buExitClick(TObject *Sender)

{

Close();

}

При нажатие на кнопку «Выполнить» будет выполняться sql запрос, который пользователь выберет в ComboBoxe. Выделите мышкой кнопку «Выполнить», перейдите на страничку Events инспектора объектов и дважды щелкните по событию OnClick. В редакторе кода откроется пустой обработчик этого события, в который необходимо ввести операторы:

void __fastcall TMainForm:: buExecClick (TObject *Sender)

{

MyODBC->SqlExecutePrepare(hDbc,hStmt,cbZapros->Text,Memo1);

}

Добавим в класс TMainForm новый метод. Для этого выделяем класс TMainForm, нажимаем правой кнопкой мыши и в появившимся меню выбираем New Method …

Далее заполняем появившееся окно в соответствии с рисунком:

В редакторе кода напишем содержание функции:

void TMainForm::Select()

{

MyODBC->SqlExecutePrepare(hDbc,hStmt,"close mycursor",Memo1);

MyODBC->SelectGetData(hDbc,hStmt,"select * from postov",Memo1,StringGrid1);

MyODBC->SqlExecutePrepare(hDbc,hStmt,"DECLARE mycursor SCROLL CURSOR for select * from postov",Memo1);

MyODBC->SqlExecutePrepare(hDbc,hStmt,"open mycursor",Memo1);

MyODBC->SqlExecutePrepare(hDbc,hStmt,"FETCH first from mycursor",Memo1);

}

Выделите мышкой кнопку «Выборка», перейдите на страничку Events инспектора объектов и дважды щелкните по событию OnClick. В редакторе кода откроется пустой обработчик этого события, в который необходимо ввести операторы: