Консультация № 176301
26.01.2010, 00:46
0.00 руб.
26.01.2010, 16:33
0 21 2
Здравствуйте! Есть такая задачка: нужно конвертировать таблицу .dbf в .IB через компоненты Delphi, вкладки палитры компонентов InterBase. ссылка на таблицу .dbf

Обсуждение

Неизвестный
26.01.2010, 02:11
общий
26.01.2010, 09:13
это ответ
Здравствуйте, Судейкин Андрей Владимирович.

Не будем заморачиваться с универсальностью, а представим, что вы уже подготовили необходимую таблицу аналогичной структуры в базе IB. Так же предположим, что в вашей программе по перегону данных уже есть TIBDatabase, TIBTransaction (для подключения к БД Interbase), уже настроенные на подключение к нужной базе, а так же - ну, хотя бы TTable (имя пусть будет Table1) со вкладки BDE. На всякий случай подскажу: в Table1 вам надо только поменять имя таблицы (укажите полный путь к файлу dbf), и сказать Active := False (рекомендую пояснить это с клавиатуры - микрофон Delphi пока еще не понимает). Для проверки положите на форму TDataSource (у неё укажите в качестве DataSet вышеобозначенную Table1), TDBGrid (выставьте ей DataSource'ем) только что созданный DataSource1 и поглядите - отображаются ли данные в таблице.

Теперь кладите на форму TIBQuery (он будет у нас зваться IBQuery1). В свойстве SQL пишите ему что-то вроде следующего:
Код:
insert into TABLE_NAME(
KZK,
CHTO,
KCH,
NCHTO,
CI,
EI,
OCN,
OCNS,
NCHP,
NCHPS,
NCENA,
VES,
KNC,
KNCH,
PR,
NPR
)values(
:KZK,
:CHTO,
:KCH,
:NCHTO,
:CI,
:EI,
:OCN,
:OCNS,
:NCHP,
:NCHPS,
:NCENA,
:VES,
:KNC,
:KNCH,
:PR,
:NPR
)


Тут я опять же предполагаю, что структура таблиц вплоть до названий полей у вас совпадает. Продолжим.
Разумеется, вы правильно указали имя БД в IBDatabase1, там же правильно указали DefaultTransaction (которая у нас называется IBTransaction1), в IBTransaction1 сказали, что DefaultDatabase - это IBDatabase1, а в IBQuery1 указали опять же правильную DerfaultTransaction. Переходим к написанию кода. Как он выглядит - см. приложение.

Поясняю, про что там.
Мы переходим в самое начало нашей таблицы dbf, а потом до тер пор, пока она не кончится, делаем следующее: перебираем все её поля и их значения запихиваем в соотв. параметры нашего запроса (который IBQuery1). После того, как все параметры мы заполнили, мы выполняем запрос на вставку данных, приведенный ваше по тексту и переходим к следующей записи нашей таблицы DBF.
Когда таблица кончилась - мы подтверждаем внесенные в базу IB изменения.
Всё просто.
Удачи.

P.S. А еще есть утилита DataPump...

Приложение:
Table1.First;
while not Table1.Eof do begin
for X := 0 to Table1.Fields.Count-1 do
IBQuery1.ParamByName(Table1.Fields[X].FieldName).AsVariant := Table1.Fields[X].AsVariant;
IBQuery1.Active := True;
IBQuery1.ExecSQL;
Table1.Next;
end;
IBQuery1.Transaction.Commit;
5
Неизвестный
26.01.2010, 15:03
общий
Del
А в какой процедуре записывать данный код, указанный в приложении?
Неизвестный
26.01.2010, 15:31
общий
Судейкин Андрей Владимирович:
Абсолютно непринципиально. Например, положи на форму кнопку, и ей на OnClick. Можно еще всяких красивостей приделать, например - положить на форму прогрессбар, и немного модифицировать код:

Код:

Table1.First;
ProgressBar1.Max := Table1.RecordCount;
while not Table1.Eof do begin
for X := 0 to Table1.Fields.Count-1 do
IBQuery1.ParamByName(Table1.Fields[X].FieldName).AsVariant := Table1.Fields[X].AsVariant;
IBQuery1.Active := True;
IBQuery1.ExecSQL;
Table1.Next;
ProgressBar1.Position := ProgressBar1.Position + 1;
end;
IBQuery1.Transaction.Commit;
Неизвестный
26.01.2010, 16:02
общий
Del:
Вроде всё делаю как вы написали, а почему то ошибку выводит при компиляции... можете посмотреть ссылка на исходник
Неизвестный
26.01.2010, 17:00
общий
Судейкин Андрей Владимирович:
Понял. Попробуйте AsString.

Кстати, я так понимаю - вы начинающий программист? Вот такого
> procedure BitBtn1Click(Sender: TObject; var x: integer);
писать не надо - должно быть примерно так:

Код:

procedure TForm1.BitBtn1Click(Sender: TObject);
var x: integer;
begin
Table1.First;
while not Table1.Eof do begin
for X := 0 to Table1.Fields.Count-1 do
IBQuery1.ParamByName(Table1.Fields[X].FieldName).AsString := Table1.Fields[X].AsVariant;
IBQuery1.Active := True;
IBQuery1.ExecSQL;
Table1.Next;
end;
IBQuery1.Transaction.Commit;
end;


Пробуйте. Если что - пишите-спрашивайте.

P.S. В дальнейшем - будет лучше, если вы в примере зашлете еще и таблицу dbf и базу IB - тогда получится ответить точнее 60
P.P.S. И не забудьте после внесения изменений в объявление процедуры заново назначить обработчик нажатия кнопки.
Неизвестный
26.01.2010, 18:28
общий
Del:
Да, вы правы я начинающий программист...
Таблицу .dbf же я заслал, а .IB таблицы у меня нету... в этом и вопрос, нужно вот эту самую таблицу .dbf конвертировать в .IB
Вообщем сделал как вы написали, теперь вылазиет такая ошибка "Could not convert variant of type (Null) into type (String)"
Неизвестный
27.01.2010, 10:10
общий
Судейкин Андрей Владимирович:
Первое.
Создаем саму базу IB, в ней создаем нужную таблицу (см. IBExpert). А в целом - я не понял, как это нет таблицы, если появляется ошибка, которую вы описали далее. Ну да ладно. Дальше.

Второе.
Тогда сделайте так:

Код:

IBQuery1.ParamByName(Table1.Fields[X].FieldName).AsString := Table1.Fields[X].AsString;


Третье.
Для работы с IB/FB/Yaffil категорически рекомендую найти набор компонентов FIBPlus. На мой (и не только) взгляд - существенно удобнее, функциональнее и мощнее стандартных IBX.
Неизвестный
27.01.2010, 16:39
общий
Del:
Установил IBExpert, но не могу создать базу IB. Вообщем загружаю IBExpert, далее выбираю База данных -> Создать базу... (у меня IBExpert на русском языке). В появившемся окне создания базы данных указываю Сервер - Локальный, в поле "Файл БД" требуется указать путь к базе IB, но как я укажу путь если у меня нет базы, а мне её нужно создать??? Может я чего то не понимаю, объясните пожалуйста...
Неизвестный
27.01.2010, 17:16
общий
Судейкин Андрей Владимирович:
Неизвестный
27.01.2010, 19:01
общий
Спасибо, с айбиэкспертом разобрался, создал базу, в ней таблицу, далее всё как вы писали, и всё равно ту же ошибку выводит, можете посмотреть, в архиве dbf и IB есть. ссылка
Неизвестный
27.01.2010, 20:08
общий
Судейкин Андрей Владимирович:
Поглядел. Значит, так.

Первое. Моя ошибка (привык к FIBPlus) - уберите IBQuery1.Active := True;
Второе. Скопируйте в каталог с проектом вышеуказанную gds32.dll
Третье. При создании формы напишите IBDatabase1.Open;

У меня - работает.

Кстати, работать не с локальной базой - существенно удобнее.
Неизвестный
27.01.2010, 20:48
общий
Del:
Чё то всё таже ошибка вылазиет, можете свой исходник кинуть?
P.S. И как проверить сконвертировалось ли содержимое .dbf в .ib ???
Неизвестный
27.01.2010, 20:48
общий
Del:
Чё то всё таже ошибка вылазиет, можете свой исходник кинуть?
P.S. И как проверить сконвертировалось ли содержимое .dbf в .ib ???
Неизвестный
28.01.2010, 10:03
общий
Судейкин Андрей Владимирович:
Добрый день! Какую СУБД Вы установили: FireBird, InterBase, Yaffil? Какая версия? Как я понимаю, Вам надо конвертировать некую АСУПовскую таблицу.
1. Там есть записи, помеченные на удаление. Что с ними делаем?
2. Структура новой таблицы
Код:
CREATE TABLE NEW_TABLE (
KZK CHAR(6),
CHTO CHAR(18),
KCH INTEGER,
NCHTO CHAR(80),
CI CHAR(2),
EI CHAR(2),
OCN NUMERIC(15,2),
OCNS NUMERIC(15,2),
NCHP NUMERIC(15,2),
NCHPS NUMERIC(15,2),
NCENA NUMERIC(15,2),
VES NUMERIC(15,3),
KNC INTEGER,
KNCH INTEGER,
PR INTEGER,
NPR CHAR(80)
);
не соответствует структуре таблицы dbf. Это сделано осознанно?
3. В новой таблице в базе должно быть ключевое поле. Какое? (Или какие?, или создать дполнительное автоинкрементное?)
4. Поле NCHTO неообходимо разделить на два: конструкторскую гравировку и название. и т.д.
Неизвестный
28.01.2010, 17:19
общий
lamed:
Здравствуйте! Установил InterBase 7.5.
1. Там есть записи, помеченные на удаление. Что с ними делаем?

ничего
2. Структура новой таблицы не соответствует структуре таблицы dbf. Это сделано осознанно?

нет, я сам не заметил что не соответствует...
3. В новой таблице в базе должно быть ключевое поле. Какое? (Или какие?, или создать дполнительное автоинкрементное?)

KZK ключевое поле
4. Поле NCHTO неообходимо разделить на два: конструкторскую гравировку и название. и т.д.

понятие не имею как это сделать
Поможете?
Неизвестный
28.01.2010, 22:12
общий
Судейкин Андрей Владимирович:
У меня FireBird 2.1.3. Ответ будет завтра вечером.
Неизвестный
28.01.2010, 23:57
общий
lamed:
хорошо
давно
Академик
320937
2216
29.01.2010, 11:30
общий
это ответ
Здравствуйте, Судейкин Андрей Владимирович.
BackUp базы данных, отдельно скрипт на создание, проект здесь:176301.ZIP (220.2 кб)
Используется хранимая процедура. В приложении обработчик выбора пункта меню. Спрашивайте, если что-то не ясно. С уважением

Приложение:
procedure TfAdmin.N25Click(Sender: TObject);
Var
i: Integer; // номер строки в dbf
iRead: integer; // прочитано
iWrite: integer; // записано
Begin
// очистка таблицы gp
try
if sp.Active then sp.Close;
sp.StoredProcName := 'GP_ZAP';
sp.Params.Clear;
sp.Prepare;
sp.ExecProc;
dm.IBTransaction1.Commit;
except
ShowMessage('Ошибка очистки!');
end;

sp.StoredProcName := 'GP_INS';
with sp.Params do begin

Clear;

CreateParam( ftString, 'kzk', ptInput );
CreateParam( ftString, 'chto', ptInput );
CreateParam( ftString, 'kch', ptInput );
CreateParam( ftString, 'nchto', ptInput );
CreateParam( ftString, 'ci', ptInput );
CreateParam( ftString, 'ei', ptInput );
CreateParam( ftFloat, 'ocn', ptInput );
CreateParam( ftFloat, 'ocns', ptInput );
CreateParam( ftFloat, 'nchp', ptInput );
CreateParam( ftFloat, 'nchps', ptInput );
CreateParam( ftFloat, 'ncena', ptInput );
CreateParam( ftFloat, 'ves', ptInput );
CreateParam( ftString, 'knc', ptInput );
CreateParam( ftString, 'knch', ptInput );
CreateParam( ftString, 'pr', ptInput );
CreateParam( ftString, 'npr', ptInput );

CreateParam( ftInteger, 'id', ptOutput );
end;
sp.Prepare;

if Tvhod.Active then TVhod.Close;
TVhod.Open;
iRead := 0;
iWrite:= 0;
for i:= 0 to TVhod.RecordCount -1 do
begin
inc(iRead);
try
with sp.Params do begin
ParamByName( 'kzk' ).AsString :=
sdos_win(TVhod.FieldByName('kzk').AsString);
ParamByName( 'chto' ).AsString :=
sdos_win(TVhod.FieldByName('chto').AsString);
ParamByName( 'kch' ).AsString :=
sdos_win(TVhod.FieldByName('kch').AsString);
ParamByName( 'nchto' ).AsString :=
sdos_win(TVhod.FieldByName('nchto').AsString);
ParamByName( 'ci' ).AsString :=
sdos_win(TVhod.FieldByName('ci').AsString);
ParamByName( 'ei' ).AsString :=
sdos_win(TVhod.FieldByName('ei').AsString);
ParamByName( 'ocn' ).AsFloat := TVhod.FieldByName('ocn').AsFloat;
ParamByName( 'ocns' ).AsFloat := TVhod.FieldByName('ocns').AsFloat;
ParamByName( 'nchp' ).AsFloat := TVhod.FieldByName('nchp').AsFloat;
ParamByName( 'nchps' ).AsFloat := TVhod.FieldByName('nchps').AsFloat;
ParamByName( 'ncena' ).AsFloat := TVhod.FieldByName('ncena').AsFloat;
ParamByName( 'ves' ).AsFloat := TVhod.FieldByName('ves').AsFloat;
ParamByName( 'knc' ).AsString :=
sdos_win(TVhod.FieldByName('knc').AsString);
ParamByName( 'knch' ).AsString :=
sdos_win(TVhod.FieldByName('knch').AsString);
ParamByName( 'pr' ).AsString :=
sdos_win(TVhod.FieldByName('pr').AsString);
ParamByName( 'npr' ).AsString :=
sdos_win(TVhod.FieldByName('npr').AsString);
end;
sp.ExecProc;
inc(iWrite);
if ( i mod 1000 = 0 ) then dm.IBTransaction1.Commit;
except
ShowMessage('Ошибка добавления записи ('+IntTostr(i)+')!');
end;
TVhod.Next;
end; { for }

dm.IBTransaction1.Commit;
TVhod.Close;
ShowMessage('Прочитано '+IntToStr(iRead)+' ;записано '+IntToStr(iWrite));
end;
5
Неизвестный
29.01.2010, 11:38
общий
Судейкин Андрей Владимирович:
Добрый день!
1. Поле KZK не может быть ключевым, так как содержит повторяющиеся значения. Создал суррогатный ключ, id, заполнение триггер-генератор.
2. На этом этапе не стал делить поле NCHTO на два, надо быть точно уверенным, что первый пробел после конструкторской гравировки отделяет от названия. Уточните, пожалуйста.
3. Проект не ограничивается одной таблицей? Вы сможете обрисовать полную цель проекта (лучше в отдельном вопросе).
Неизвестный
29.01.2010, 13:28
общий
Del:
Большое спасибо, всё работает!
Неизвестный
29.01.2010, 13:29
общий
lamed:
Спасибо, но мне уже помогли
Форма ответа