Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.07.06;
Скачать: [xml.tar.bz2];

Вниз

Странное поведение выборки в Access   Найти похожие ветки 

 
DimonS   (2008-06-06 07:43) [0]

Добрый день (ну или у кого что) всем.

Столкнулся с таким траблом, в первый раз, так что не пинайте если уже объясняли.
Есть две абсолютно одинаковых по структуре базы Access (таблицы и их структура так же одинаковы). Нужно было сделать копирование новых записей из одной в другую - типа репликации, с удалением в основной базе старых записей и сохранением их в другой базе. Код такой:

procedure TForm1.Button1Click(Sender: TObject);
var
i:Integer;
Dat:TDateTime;
begin
ADORep.Close;
ADORep.SQL.Clear;
ADORep.SQL.Add("select Max(Time5) as Dat from PathForms");
ADORep.Open;

Dat:=ADORep.fieldByName("Dat").AsDateTime;

Edit3.Text:=DateTimeToStr(Dat);

ADOData.Close;
ADOData.SQL.Clear;
ADOData.SQL.Add("select * from PathForms where Time5>:Dat");
ADOData.Parameters.ParamValues["Dat"]:=Dat;
ADOData.Open;

while not ADOData.Eof do
begin
 ADORep.Close;
 ADORep.SQL.Clear;
 ADORep.SQL.Add("delete from PathForms where Code1=:C1 and Code2=:C2");
 ADORep.Parameters.ParamValues["C1"]:=ADOData.fieldByName("Code1").AsInteger;
 ADORep.Parameters.ParamValues["C2"]:=ADOData.fieldByName("Code2").AsInteger;
 ADORep.ExecSQL;

 ADOData.Next;
end;

ADORep.Close;
ADORep.SQL.Clear;
ADORep.SQL.Add("select Top 1 * from PathForms");
ADORep.Open;

ADOData.First;
while not ADOData.Eof do
begin
   ADORep.Insert;
   for i:=1 to ADOData.FieldCount-1 do
     ADORep.Fields[i].Value:=ADOData.Fields[i].Value;
     Dat:=ADOData.Fields[8].Value;
   ADORep.Post;

   ADOData.Next;
end;

end;


Можете не пинать, сам знаю, что перебор вместо запросов это отстой, но пока не нашел, как из одной базы Access запросом перебросить данные в другую (из dBase в Access кидается запросто, а вот в таком случае незнаю), так что если кто подскажет, то приму к сведению и переработаю код.

Code1, Code2 - ключевые поля.
Time5 - дата/время последнего изменения записи, формат Дата/Время.

А проблема (хотя и не особо проблема) такая. Смотрим на максимальное время в обновляемой таблице:
http://i014.radikal.ru/0806/69/e909c6671dc8.jpg

А теперь время отобранных выборкой записей:
http://i042.radikal.ru/0806/bb/bcc7fa21955e.jpg

ADOData.Fields[8].Value; - это значение поля Time5.

Вопрос: почему выбираются записи с меньшим значением даты/времени?

ЗЫ. Впринципе, это не особо мешает, 2-3 сотни записей обрабатываются в течение нескольких секунд, но все же интересно узнать, что за баг.

ЗЫЗЫ. простой репликой базы нельзя обновить по нескольким причинам, одна из них - базы под паролем.


 
Slym ©   (2008-06-06 10:53) [1]

DimonS   (06.06.08 7:43)
замечания по коду:
1. незачем в цикле каждый каз SQL править, можно 1 раз:
ADORep.Close;
ADORep.SQL.Text:="delete from PathForms where Code1=:C1 and Code2=:C2";
while not ADOData.Eof do
begin
ADORep.Parameters.ParamValues["C1"]:=ADOData.fieldByName("Code1").AsInteger;
ADORep.Parameters.ParamValues["C2"]:=ADOData.fieldByName("Code2").AsInteger;
ADORep.ExecSQL;
ADOData.Next;
end;

2. в п1 можно заранее расчитать индексы полей и параметров, а не дергать fieldByName и ParamValues

3. "select Top 1 * from PathForms" можно заменить на "select * from PathForms where false" но лучше состряпать INSERT запрос
4. если к запросам зацеплены Гриды то делать DisableControls
5. выяви самый медренный участок в коде...


 
sniknik ©   (2008-06-06 11:02) [2]

> из dBase в Access кидается запросто, а вот в таком случае незнаю
в хелпе примеры есть и для "таких случаев".


 
Anatoly Podgoretsky ©   (2008-06-06 11:18) [3]

Надо поизучать SQL и заменить на один запрос, без цикла


 
Slym ©   (2008-06-06 12:19) [4]

насколько быстрее такой код? (Расставь конекшены)

procedure Button1Click();
var
 Date:TDateTime;
 Source:TAdoQuery;
 DelCmd,InsCmd:TAdoCommand;
 i:integer;
 KeyField0,KeyField1:TField;
 Fields1,Fields2:string;
begin
 Source:=TAdoQuery.Create(nil);
 try
   //Dest.Connection:=Connection;
   Source.CursorType:=ctOpenForwardOnly;
   Source.LockType:=ltReadOnly;
   Source.SQL.Text:="select Max(Time5) as Dat from PathForms";
   Source.Open;
   if Source.IsEmpty then raise Exception.Create("IsEmpty");
   Date:=Source.Fields[0].AsDateTime;
   Source.Close;

   //Source.Connection:=Connection;
   Source.CursorType:=ctOpenForwardOnly;
   Source.LockType:=ltReadOnly;
   Source.SQL.Text:="select * from PathForms where Time5>:Dat";
   Source.Parameters[0].Value:=Date;
   Source.Open;

   DelCmd:=TAdoCommand.Create(nil);
   try
     //DelCmd.Connection:=Connection;
     DelCmd.CommandText:="delete from PathForms where Code1=:C1 and Code2=:C2";
     DelCmd.Prepared:=true;

     Fields1:="";Fields2:="";
     for i:=1 to Source.FieldCount-1 do
     with Source.Fields[i] do
     begin
       Fields1:=Fields1+"["+FieldName+"],";
       Fields2:=Fields2+":"+FieldName+",";
     end;
     Delete(Fields1,Length(Fields1),1);
     Delete(Fields2,Length(Fields2),1);

     InsCmd:=TAdoCommand.Create(nil);
     try
       //InsCmd.Connection:=Connection;
       InsCmd.CommandText:="INSERT INTO PathForms ("+Fields1+") VALUES ("+Fields2+");";
       InsCmd.Prepared:=true;

       KeyField0:=Source.fieldByName("Code1");
       KeyField1:=Source.fieldByName("Code2");
       while not Source.Eof do
       begin
         DelCmd.Parameters[0].Value:=KeyField0.AsInteger;
         DelCmd.Parameters[1].Value:=KeyField1.AsInteger;
         DelCmd.Execute;

         for i:=1 to Source.FieldCount-1 do
           InsCmd.Parameters[i].Value:=Source.Fields[i].Value;
         InsCmd.Execute;
         Source.Next;
       end;
     finally
       InsCmd.Free;
     end;
   finally
     DelCmd.Free;
   end;
 finally
   Source.Free;
 end;
end;


 
DimonS   (2008-06-07 02:16) [5]


> Slym ©   (06.06.08 10:53) [1]


> Slym ©   (06.06.08 12:19) [4]


Спасибо за советы, принял к сведению :)


> sniknik ©   (06.06.08 11:02) [2]

Если про стандартный хелп MS Access, то не нашел ничего, да там вообще толком-то ничего нет.


> Anatoly Podgoretsky ©   (06.06.08 11:18) [3]

Это я и сам знаю, учу по мере возможностей :).

А вообще, основной вопрос так и остался - почему выбираются записи по времени меньшие, чем назначено в выборке?


 
DimonS   (2008-06-07 04:08) [6]

Вот сижу, разбираюсь с ышеуказанными исправлениями.

> Slym ©   (06.06.08 10:53) [1]

