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

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

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

Delphi.int.ru Expert

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

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

#   

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


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

DNK
I. DNK
Баллы: 5

Подробнее »



Вопрос # 1 806

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

Здравствуйте, уважаемые эксперты!
Подскажите , как можно сделать так чтобы при изменении в gride записи она автомотически изменялась во всех таблицах где она встречается .... я предпринимала некоторые попытки но выскакивает сообщение: resultat : Dataset not in edit or insert mode --- > это при попытке № раз (код №1)
Либо вообще ничего не происходит (Код №2)

Приложение:
  1.  
  2. i:integer;
  3. begin
  4. for i:=1 to DM.resultat.RecordCount do
  5. begin
  6. if dm.resultat.FieldByName('ID_D').AsInteger=DM.dogovor.FieldByName('ID_D').AsInteger then
  7.  
  8. if dm.resultat.FieldByName('ID_C').AsInteger=DM.klient.FieldByName('ID_C').AsInteger then
  9.  
  10. end;
  11.  
  12.  
  13. If DM.klient.FieldByName('id_c')=dm.resultat.FieldByName('id_c') then
  14.  
  15.  


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

Вопрос задала: Танюшка (статус: Посетитель)
Вопрос отправлен: 7 августа 2008, 10:56
Состояние вопроса: открыт, ответов: 3.

Ответ #1. Отвечает эксперт: Помфюк Владимир Степанович

Здравствуйте, Танюшка!
перед изменением таблицы надо бы её перевести в режим редактирования:
dm.resultat.edit;

Ответ отправил: Помфюк Владимир Степанович (статус: Абитуриент)
Время отправки: 7 августа 2008, 11:01

Ответ #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:02 [#1]:

а зачем два одинаковых вопроса?
Танюшка

Танюшка (статус: Посетитель), 7 августа 2008, 11:23 [#2]:

я извиняюсь за повторение просто не знала что при обновлении мой вопрос отсылается дважды .
теперь пишет ошибку: "Не удается найти строку для обнавления, некоторые значения могли быть изменены со времени ее последнего чтения ."
Что еще нужно добавить?
ANBsoft

ANBsoft (статус: Студент), 7 августа 2008, 11:30 [#3]:

И если нужно переносить данные из одного запроса в другой, то лучше это делать по событию AfterPost измененного запроса.
Танюшка

Танюшка (статус: Посетитель), 7 августа 2008, 11:46 [#4]:

Так тож не получается оно в базе изменения только в опред таблицах делает а там где нужно то есть в результирующей старые записи не меняет а это оч нужно сделать ...
ANBsoft

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

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

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

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

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

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] [Следующая »]

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

Версия движка: 2.6+ (26.01.2011)
Текущее время: 23 июля 2017, 05:53
Выполнено за 0.14 сек.
Рейтинг@Mail.ru