Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 2 128

/ вопрос открыт /

Доброго времени суток, уважаемые эксперты!
Скажите как правильно сформировать алгоритм по обмену данными между 2 одинаковыми базами (аксесс) но которые находятся на разных дисках.
Но условие такое , если запись с ID есть в обеих таблицах то обновление данных.
Если ключ только в одной таблице то вставка записи.
я тут пробовала делать так (может и коряво ... как умею)
использую 2 ADOConnection для соединения с базами.

Приложение:
  1.  
  2.  
  3. i,g,j:integer;
  4.  
  5.  
  6.  
  7.  
  8.  
  9. With DataModule1.Connection do
  10. Begin
  11. Connected:=False; ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+GetCurrentDir+'\Zalob.mdb;Mode=ReadWrite;Persist Security Info=False';
  12. Connected:=True;
  13. End;
  14.  
  15.  
  16.  
  17.  
  18. With ADOConnection1 do
  19. Begin
  20. Connected:=False;
  21. ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=L:\..\...\Zalob.mdb;Mode=ReadWrite;Persist Security Info=False';
  22. Connected:=True;
  23. End;
  24.  
  25.  
  26.  
  27.  
  28. ADOQuery2-DataModule1.Connection
  29.  
  30.  
  31.  
  32.  
  33. with ADOQuery1 do
  34. begin
  35. close;
  36. sql.Clear;
  37. sql.Add('select * from Zurnal order by PorNomer');
  38. Open;
  39. end;
  40. with ADOQuery2 do
  41. begin
  42. close;
  43. sql.Clear;
  44. sql.Add('select * from Zurnal order by PorNomer');
  45. Open;
  46. end;
  47.  
  48.  
  49.  
  50.  
  51.  
  52. while not ADOQuery1.Eof do begin
  53. g:=StrToInt(ADOQuery1.Fields.Fields[1].AsString);
  54. j:=StrToInt(ADOQuery2.Fields.Fields[1].AsString);
  55.  
  56. tex:='update Zurnal set StatusKol ='+QuotedStr(ADOQuery2.Fields.Fields[3].AsString)+',fio=' +QuotedStr(ADOQuery2.Fields.Fields[4].AsString)+ ',KemPereslano='+QuotedStr(ADOQuery2.Fields.Fields[5].AsString)+',Adress='+QuotedStr(ADOQuery2.Fields.Fields[6].AsString)+',Soderganie='+QuotedStr(ADOQuery2.Fields.Fields[7].AsString)+',Ispolnitel='+QuotedStr(ADOQuery2.Fields.Fields[8].AsString)+',Status='+QuotedStr(ADOQuery2.Fields.Fields[9].AsString)+',Ident='+QuotedStr(ADOQuery2.Fields.Fields[11].AsString)+'';
  57. if TryStrToDateTime(DateTimeToStr(ADOQuery2.Fields.Fields[2].AsDateTime), d) then tex:=tex + ', DataPost='+QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[2].AsDateTime))+'';
  58. if TryStrToDateTime(DateTimeToStr(ADOQuery2.Fields.Fields[10].AsDateTime), d) then tex:=tex+ ', DataIspolnen='+QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[10].AsDateTime))+'';
  59. tex:=tex+ ' where PorNomer = '+QuotedStr(ADOQuery1.Fields.Fields[1].AsString)+'';
  60. ADOQuery3.Close;
  61. ADOQuery3.SQL.Clear;
  62. ADOQuery3.SQL.Text:=tex;
  63. ADOQuery3.ExecSQL;
  64. end else begin
  65. tex:= 'insert into Zurnal (PorNomer,DataPost,StatusKol,fio,KemPereslano,Adress,Soderganie,Ispolnitel,Status,DataIspolnen,Ident) values('+QuotedStr(ADOQuery2.Fields.Fields[1].AsString)+','+QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[2].AsDateTime))+','+QuotedStr(ADOQuery2.Fields.Fields[3].AsString)+','+QuotedStr(ADOQuery2.Fields.Fields[4].AsString)+','+QuotedStr(ADOQuery2.Fields.Fields[5].AsString)+','+QuotedStr(ADOQuery2.Fields.Fields[6].AsString)+','+QuotedStr(ADOQuery2.Fields.Fields[7].AsString)+','+QuotedStr(ADOQuery2.Fields.Fields[8].AsString)+','+QuotedStr(ADOQuery2.Fields.Fields[9].AsString)+','+QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[10].AsDateTime))+','+QuotedStr(ADOQuery2.Fields.Fields[11].AsString)+')';
  66.  
  67. ADOQuery3.Close;
  68. ADOQuery3.SQL.Clear;
  69. ADOQuery3.SQL.Text:=tex;
  70. ADOQuery3.ExecSQL;
  71. end;
  72. ADOQuery1.next;
  73. end;


Танюшка Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задала: Танюшка (статус: Посетитель)
Вопрос отправлен: 26 ноября 2008, 17:07
Состояние вопроса: открыт, ответов: 2.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, Танюшка!
А всё ведь проще надо делать. Для одной базы делаем Select * from table и пробегая в цикле по ней, выполняем select * from table2 where id=ид_с_первой таблицы
Если запись есть - делаем сверку по другим полям и по надобности записываем ид в специальный файл/массив/StringList. Если записи нет (возвратит Query.RecordCount = 0), то добавим в другой массив -там где храним номера для добавления. То есть, пока сверяем, базу не модифицируем.
А потом, имея на руках "протоколы сверки", добавляем.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 26 ноября 2008, 18:04
Оценка за ответ: 5

Ответ #2. Отвечает эксперт: Косолапов Дмитрий Юрьевич

