- 1
- 2
- 3
- 4
- . . .
- последняя (6) »
возник вопрос. Все сработало, файл базы создался, но на фейсе программы ничего не изменилось.
- Да, вот тут, ты прав. Недоработка. Но, я тоже обдумал… надо ввести изменения.
165 try
170 IBDatabase1.CreateDatabase;
180 IBDatabase1.Connected:=True;
190 IBTransaction1.Active:=True;
192 except
194 ShowMessage('Не нахожу dll');
195 exit;
196 end; // try
187 FMain.Caption := fn;
198 ShowTables;
200 end;
- Во-первых давай позаботимся о том, чтобы исключительное положение, которое у нас возникло, было бы хоть как ни будь обработано ( строки 165, 192-196).
- Строка 198 выдаст название новой базы в заголовке программы и сообщит что таблиц, в этой базе пока нет.
procedure ShowTables;
begin
with FMain.ListBox1 do
begin
Clear;
Items.Add('Empty');]
end;
end;
- Сразу скажу, что процедуру ShowTables мы очень скоро будем существенно менять, посему не буду нумеровать строки…
- * -
* Все сработало, но…
- Да, хвалится пока еще нечем. Надо делать следующий шаг.
010 procedure TFMain.OpenDB1Click(Sender: TObject); 020 begin 030 with OpenDialog1 do 040 begin 050 Filter := 'DB|*.fdb'; 060 DefaultExt := 'fdb'; 070 if Execute then 080 with DataModule2 do 090 begin 100 IBDatabase1.DatabaseName:= FileName; 110 IBDatabase1.Params.Clear; 120 IBDatabase1.Params.Add('USER Cats'); 130 IBDatabase1.Params.Add('PASSWORD forever'); 140 try 150 IBDatabase1.Connected:=True; 160 except 170 ShowMessage('Не могу работать!'); 180 exit; 190 end; // try 200 IBTransaction1.Active:=True; 210 FMain.Caption := FileName; 220 ShowTables; 230 end; // DataModule2 240 end; // OpenDialog1 250 end; - Открываем диалог загрузки файла – стр. 30 - Т.к. этот диалог будет использоваться и в других целях в строках 50, 60 уточняем, что сейчас будет речь идти о базе данных. - Если в стр. 70 файл базы найден, вводим параметры базы строки 100-130 (обрати внимание пароль и пользователь должен быть тот же, что и при создании базы). - Наученные опытом в строках 140-190 пытаемся соединится с базой. (обрати внимание на стр. 190 – желательно кончики программных блоков помечать – легче будет разбираться). * А почему ты изменил 170 строку. - Искл. состояние может возникнуть не только из-за dll, но и в случае если база будет не родная (не совпадает пароль и др.) т.е. это место надо переписать более тщательно, сделаем это позже. * Нет ничего более постоянного … - Согласен, давай изменим строку 160 160 except // в дальнейшем обработать 1. отсутствие dll. 2. несовпадение пароля 3. другие случаи - Теперь пришла пора для вкусненького. * Погоди, сбегаю за кетчупом. - Боюсь, ни клаве ни монитору кетчуп не понравится. - Открою тебе великую тайну: - Когда мы создали пустую базу. База там уже есть. * Я что-то подобное подозревал, файл то не очень маленький. - Да, в этом файле есть служебная база в которой будут хранится сведения о нашей базе. * База о базе. Логично. Ведь логичное же, что директор завода Жигулей ездит на Мерседесе. - Переписываем ShowTables: - procedure ShowTables(fn:string); begin FMain.Caption := fn; with FMain.ListBox1 do begin Clear; PrintList('select DISTINCT R.RDB$RELATION_NAME '+ 'from RDB$RELATION_FIELDS R '+ 'where R.RDB$SYSTEM_FLAG = 0 order by R.RDB$RELATION_NAME'); end; end; * Опять нет нумерации, значит это тоже временно. - Совершенно точно. А теперь функция PrintList: 010 function PrintList( iSQL:string):boolean; 020 begin 030 with DataModule2.IBSQL1 do 040 begin 050 result := false; 060 Close; 070 SQL.Clear; 080 SQL.Add(iSQL); 090 ExecQuery; 100 if RecordCount = 0 then 110 begin 120 FMain.ListBox1.Items.Add('Empty'); 130 result := true; 140 exit; 150 end; 160 while not EOF do 170 begin 180 FMain.ListBox1.Items.Add( trim(Fields[0].AsString)); 190 Next; 200 end; // while 210 end; 220 end; - PrintList выполняет (стр. 90) наш первый SQL запрос (стр. 80). В случае, когда осмысленного ответа нет (стр. 100-150) выдается надпись - 'Empty' т.е. базы нет, а иначе (стр. 160-200) выдаем список таблиц в нашей базе. * А что за страшную строку получает PrintList получает как параметр. - Это тот самый запрос и есть. Пока разбирать его не будем. - * - (уточнение, “- * -“ равняется банке пива) - Ну как, чего ты такой… * Опять, не работает. - Привыкай к тяготам лишениям нашей службы… - Ну что там у нас * Operation cancelled at user's request - Н-да, и что характерно, каждый раз на этом месте… - Так, у компонента IBDatabase1 измени свойство LoginPrompt на False. И будет тебе счастье. - * - * Ну, что, сразу нельзя было сказать? - Забыл, бывает… - Как, заработало? * Да, но гора родила мышь. Ввели много дополнительных слов, а результат тот же. - Ничего, скоро мышка превратится в кошку, затем в собачку а там и до крокодила недалеко. * Не п*ди, что будем делать дальше? - Дальше?
- Для начала, что попроще. - На закладке History помести TMemo – во всю ее ширину и высоту, да, назови это дело His. - А на закладке SQL надо расположить тоже TMemo (у меня оно названо Memo1) и для начала пару кнопок “Run SQL” и “Clear SQL”. - Теперь делаем процедуры кнопок: procedure TFMain.Button1Click(Sender: TObject); begin // кнопка run SQL RunSQL( MakeSQL); end; * Опять временно? - Ну, не хочу тебя сразу пугать, все по очереди. - Обрати внимание на комментарий к слову begin – рекомендую так подписывать процедуру, если название ее мало информативно. * А вторая кнопка? - Ну, даже неудобно… procedure TFMain.Button2Click(Sender: TObject); begin Memo1.Clear; end; * Да, проще некуда. Так теперь по очереди RunSQL( MakeSQL); - Недавно переделал, довольно много повкалывал с этими 30 строками… 010 function RunSQL( S:string):boolean; 020 var 030 b : boolean; // отслеживание ошибки 040 Mistake : string; // сообщение ошибки 050 begin 060 with DataModule2.IBSQL1 do 070 begin 080 Close; 090 SQL.Clear; 100 SQL.Add(S); 110 try 120 ExecQuery; // попытка выполнения запроса 130 b := true; // ошибки нет 140 except // Обработка ошибки 150 on E: Exception do 160 begin 170 b := false; // к сожалению, ошибка 180 Mistake := E.ClassName+' raised exception: '+E.Message; 190 end; 200 end; // try 210 end; // with DataModule2 220 result := not b; 230 if b 240 then 250 begin // запрос выполнен 260 Hi.Lines.Add('ok'); 270 Memo1.Clear; // и переход на закладку History 280 if DataModule2.IBSQL1.SQLType = SQLSelect 290 then PrintSELECT(S) // распечатка результата запроса SELECT 300 else PageControl1.ActivePageIndex := 3; 310 end 320 else 330 begin // была ошибка 340 ShowMessage(Mistake); // сообщение об ошибке 350 Hi.Lines.Add('Error'); 360 Hi.Lines.Add(Mistake); // запись в историю 370 end; 380 Hi.Lines.Add('------------'); 390 end; - Самое интересное происходит, когда запрос НЕ выполняется. * Прочитал, все понятно, и над чем тут было биться? - Все понятно? Отлично, объясни тогда строки 280, 290. * Так, интересно. Определяется тип запроса и если это SELECT. Нечестно, ты еще ничего не сказал о PrintSELECT. - Давай, это исправим: 010 procedure PrintSELECT(S:string); 020 var 030 i : integer; 040 a : string; 050 LHTML : TStringList; 060
Задача: открыть существующую базу данных.
010 procedure TFMain.OpenDB1Click(Sender: TObject); 020 begin 030 with OpenDialog1 do 040 begin 050 Filter := 'DB|*.fdb'; 060 DefaultExt := 'fdb'; 070 if Execute then 080 with DataModule2 do 090 begin 100 IBDatabase1.DatabaseName:= FileName; 110 IBDatabase1.Params.Clear; 120 IBDatabase1.Params.Add('USER Cats'); 130 IBDatabase1.Params.Add('PASSWORD forever'); 140 try 150 IBDatabase1.Connected:=True; 160 except 170 ShowMessage('Не могу работать!'); 180 exit; 190 end; // try 200 IBTransaction1.Active:=True; 210 FMain.Caption := FileName; 220 ShowTables; 230 end; // DataModule2 240 end; // OpenDialog1 250 end; - Открываем диалог загрузки файла – стр. 30 - Т.к. этот диалог будет использоваться и в других целях в строках 50, 60 уточняем, что сейчас будет речь идти о базе данных. - Если в стр. 70 файл базы найден, вводим параметры базы строки 100-130 (обрати внимание пароль и пользователь должен быть тот же, что и при создании базы). - Наученные опытом в строках 140-190 пытаемся соединится с базой. (обрати внимание на стр. 190 – желательно кончики программных блоков помечать – легче будет разбираться). * А почему ты изменил 170 строку. - Искл. состояние может возникнуть не только из-за dll, но и в случае если база будет не родная (не совпадает пароль и др.) т.е. это место надо переписать более тщательно, сделаем это позже. * Нет ничего более постоянного … - Согласен, давай изменим строку 160 160 except // в дальнейшем обработать 1. отсутствие dll. 2. несовпадение пароля 3. другие случаи - Теперь пришла пора для вкусненького. * Погоди, сбегаю за кетчупом. - Боюсь, ни клаве ни монитору кетчуп не понравится. - Открою тебе великую тайну: - Когда мы создали пустую базу. База там уже есть. * Я что-то подобное подозревал, файл то не очень маленький. - Да, в этом файле есть служебная база в которой будут хранится сведения о нашей базе. * База о базе. Логично. Ведь логичное же, что директор завода Жигулей ездит на Мерседесе. - Переписываем ShowTables: - procedure ShowTables(fn:string); begin FMain.Caption := fn; with FMain.ListBox1 do begin Clear; PrintList('select DISTINCT R.RDB$RELATION_NAME '+ 'from RDB$RELATION_FIELDS R '+ 'where R.RDB$SYSTEM_FLAG = 0 order by R.RDB$RELATION_NAME'); end; end; * Опять нет нумерации, значит это тоже временно. - Совершенно точно. А теперь функция PrintList: 010 function PrintList( iSQL:string):boolean; 020 begin 030 with DataModule2.IBSQL1 do 040 begin 050 result := false; 060 Close; 070 SQL.Clear; 080 SQL.Add(iSQL); 090 ExecQuery; 100 if RecordCount = 0 then 110 begin 120 FMain.ListBox1.Items.Add('Empty'); 130 result := true; 140 exit; 150 end; 160 while not EOF do 170 begin 180 FMain.ListBox1.Items.Add( trim(Fields[0].AsString)); 190 Next; 200 end; // while 210 end; 220 end; - PrintList выполняет (стр. 90) наш первый SQL запрос (стр. 80). В случае, когда осмысленного ответа нет (стр. 100-150) выдается надпись - 'Empty' т.е. базы нет, а иначе (стр. 160-200) выдаем список таблиц в нашей базе. * А что за страшную строку получает PrintList получает как параметр. - Это тот самый запрос и есть. Пока разбирать его не будем. - * - (уточнение, “- * -“ равняется банке пива) - Ну как, чего ты такой… * Опять, не работает. - Привыкай к тяготам лишениям нашей службы… - Ну что там у нас * Operation cancelled at user's request - Н-да, и что характерно, каждый раз на этом месте… - Так, у компонента IBDatabase1 измени свойство LoginPrompt на False. И будет тебе счастье. - * - * Ну, что, сразу нельзя было сказать? - Забыл, бывает… - Как, заработало? * Да, но гора родила мышь. Ввели много дополнительных слов, а результат тот же. - Ничего, скоро мышка превратится в кошку, затем в собачку а там и до крокодила недалеко. * Не п*ди, что будем делать дальше? - Дальше?
Готовимся выполнять SQL запросы.
- Для начала, что попроще. - На закладке History помести TMemo – во всю ее ширину и высоту, да, назови это дело His. - А на закладке SQL надо расположить тоже TMemo (у меня оно названо Memo1) и для начала пару кнопок “Run SQL” и “Clear SQL”. - Теперь делаем процедуры кнопок: procedure TFMain.Button1Click(Sender: TObject); begin // кнопка run SQL RunSQL( MakeSQL); end; * Опять временно? - Ну, не хочу тебя сразу пугать, все по очереди. - Обрати внимание на комментарий к слову begin – рекомендую так подписывать процедуру, если название ее мало информативно. * А вторая кнопка? - Ну, даже неудобно… procedure TFMain.Button2Click(Sender: TObject); begin Memo1.Clear; end; * Да, проще некуда. Так теперь по очереди RunSQL( MakeSQL); - Недавно переделал, довольно много повкалывал с этими 30 строками… 010 function RunSQL( S:string):boolean; 020 var 030 b : boolean; // отслеживание ошибки 040 Mistake : string; // сообщение ошибки 050 begin 060 with DataModule2.IBSQL1 do 070 begin 080 Close; 090 SQL.Clear; 100 SQL.Add(S); 110 try 120 ExecQuery; // попытка выполнения запроса 130 b := true; // ошибки нет 140 except // Обработка ошибки 150 on E: Exception do 160 begin 170 b := false; // к сожалению, ошибка 180 Mistake := E.ClassName+' raised exception: '+E.Message; 190 end; 200 end; // try 210 end; // with DataModule2 220 result := not b; 230 if b 240 then 250 begin // запрос выполнен 260 Hi.Lines.Add('ok'); 270 Memo1.Clear; // и переход на закладку History 280 if DataModule2.IBSQL1.SQLType = SQLSelect 290 then PrintSELECT(S) // распечатка результата запроса SELECT 300 else PageControl1.ActivePageIndex := 3; 310 end 320 else 330 begin // была ошибка 340 ShowMessage(Mistake); // сообщение об ошибке 350 Hi.Lines.Add('Error'); 360 Hi.Lines.Add(Mistake); // запись в историю 370 end; 380 Hi.Lines.Add('------------'); 390 end; - Самое интересное происходит, когда запрос НЕ выполняется. * Прочитал, все понятно, и над чем тут было биться? - Все понятно? Отлично, объясни тогда строки 280, 290. * Так, интересно. Определяется тип запроса и если это SELECT. Нечестно, ты еще ничего не сказал о PrintSELECT. - Давай, это исправим: 010 procedure PrintSELECT(S:string); 020 var 030 i : integer; 040 a : string; 050 LHTML : TStringList; 060
- 1
- 2
- 3
- 4
- . . .
- последняя (6) »