Форум: "Начинающим";
Текущий архив: 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.048 c