Здравствуйте, Танюшка!
Не совсем согласен с мнением Вадима К - запросы в цикле представляются нерациональными... Вместо этого я бы предложил во втором запросе (или даже таблице) делать поиск с использованием индекса (ID ведь первичный ключ).

Также могу предложить вместо "ручной" сверки использовать стандартные возможности по репликации MS Access.

Ответ отправил: Косолапов Дмитрий Юрьевич (статус: 8-ой класс)
Время отправки: 27 ноября 2008, 08:43


Мини-форум вопроса

Всего сообщений: 4; последнее сообщение — 29 ноября 2008, 10:05; участников в обсуждении: 3.
Вадим К

Вадим К (статус: Академик), 27 ноября 2008, 09:56 [#1]:

to Косолапов Дмитрий Юрьевич
Вам кажеться или вы пробовали? Некоторые движки БД поиск реализуют крайне хитрым оборазом - они просто проходят сверху вниз по записям и смотрят. А это будет ещё медленее. В случае select (который будет возвращать либо 0, либо одну запись) это будет значительно эффективней на больших объемах.
Конечно, можно сделать сортировку по этому ключу и аккуратно паралельно продвигаться, но для такой качественно реализовать такой алгоритм надо ещё уметь.

А вот использовать встроенные методы - это обычно самый "эффективный путь". Хотя и тут можно постараться:)
Галочка "подтверждения прочтения" - вселенское зло.
Косолапов Дмитрий Юрьевич

Косолапов Дмитрий Юрьевич (статус: 8-ой класс), 28 ноября 2008, 10:47 [#2]:

"они просто проходят сверху вниз по записям и смотрят" - нет, такой поиск нам не нужен, конечно же :) Я имел в виду нормальный поиск по индексу.
Танюшка

Танюшка (статус: Посетитель), 28 ноября 2008, 11:06 [#3]:

спасибо вадим!!!!!
я воспользовалась вашим советом но немного по другому:
while not ADOQuery2.Eof do
begin
tex:='update Zurnal set StatusKol =' + QuotedStr(ADOQuery2.Fields.Fields[3].AsString) + ',fio=' + QuotedStr(ADOQuery2.Fields.Fields[4].AsString) + ',KemPereslano=' + QuotedStr(ADOQuery2.Fields.Fields[5].AsString)+ ',Adress=' + QuotedStr(ADOQuery2.Fields.Fields[6].AsString) + ',Soderganie=' + QuotedStr(ADOQuery2.Fields.Fields[7].AsString) + ',Ispolnitel=' + QuotedStr(ADOQuery2.Fields.Fields[8].AsString) + ',Status=' + QuotedStr(ADOQuery2.Fields.Fields[9].AsString) + ',Ident=' + QuotedStr(ADOQuery2.Fields.Fields[11].AsString) + '';
if TryStrToDateTime(DateTimeToStr(ADOQuery2.Fields.Fields[2].AsDateTime), d) then tex:=tex + ', DataPost=' + QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[2].AsDateTime)) + '';
if TryStrToDateTime(DateTimeToStr(ADOQuery2.Fields.Fields[10].AsDateTime), d) then tex:=tex+ ', DataIspolnen=' + QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[10].AsDateTime)) + '';
tex:=tex+ ' where PorNomer = ' + QuotedStr(ADOQuery2.Fields.Fields[1].AsString) + '';
ADOQuery3.Close;
ADOQuery3.SQL.Clear;
ADOQuery3.SQL.Text:=tex;
ADOQuery3.ExecSQL;// ADOQuery3 связан с таблицей на сервере(которую обнавляю)
if (ADOQuery3.ExecSQL=0) then begin
tex:= 'insert into Zurnal (PorNomer, DataPost, StatusKol, fio, KemPereslano, Adress, Soderganie, Ispolnitel, Status, DataIspolnen, Ident) values(' + QuotedStr(ADOQuery2.Fields.Fields[1].AsString) + ',' + QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[2].AsDateTime)) + ',' + QuotedStr(ADOQuery2.Fields.Fields[3].AsString) + ',' + QuotedStr(ADOQuery2.Fields.Fields[4].AsString) + ',' + QuotedStr(ADOQuery2.Fields.Fields[5].AsString)+ ',' + QuotedStr(ADOQuery2.Fields.Fields[6].AsString) + ',' + QuotedStr(ADOQuery2.Fields.Fields[7].AsString) + ',' + QuotedStr(ADOQuery2.Fields.Fields[8].AsString) + ',' + QuotedStr(ADOQuery2.Fields.Fields[9].AsString) + ',' + QuotedStr(DateTimeToStr(ADOQuery2.Fields.Fields[10].AsDateTime)) + ',' + QuotedStr(ADOQuery2.Fields.Fields[11].AsString) + ')';
ADOQuery3.Close;
ADOQuery3.SQL.Clear;
ADOQuery3.SQL.Text:=tex;
ADOQuery3.ExecSQL;
end;
ADOQuery2.Next;
end;
//ADOQuery2 связан с таблицей которая на рабочем диске
выкладываю для тех кому интересно....
можете пообсуждать рациональность данного куска кода
Косолапов Дмитрий Юрьевич

Косолапов Дмитрий Юрьевич (статус: 8-ой класс), 29 ноября 2008, 10:05 [#4]:

ADOQuery3.ExecSQL;// ADOQuery3 связан с таблицей на сервере(которую обнавляю)
if (ADOQuery3.ExecSQL=0)

В этом месте запрос дважды выполняется.

В целом, весьма жесткая синхронизация. Устраивает ли производительность? А стандартной репликацией точно не хотите пользоваться?

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 17 февраля 2020, 02:17
Выполнено за 0.03 сек.
Рейтинг@Mail.ru