Да, такой код работает нормально, спасибо, не знал что так можно. Хотя прибавки в скорости практически не видно.
И про выборку такого вида не встречал пока нигде, но работает нормально.


> Slym ©   (06.06.08 12:19) [4]
> насколько быстрее такой код? (Расставь конекшены)


Да, работает быстрее раза в три-четыре, но только начало. Спотыкается на этом куске:
for i:=1 to Source.FieldCount-1 do
          InsCmd.Parameters[i].Value:=Source.Fields[i].Value;


Ошибка "List index out not found(47)". Понимаю, что типа нет такого поля, но в таблицах 48 полей, таблицы одинаковы по структуре (вторая просто копия первой). Причем при наведении курсора на Source.Fields[i].Value; в режиме отладки показывает значение этого поля. Буду разбираться дальше.
А вообще, код интересный, спасибо за него, разобрался что к чему :)


 
ASoft   (2008-06-07 04:39) [7]


> ...как из одной базы Access запросом перебросить данные в другую...

TADOCommand:
INSERT INTO таблица  [ ( поле [,...] ) ]
{ VALUES ( Wertliste [,...] ) } | SELECT-команда ;


 
DimonS   (2008-06-07 04:47) [8]


> ASoft   (07.06.08 04:39) [7]

Ну да. Базы на разных сетевых адресах, как в запросе указать к ним путь? Нужно ведь указать путь, название базы и еще таблицу в базе. На этом то я и споткнулся.


 
Slym ©   (2008-06-07 06:43) [9]

DimonS   (07.06.08 4:08) [6]
Ошибка "List index out not found(47)".

мой косяк :)
InsCmd.Parameters[i-1].Value:=Source.Fields[i].Value;


 
Slym ©   (2008-06-07 06:45) [10]

ты даже не представляешь во сколько раз будет быстрее если базу еще и монопольно открыть...


 
DimonS   (2008-06-07 07:21) [11]


> Slym ©   (07.06.08 06:45) [10]
> ты даже не представляешь во сколько раз будет быстрее если
> базу еще и монопольно открыть...


Вот этого и нельзя сделать. К сожалению. Про увеличение скорости в монопольном режиме я вкурсе. База постоянно пополняется/изменяется.


 
DimonS   (2008-06-07 07:50) [12]

To Slym
Щас достану наверное :)


> InsCmd.Parameters[i-1].Value

Да, действительно, так работает. Сразу не дошло :)

Но вот в чем прикол оказался - при вставке записей в поля формата Дата/время вставляется только дата, времени нет.
Вроде в строке

InsCmd.Parameters[i].Value:=Source.Fields[i].Value;
нет никаких ограничений. Что может быть? Остальные поля вставляются нормально.


 
sniknik ©   (2008-06-07 08:26) [13]

> Если про стандартный хелп MS Access,
именно, хотя я чтобы не запускать access(может вообще не установлен) просто открываю его файл справки - JETSQL40.CHM.
> то не нашел ничего,
раздел "Предложение IN"
> да там вообще толком-то ничего нет.
???? там есть все. все что вообще есть книги/описания/статьи в инете, все оттуда взято...

> нет никаких ограничений. Что может быть?
параметр/значение может быть целочисленного типа, тогда сработает авто приведение типа.
проверь их типы.


 
Slym ©   (2008-06-09 08:14) [14]

DimonS   (07.06.08 7:50) [12]
нет никаких ограничений. Что может быть? Остальные поля вставляются нормально

если Source создается динамически (как я привел выше), то искать проблему нужно в ДБ и форматах полей/отображения



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.07.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.043 c
2-1212864651
ply
2008-06-07 22:50
2008.07.06
сделать первую букву заглавной


2-1212653898
Kaer
2008-06-05 12:18
2008.07.06
Не работает Int64


6-1186510169
Балбес
2007-08-07 22:09
2008.07.06
TServerSocket и несколько подключений


2-1212608338
kami
2008-06-04 23:38
2008.07.06
Как организовать одновременное чтение из COM-порта


15-1211534621
Slider007
2008-05-23 13:23
2008.07.06
С днем рождения ! 23 мая 2008 пятница





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский