Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001
begin
StrCopy(szTblType, Rec.szValue);
Break;
end;
finally
Check(DbiCloseCursor(Cur));
end;
end;
iOptParams := 1;
pfldOptParams := @OptDesc;
pOptData := @OptData;
end;
StrPCopy(OptData, LDName);
Check(DbiDoRestructure(Database.Handle, 1, @TblDesc, nil, nil, nil, False));
finally
Session.CloseDatabase(Database);
end;
end;
Примеры использования:
ChangeLangDriver('DBDEMOS', 'EMPLOYEE', 'ancyrr');
ChangeLangDriver('DBDEMOS', 'EMPLOYEE.DB', 'ancyrr');
ChangeLangDriver('C:DELPHIDEMOSDATA', 'CLIENTS.DBF', 'db866ru0');
LDName:
для D1 – имя .LD файла в каталоге IDAPILANGDRV;
для D2 и CB – из BDECFG32.HLP поле Short name в табличке по указателю language drivers, dBASE или поле Internal в табличке по указателю language drivers, Paradox;
для D3 и выше – не знаю так как у меня её нет, но думаю, что также, как и в D2.
Существует ли средство для вывода определения структуры таблицы?
Я создал таблицу и хочу получить её структуру, чтобы сделать изменённый оператор создания таблицы.
Nomadic отвечает:
Для этого существует утилита DB2LOOK. Она находится в SQLLIBMISC.
Пример использования:
CONNECT TO SAMPLE USER xxx USING yyy
DB2LOOK –d SAMPLE –u xxx –e –t employee
Вывод может быть перенаправлен в файл. Полный синтаксис выдаётся по команде:
DB2LOOK ?
У меня есть текстовые файлы, которые я хочу использовать в запросах к DB2, но не хочу создавать из них постоянные таблицы в базе. Что делать?
Nomadic отвечает:
Можно воспользоваться табличными функциями (Table Functions). Они позволяют использовать файлы как таблицы. Примеры приведены в руководстве «Embedded SQL Programming Guide».
Список структуры полей таблицы
В данном проекте создается список структуры полей соответствующей таблицы, с использованием массивов Fields и IndexDefs, который затем отображается в компоненте ListBox. Демонстрационный проект (dbbrowsr.dpr) решает эту задачу несколько иначе. Вы можете сравнить две версии этого кода.
Примечание: Данный код работает только в 16-битной среде.
procedure TForm1.Button1Click(Sender: TObject);
const MyFielddefs: array[ftUnknown..ftGraphic] of string [8] = ('Unknown', 'String', 'Smallint', 'Integer', 'Word','Boolean', 'Float', 'Currency', 'BCD', 'Date','Time', 'DateTime', 'Bytes', 'VarBytes', 'Blob','Memo', 'Graphic');
var
i, Indx: integer;
Definition: string;
begin
for i := 0 to Table1.FieldCount - 1 do begin
Definition := Table1.Fields[i].DisplayLabel;
Definition := Definition + ' ' +MyFieldDefs[Table1.Fields[i].DataType];
Table1.IndexDefs.Update;
if Table1.Fields[i].IsIndexField then begin
Indx := Table1.IndexDefs.Indexof(Table1.Fields[i].Name);
if Indx > -1 then if ixPrimary in Table1.IndexDefs[Indx].Options then Definition := Definition + ' (Первичный)';
end;
Listbox1.Items.Add(Definition);
end;
end;
Приведенная выше версия не работает в 32-битной среде, поскольку в ней присутствуют дополнительные типы полей. Вот версия, которая работает в 32-битной среде:
procedure TForm1.Button1Click(Sender: TObject);
const
MyFielddefs: array[ftUnknown..ftTypedBinary] of string [11] =('Unknown', 'String', 'Smallint', 'Integer','Word', 'Boolean', 'Float', 'Currency', 'BCD','Date', 'Time', 'DateTime', 'Bytes', 'VarBytes','AutoInc', 'Blob', 'Memo', 'Graphic', 'FmtMemo','ParadoxOle', 'DBaseOle', 'TypedBinary');
var
i, Indx: integer;
Definition: string;
begin
for i := 0 to Table1.FieldCount - 1 do begin
Definition := Table1.Fields[i].DisplayLabel;
Definition := Definition + ' ' +MyFieldDefs[Table1.Fields[i].DataType];
Table1.IndexDefs.Update;
if Table1.Fields[i].IsIndexField then begin
Indx := Table1.IndexDefs.Indexof(Table1.Fields[i].Name);
if Indx > -1 thenif ixPrimary in Table1.IndexDefs[Indx].Options then Definition := Definition + ' (Первичный)';
end;
Listbox1.Items.Add(Definition);
end;
end;
Создание индексного файла из Delphi
Delphi 1
Если вы используете таблицы dBASE или Paradox, то для создания нового индекса воспользуйтесь методом AddIndex. Для примера:
Table1.AddIndex('Articles','Title', []);
создаст индексный файл с именем ARTICLES с использованием поля TITLE в качестве индексного ключа. При создании вы можете воспользоваться различными индексными опциями (например, уникальность, необслуживаемый и пр.) – для получения дополнительной информации обратитесь к электронной справке по Delphi. ПРИМЕЧАНИЕ: Ваша таблица должна быть открыта исключительно для того, чтобы только воспользоваться методом AddIndex.
Поддержка/обновление индексного файла, если только при создании вы не выставили флаг «необслуживаемый», происходит автоматически.
Контекстное меню на основе базы данных
var
m:TMenuItem;
navidummy:TComponent;
…………………………………………………
procedure TMyForm.CreatePopUpMM(Sender: TObject);
begin
Navidummy.free;
Navidummy:=TComponent.create(self);
While not NaviT.EOF do
begin
m := TMenuItem.create(navidummy);
II:=II+1;
with m do begin
name :='MM'+IntToStr(II);
caption := NaviT.Fieldbyname('MyWHAT').AsString;
tag := NaviT.Fieldbyname('MyTAG').AsInteger;
visible:=True;
OnClick:= NaviExec;
end;
MyMenuItem.add(m);
NaviT.Next;
end;
NaviT.Close;
end;
procedure TMyForm.NaviExec(Sender:TObject);
begin
What.text := (Sender as TMenuItem).Caption;
{ Здесь я получаю то, что хочу ! }
Key:= (Sender as TMenuItem).Tag;
end;
Корректное закрытие базы данных приложением Delphi
Delphi 1
Очень интересный и полезный вопрос!! Я сам так с ним до конца и не разобрался! Но я попробую систематизировать события, происходящие при запросе на завершение работы Windows:
Windows посылает сообщение WM_QUERYENDSESSION главным окнам всех запущенных приложений, при этом приложения должно сообщить свою готовность к завершению работы.
Если при этом хотя бы одно из приложений ответит отрицательно, Windows прерывает процесс завершения работы.
Delphi перехватывает это сообщение, и, в свою очередь, вызывает метод TForm.CloseQuery, (в главной форме, естественно), который генерирует событие OnCloseQuery, в обработчике которого можно указать на неготовность завершения приложения и отмены завершения работы Windows.
Если я правильно понимаю, если ваше приложение «не мешает» Windows завершить свою работу, Windows нормально НЕ завершает работу приложения, поскольку для этого нет необходимости, не нужно освобождать память, ресурсы и пр. Так, если это утверждение верно (это легко можно проверить, но я слишком ленив сейчас), то событие OnCloseQuery – ваш единственный шанс сохранения данных на диске. Я не думаю что эта логика слишком плоха, просто это одна из тех причуд Windows, которую нужно знать и пользоваться ею. Что может произойти в описанном выше сценарии: редактируемая в настоящий момент запись не будет отправлена (Post) в базу данных, но та же самая вещь может случиться и при нормальном завершении приложения.
При выходе из windows, вы вызываете WM_CLOSE api (или что-то типа этого) для каждого работающего в настоящий момент приложения. Программа закрывается точно таким же образом, как если бы вы щелкнули на кнопке закрытия или вызвали close из главной формы. Поэтому вам не нужно предпринимать никаких дополнительный действий, связанных с завершением работы с таблицами.
Изменение свойств базы данных во время выполнения приложения
Delphi 1
Свойство DatabaseName тесно связано с:
• каталогом, где расположены ваши табличные файлы.
• BDE-псевдоним вашей базы данных.
• DatabaseName вашего компонента TDatabase, если вы имеете его.
Выводы?
Как мне задать выражение по умолчанию для объекта TField?
Delphi 3
Это будет работать, если вы уже установили атрибуты поля и ассоциировали его с полем вашей таблицы. Если вы установили значение в Инспекторе Объектов, т.е. задали строку, не думайте, что это сработает во время выполнения приложения. Если вы попытаетесь во время прогона установить свойство TField.DefaultExpression примерно так: