|
Вопрос # 1 806/ вопрос открыт / |
|
Здравствуйте, уважаемые эксперты!
Подскажите , как можно сделать так чтобы при изменении в gride записи она автомотически изменялась во всех таблицах где она встречается .... я предпринимала некоторые попытки но выскакивает сообщение: resultat : Dataset not in edit or insert mode --- > это при попытке № раз (код №1)
Либо вообще ничего не происходит (Код №2)
Приложение: Переключить в обычный режим-
- i:integer;
- begin
- for i:=1 to DM.resultat.RecordCount do
- begin
- if dm.resultat.FieldByName('ID_D').AsInteger=DM.dogovor.FieldByName('ID_D').AsInteger then
-
- if dm.resultat.FieldByName('ID_C').AsInteger=DM.klient.FieldByName('ID_C').AsInteger then
-
- end;
-
-
- If DM.klient.FieldByName('id_c')=dm.resultat.FieldByName('id_c') then
-
-
 |
Вопрос задала: Танюшка (статус: Посетитель)
Вопрос отправлен: 7 августа 2008, 10:56
Состояние вопроса: открыт, ответов: 3.
|
Ответ #1. Отвечает эксперт: Помфюк Владимир Степанович
Здравствуйте, Танюшка!
перед изменением таблицы надо бы её перевести в режим редактирования:
dm.resultat.edit;
Ответ #2. Отвечает эксперт: ANBsoft
Здравствуйте, Танюшка!
А по окончании редактирования записи нужно выполнить
dm.resultat.post;
это для сохранения сделанных изменей.
Каким гридом пользуемся?
При использовании TDBGrid все действия происходят автоматически.
Чтобы его подключить к запросу, ставим на форма TDataSource, в поле DataSet указываем свой запрос.
После этого ставим TDBGrid и в поле DataSource указываем описанный TDataSource.
Это намного удобнее чем делать через обычные гриды.
 |
Ответ отправил: ANBsoft (статус: Студент)
Время отправки: 7 августа 2008, 11:13
Оценка за ответ: 5
|
Ответ #3. Отвечает эксперт: Шичко Игорь
Здравствуйте, Танюшка!
А Вы не пробовали при анализе таблиц dogovor и klient воспользоваться SQL-запросами.
Мне кажется это будет немного попроще:
i, temp:integer;
begin
DM.resultat.First; //переходим на первую запись
for i:=1 to DM.resultat.RecordCount do
begin
temp:= dm.resultat.FieldByName('ID_D').AsInteger;
SQLdogovor.SQL.Text:= "Select ID_D, Fields[1] from dogovor where ID_D = temp;
SQLdogovor.Open; SQLdogovor.First; // считываем запись из dogovor по ID_D
SQLclient.SQL.Text:= "Select ID_D, Fields[1] from client where ID_D = temp;
SQLclient.Open; SQLclient.First; // считываем запись из client по ID_D
dm.resultat.edit; // редактирование
dm.resultat.FieldByName('Наименование').AsString:=SQLdogovor.Fields.Fields[1].AsString;
dm.resultat.FieldByName('ФИО').AsString:=SQLclient.Fields.Fields[1].AsString;
dm.resultat.post;
SQLdogovor.Close;
SQLclient.Close;
DM.resultat.Next;
end;
end;
SQLclient и SQLdogovor - TADOQuery
 |
