Свойство | Значение | Комментарий |
TQuery | ||
RequestLive | True | Можно обновлять таблицу в сетке и передавать обновления в БД |
DatabaseName | Student | Условное имя БД (alias) |
Name | Q1 | Имя этого компонента |
SQL | Select * from P | SQL - оператор |
TDataSource | ||
DataSet | Q1 | Имя компонента TQuery, связанного с БД |
Name | DS1 | Имя этого компонента |
TDBGrid | ||
DataSource | DS1 | Имя компонента TDataSource |
TDBNavigator | ||
DataSource | DS1 | Имя компонента TDataSource |
VisibleButtons | nbFirst, … | Список разрешенных кнопок для перемещения по таблице |
Компоненты верхних слоев ссылаются на имена компонентов в нижних слоях.
Компонент TTable предназначен для доступа к единственной таблице файл-серверной СУБД, а TQuery - к любому количеству таблиц в клиент-серверной СУБД.
Обычно TTable используется в навигационном режиме для обработки единичных строк в таблице, а TQuery - для групповых операций с помощью SQL.
Оба компонента могут открыть набор данных методом Open или двоичным свойством Active и закрыть методом Close или тем же свойством Active.
Для просмотра и изменения НД обычно используются компоненты: TDBNavigator, TDBGrid и др., которые автоматически вызывают нужные методы компонентов TTable и TQuery.
Примеры программного доступа к НД:
Пример 1: Изменение в БД
Q1 : TQuery;
...
Q1.Open; // Открыть НД - выполнить оператор SQL SELECT
...
Q1.Edit; // Перевести в режим редактирования
Q1.FieldByName('gorod').AsString := 'Москва';
// Столбец 'Gorod' интерпретируется как строка
// Клетке присваивается значение 'Москва'
Q1.Post; // Запомнить изменения в БД
...
Q1.Close; // Закрыть НД
Существуют другие типы-свойства:
AsBoolean : Boolean;
AsDataTime : TDataTime;
AsFloat : double;
AsInteger : integer;
Пример 2: Изменение БД с подтверждением
if Q1.Modified then // НДбылизменен?
if MessageDlg('Записать?', mtConfirmation[mbYes,mbNo],0) = mrYes then
Q1.Post; // Запомнить изменения в БД
Свойство Modified принимает значение true, если хотя бы одна клетка НД была изменена пользователем.
Пример 3: Подсчет суммы значений в столбце
var
sum : integer;
begin
sum := 0;
Q1.Open;
Q1.First; // Переход к 1-ой строке
while not Q1.EOF do
begin
sum := sum + Q1.FieldByName('ves').AsInteger;
Q1.Next;
end;
Q1.Close;
...
end;
Некоторые особенности класса TQuery
1) Свойство SQL может содержать только один оператор SQL, хотя в нем могут упоминаться несколько таблиц.
2) Операторы SELECT из этого свойства выполняются методом Open, а операторы INSERT, DELETE и UPDATE методом ExecSQL.
Например:
а)
with Query1 do
begin
Close; { закрыть НД }
SQL.Clear; { удалить предыдущий оператор SQL }
SQL.Add('SELECT * FROM P'); { задать новый оператор SQL }
Open; { будет выполнять этот оператор SQL }
end;
б)
with Query1 do
begin
Close; { закрыть НД }
SQL.Clear; { удалить предыдущий оператор SQL }
SQL.Add('DELETE FROM S'); { задать новый оператор SQL }
ExecSQL; { выполняет другой оператор SQL, помимо SELECT }
end;
3) Свойство RequestLive задает желание изменять данные в БД путем навигации и правки НД, т.е. правки результата оператора SELECT.
Однако истина (true) в свойстве RequestLive не гарантирует, что правка будет разрешена. Для разрешения требуется, кроме того:
а) обращаться только к одной таблице;
б) не применять часть ORDER BY;
в) не применять функции вида SUM, AVG и пр.;
г) не применять вычисляемые столбцы.
4) При любых значениях свойств RequestLive и CanModify изменять БД можно операторами UPDATE, INSERT, DELETE и методом ExecSQL.
5) Изменяющийся оператор SQL можно построить двумя способами:
а)
var
x : string[10];
...
with Query1 do
begin
Close; { закрытьНД }
SQL.Clear; { удалить предыдущий оператор SQL }
SQL.Add('SELECT * FROM P WHERE ves='+x); { задать новый оператор SQL }
Open; { будет выполнять этот оператор SQL }
end;
x - строковая переменная, содержащая заданный пользователем вес детали.
б) Пусть свойство SQL содержит оператор с двумя параметрами:
SELECT * FROM P WHERE gorod=:Gor AND ves=:Massa
тогда с помощью метода ParamByName можно дать параметру некоторое значение.
Пример:
var
Town, x : string[30];
...
with Query1 do
begin
Close; { закрыть НД }
SQL.Clear;
SQL.Add('SELECT * FROM P WHERE gorod=:Gor AND ves=:Massa');
ParamByName('Gor').Value := Town;
ParamByName('Massa').Value := x;
Open; { будет выполнять оператор SQL }
end;
6) Пусть свойство SQL содержит оператор, который возвращает одиночный результат. Например: SELECT SUM(kapital) FROM S;
Этот результат удобно извлекать с помощью метода FieldByName.
Пример:
var
Y : string[30];
...
with Query1 do
begin
Close;
Open;
Y := FieldByName('SUM(kapital)').Value; { или .AsString }
Label1.Caption := Y;
end;
Компоненты для односвязной формы
Такая форма содержит одну связь и две таблицы: главную и подчиненную.
Таблицы связаны между собой через столбцы, имеющие одинаковые значения в строках. Связь между таблицами возможна только по тем столбцам, которые имеют индексы.
Для такой формы нужны следующие компоненты:
TTable - для каждой таблицы по 1 шт.
TDataSource - для каждой таблицы по 1 шт.
TDBGrid - для каждой таблицы по 1 шт.
TDBNavigator - 1 шт. (общая)
Основные свойства этих компонент
Свойство | Значение | Комментарий |
T1:TTable (главная таблица) | ||
DatabaseName | Student | Условное имя БД (alias) |
Name | T1 | Имя этого компонента |
TableName | SP | Имя таблицы (поставок) |
DS1:TDataSource (главная таблица) | ||
DataSet | T1 | Имя компонента TTable, связанного с БД |
Name | DS1 | Имя этого компонента |
Grid1:TDBGrid (главная таблица) | ||
DataSource | DS1 | Имя компонента TDataSource |
T2:TTable | ||
DatabaseName | Student | Условное имя БД (alias) |
Name | T2 | Имя этого компонента |
TableName | S | Имя таблицы (поставщиков) |
MasterSource | DS1 | Имя компонента TDataSource, связанного с главной таблицей (источник данных главной таблицы) |
IndexFieldNames | Nomer | Имя столбца индекса в подчиненной таблице |
MasterFields | Nomer_s | Имя связующего столбца из главной таблицы |
DS2:TDataSource (подчиненная таблица) | ||
DataSet | T2 | Имя компонента TTable, связанного с БД |
Name | DS2 | Имя этого компонента |
Grid2:TDBGrid (подчиненная таблица) | ||
DataSource | DS2 | Имя компонента TDataSource |
TDBNavigator | ||
DataSource | DS1 | Имя главного компонента TDataSource |
Тема 16. Обработка исключительных ситуаций
Исключительная ситуация – это событие, прерывающее нормальное выполнение программы. Иначе говоря, исключительная ситуация является ошибкой, возникающей во время выполнения программы.
В ObjectPascal определены две конструкции для работы с исключительными ситуациями.
Блок try … except
Блок try … except используется для реакции на конкретную исключительную ситуацию.
try
statement1;
statemant2;
…
except
on Exception1 do statemant3;
on Exception2 do statemant4;
…
else statementN
end;
Если при выполнении операторов, расположенных в разделе try, не возникает исключительная ситуация, то обращения к разделу except вообще не происходит.
Если в разделе try возникает исключительная ситуация, то управление сразу передается разделу except.
Раздел except содержит набор операторов on … do, определяющих реакцию на исключительные ситуации. Между ключевыми словами on и do указывается имя класса исключительной ситуации. Оператор, расположенный после слова do, предназначен для ее обработки.
Исключительные ситуации, возникающие во время выполнения программы, описываются в языке ObjectPascal с помощью специального объектного типа Exception. На базе этого типа определен ряд дочерних классов, соответствующих наиболее типичным исключительным ситуациям.
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c: double;
begin
TRY
a:=StrToInt(Edit1.Text);
b:=StrToInt(Edit2.Text);
c:=a/b;
ShowMessage ('Результат ='+FloatToStr(c));
EXCEPT on EZeroDivide do ShowMessage ('Ошибкаделенияна 0');
on EConvertError do ShowMessage ('Неверныйформатчисла');
END;
end;
Блок try … finally
Блок try … finally используется в тех случаях, когда необходимо выполнить некоторые действия даже в случае возникновения исключительной ситуации.
try
statement1;
statement2;
…
finally
statement3;
statement4;
…
statementN;
end;
В данной конструкции сначала выполняются операторы, расположенные в разделе try. Если при их выполнении не возникло исключительной ситуации, то выполняются операторы, расположенные в разделе finally. Если же при выполнении операторов в разделе try возникает исключительная ситуация, то управление сразу передается первому оператору раздела finally.