Ответ отправил: Шичко Игорь (статус: 9-ый класс)
Время отправки: 7 августа 2008, 12:05
|
Мини-форум вопроса
Всего сообщений: 23; последнее сообщение — 7 августа 2008, 20:05; участников в обсуждении: 5.
Страницы: [1] [2] [Следующая »]
|
Танюшка (статус: Посетитель), 7 августа 2008, 11:23 [#2]:
я извиняюсь за повторение просто не знала что при обновлении мой вопрос отсылается дважды .
теперь пишет ошибку: "Не удается найти строку для обнавления, некоторые значения могли быть изменены со времени ее последнего чтения ."
Что еще нужно добавить?
|
|
ANBsoft (статус: Студент), 7 августа 2008, 11:30 [#3]:
И если нужно переносить данные из одного запроса в другой, то лучше это делать по событию AfterPost измененного запроса.
|
|
Танюшка (статус: Посетитель), 7 августа 2008, 11:46 [#4]:
Так тож не получается оно в базе изменения только в опред таблицах делает а там где нужно то есть в результирующей старые записи не меняет а это оч нужно сделать ...
|
|
ANBsoft (статус: Студент), 7 августа 2008, 11:46 [#5]:
Кроме того, Ваш код во многих случаях вообще не будет работать (так как RecordCount возвращает количество уже полученных записей, а не полное их количество).
Я бы рекомендовал на событие AfterPost Ваших запросов Dogovor и Klient поставить такой код:
if dm.resultat.Locate('ID_D',DM.dogovor.FieldByName('ID_D').AsInteger,[]) then begin
dm.resultat.Edit;
dm.resultat.FieldByName('Наименование').AsString:=DM.dogovor.Fields.Fields[1].AsString;
dm.resultat.Post;
end
else ShowMessage('Запись не найдена');
и
if dm.resultat.Locate('ID_C',DM.klient.FieldByName('ID_C').AsInteger,[]) then begin
dm.resultat.Edit;
dm.resultat.FieldByName('ФИО').AsString:=DM.klient.Fields.Fields[1].AsString;
dm.resultat.Post;
end
else ShowMessage('Запись не найдена');
Так будет намного лучше.
|
|
Танюшка (статус: Посетитель), 7 августа 2008, 11:53 [#6]:
Сейчас попробую ...
|
|
Танюшка (статус: Посетитель), 7 августа 2008, 11:54 [#7]:
Спасибо вам огромное!!!!!!!!!!!!!!!!!Бубырь Александр Николаевич !!!!!!!!!!!
Вышло просто так как было нужно ))))))))))))
|
|
ANBsoft (статус: Студент), 7 августа 2008, 12:03 [#8]:
Значит можно и оценку поставить .
|
|
Танюшка (статус: Посетитель), 7 августа 2008, 12:42 [#9]:
Извините за навязчивость, но тут такое дело, почему-то меняется только одна запись , а все остальные остаются без изменения......... может тут еще цикл какой-нить добавить...
|
|
Помфюк Владимир Степанович (статус: Абитуриент), 7 августа 2008, 12:52 [#10]:
Проще всего воспользоватся видоизменённом советом Игоря Шичко: использовать SQL-запросы update:
SQLresultat.SQL.Text:= 'update resultat set Наименование='''+DM.dogovor.Fields.Fields[1].AsString+''' where ID_D ='+DM.dogovor.FieldByName('ID_D').AsString;
тогда точно обновлятся все записи c совпадающими ID_D
|
|
ANBsoft (статус: Студент), 7 августа 2008, 13:03 [#11]:
если записей много, можно переделать так:
dm.resultat.First;
if dm.resultat.FieldByName('ID_D').AsInteger=DM.dogovor.FieldByNamedm.resultat.Edit;
dm.resultat.FieldByName('Наименование').AsString:=DM.dogovor.Fields.Fields[1].AsString;
dm.resultat.Post;
end;
('ID_D').AsInteger then begin
while dm.resultat.LocateNext('ID_D',DM.dogovor.FieldByName('ID_D').AsInteger,[]) do begin
dm.resultat.Edit;
dm.resultat.FieldByName('Наименование').AsString:=DM.dogovor.Fields.Fields[1].AsString;
dm.resultat.Post;
end;
Хотя лучше будет описанный выше массовый апдейт.
|
|
ANBsoft (статус: Студент), 7 августа 2008, 13:06 [#12]:
Пардон, как-то коряво отослало, еще раз:
если записей много, можно переделать так:
dm.resultat.First;
if dm.resultat.FieldByName('ID_D').AsInteger=DM.dogovor.FieldByName('ID_D').AsInteger then begin
dm.resultat.Edit;
dm.resultat.FieldByName('Наименование').AsString:=DM.dogovor.Fields.Fields[1].AsString;
dm.resultat.Post;
end;
while dm.resultat.LocateNext('ID_D',DM.dogovor.FieldByName('ID_D').AsInteger,[]) do begin
dm.resultat.Edit;
dm.resultat.FieldByName('Наименование').AsString:=DM.dogovor.Fields.Fields[1].AsString;
dm.resultat.Post;
end;
Хотя лучше будет описанный выше массовый апдейт.
|
|
Шичко Игорь (статус: 9-ый класс), 7 августа 2008, 13:35 [#13]:
Одна запись поэтому и корректируется, потому что нужно использовать структуру
First
for...
begin
...
Next
end;
Как я ранее уже написал, согласен также с
Помфюк Владимир Степанович
|
|
ANBsoft (статус: Студент), 7 августа 2008, 13:57 [#14]:
В общем, выбор зависит от конкретных задач, описанные мной алгоритмы позволяют программно контролировать все вносимые изменения, массовые апдейты несомненно проще и быстрее, но в некоторых случаях потребуют усложнения бизнес-правил самой базы данных, а это сложнее отлаживается и не все базы позволяют это делать (например если при изменении каждой записи в resultat нужно изменять в соответствии с ней еще какие-то зависимые таблицы или делать пересчеты).
Описанные варианты позволяют выбирать в зависимости от конкретных задач, далее каждый выбирает сам.
|
|
Шичко Игорь (статус: 9-ый класс), 7 августа 2008, 14:23 [#15]:
to Бубырь Александр Николаевич
Совершенно согласен, кроме этого влияние имеет какой размер базы планируется использовать
|
|
Вадим К (статус: Академик), 7 августа 2008, 14:45 [#16]:
to Шичко Игорь
ваша конструкция с for плоха. плоха по той причине, что для некоторых баз получения общего кол-ва записей - долгая операция.
Но это пол проблемы. если не сделать транзакцию, то может оказаться, что на момент прохода по записям, кол-во может отличаться. (это возможно при совместной работе нескольких пользователей).
правильная конструкция выглядит где то так.
MyTable.first;
while not MyTable.eof do begin
//код обработки записи
//....
MyTable.next
end;
Для некоторых типов баз такой "проход" гораздо эффективнее.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Танюшка (статус: Посетитель), 7 августа 2008, 15:28 [#17]:
а что это за LocateNext?
|
|
Шичко Игорь (статус: 9-ый класс), 7 августа 2008, 15:31 [#18]:
to Вадим К
Вадим, согласен, но не совсем.
Подсчет количества записей насколько я понимаю происходит при открытии набора. Поэтому коль уж мы по нему идем, то подразумевается, что известно количество.
MyTable.first не сможет выполниться без открытия таблицы.
Хотя в целом мой алгоритм расчитан в большем мере на работу с наборами, созданными на основе SQL-запросов.
|
|
Вадим К (статус: Академик), 7 августа 2008, 15:45 [#19]:
есть два способа работы с базами.
в первом закачиваются все данные. в таком случае количество записей известно и по ним можно безобидно пройтись.
Но при больших объёмах, закачивать невыгодно. Поэтому запрос кол-ва записей превращается в лишний SQL запрос.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 7 августа 2008, 17:06 [#20]:
TIBCustomDataSet.LocateNext
Searches the dataset for the record after a specified record and makes that record the current record.
function LocateNext(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean;
Description
Call LocateNext to search a dataset for a record after the current cursor position
Аналогично Locate, но ищет следующую запись начиная с текущей, удовлетворяющую условию.
Правда не во всех компонентах есть, я пользуюсь TIBQuery, потому и написал по привычке.
|
Страницы: [1] [2] [Следующая »]
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|