Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Изменение значений полей в 2х таблицах ADO


Автор: RuthlessD 16.6.2011, 19:54
Доброе время суток, подскажите пожалуйста как можно выполнить задачу -
имеются 2 таблицы, в первой таблице 1 поле - специальность, оно же и ключевое. Во второй таблице поля специальность и дисциплина(дисциплина ключевое). Вопрос состоит в том, как сделать возможным изменение специальности в первой таблице, с последующими заменами этих же специальностей на новое значение, во второй таблице.

Добавлено через 1 час 2 минуты
Вот код того как я изменяю изменяю данные в первой таблице:

Жму на форме кнопку изменения данных.
procedure TForm12.Button2Click(Sender: TObject);
begin
Form13.show;
Adotable1.Edit;
end;



это кнопка на другой форме, с помощью которых я изменяю на введенные значение в dbedit
procedure TForm13.Button1Click(Sender: TObject);
begin
if dbedit1.text='' then begin messagebox(0,'Введите специальность!','Внимание',MB_OK); Abort; end else
form12.adotable1.post;
Form13.Close;
end;
  

Автор: Akella 16.6.2011, 23:00
Наверное скоро откроем специальный раздел в Delphi для студентов

Автор: Данкинг 16.6.2011, 23:53
Если каждая специальность имеет своё значение ключа, то заменить запросом - с условием WHERE - не составит труда. smile 

Автор: RuthlessD 17.6.2011, 04:39
Я не использую ADOQuery...

Автор: 14SatanA88 17.6.2011, 08:37
Цитата(RuthlessD @  16.6.2011,  19:54 Найти цитируемый пост)
TForm12 TForm13
  smile 

по сабжу
ну пройдись for'ом и поменяй

и еще.
пользуйся кнопкой "код", а то невозможно читать.

Автор: RuthlessD 17.6.2011, 08:44
14SatanA88, Я только учусь, название форм я не менял потому что мне так реально удобно, я знаю что где есть, хоть и не красиво.
А насчет фора, я даже не представляю как это сделать. У меня была чуть другая мысль: изменяя какую либо специальность, в первую переменную записывалось бы изменяемое значение, а во вторую то на что изменили. Потом в другой таблице через локейт(locate) сделать сортировку по первой переменной и заменить на значение из 2й переменной. Но как это организовать хоть убейте не знаю, не могу....

Автор: 14SatanA88 17.6.2011, 09:01
Цитата

Я только учусь


я сам недавно только колледж окончил

Цитата

название форм я не менял потому что мне так реально удобно


рекомендую менять название компонентов (и форм в частности) на свои. это реально удобней. сам прошел этот этап.

Цитата

через локейт(locate) сделать сортировку


вообще locate - это поиск

ну сделай замену так
Код

adotable1.first; // таблицу в начало
adotavle1.edit; // разрешаем редактирование, иначе вылетит
for i:=1 to adotable1.recordcount do // от 1 (первая запись) до recordcoun (число записей вообще)
begin
if (adotable1.fieldbyname('spec').asstring=old_spec) then adotable1.fieldbyname('spec').asstring:=new_spec; // проверка и замена 
adotable1.post; // сохранить изменения записи
adotable1.next; // перейти к следующей
end;


if (adotable1.fieldbyname('spec').asstring=old_spec) then adotable1.fieldbyname('spec').asstring:=new_spec; 
здесь у тебя будет:
spec - имя поля, где специальность
old_spec - строковая переменная, где ты запишешь старую специальность
new_spec - строковая переменная, где новая специальность

а вообще sql-ем лучше. но я в нем не шарю практически

Автор: chip_and_dayl 17.6.2011, 09:03
Цитата(RuthlessD @  16.6.2011,  19:54 Найти цитируемый пост)
Вопрос состоит в том, как сделать возможным изменение специальности в первой таблице, с последующими заменами этих же специальностей на новое значение, во второй таблице.


Организовать правильно структуру базы и тогда такого извращения не будет. + знание СКЛ запросов не помешало бы

Добавлено через 3 минуты и 21 секунду
НО если уже пошли извращаться, то лучше сделать обновление через запрос, иначе если будет записей свыше 1 000, то будет не гуд.

Запрос типа

Код

update Таблица set ПОЛЕ_СПЕЦИАЛЬНОСТЬ = НОВОЕ ЗНАЧЕНИЕ where ПОЛЕ_СПециальность=СТАРОЕ_ЗНАЧЕНИЕ

Автор: RuthlessD 17.6.2011, 09:38
14SatanA88,  Появляется ошибка, когда я жму на кнопку изменить ...... raised exception class EDatabaseError with message 'ADOTable2: Dataset not in edit or insert mode'.



Вот кнопка зименить. 
procedure TForm13.Button1Click(Sender: TObject);
var spec,newspec:string; I:integer;
begin
spec:=form12.ADOTable1.FieldByName('Specialnost').Value;
if dbedit1.text='' then begin  messagebox(0,'Введите специальность!','Внимание',MB_OK); Abort; end  else
newspec:=dbedit1.Text;
form12.adotable1.post;

form12.adotable2.edit;        // разрешаем редактирование, иначе вылетит
form12.adotable2.first; // таблицу в начало
for i:=1 to form12.adotable2.recordcount do // от 1 (первая запись) до recordcoun (число записей вообще)
begin
if (form12.adotable2.fieldbyname('Specialnost').asstring=spec) then form12.adotable2.fieldbyname('Specialnost').asstring:=newspec; // проверка и замена
form12.adotable2.post; // сохранить изменения записи
form12.adotable2.next; // перейти к следующей
Form13.Close;
end;
end;


Эта кнопка находится на форме, которую открываю с помощью 
procedure TForm12.Button2Click(Sender: TObject);
begin
Form13.show;
Adotable1.Edit; // Тут я в эдит 1й дататэйбл перевожу. 
end;



chip_and_dayl,  Да понимаю, но структуру уже поздно менять, мне этот проект надо доделывать....
В ADotable вроде же нельзя SQL пользоваться (?

Автор: Данкинг 17.6.2011, 09:38
Какой нафиг цикл, если запросом это будет наиболее быстро.

Добавлено через 1 минуту и 15 секунд
Цитата(RuthlessD @ 17.6.2011,  05:39)
Я не использую ADOQuery...

А, так это принцип такой, что ли? smile Ну, тогда перебирай в цикле и юзай .Edit ... .Post.

Автор: 14SatanA88 17.6.2011, 09:40
Цитата(RuthlessD @  17.6.2011,  09:38 Найти цитируемый пост)
Появляется ошибка, когда я жму на кнопку изменить ...... raised exception class EDatabaseError with message 'ADOTable2: Dataset not in edit or insert mode'.


значит ты пытаешься записать значение в таблицу, к которой доступ закрыт.

пользуйся кнопкой "код", когда постишь код.

на какой строке ошибка?

Добавлено через 39 секунд
Цитата(Данкинг @  17.6.2011,  09:38 Найти цитируемый пост)
запросом это будет наиболее быстро

плюсую.
да и кода меньше

Автор: RuthlessD 17.6.2011, 09:47
На какой строке не пишиь, жму Break, экран показывает просто весь код, нигде ничего не выделяя, а программа продолжает работать.


Код

procedure TForm13.Button1Click(Sender: TObject);
var spec,newspec:string; I:integer;
begin
spec:=form12.ADOTable1.FieldByName('Specialnost').Value;
if dbedit1.text='' then begin  messagebox(0,'Введите специальность!','Внимание',MB_OK); Abort; end  else
newspec:=dbedit1.Text;
form12.adotable1.post;

form12.adotable2.edit;        // разрешаем редактирование, иначе вылетит
form12.adotable2.first; // таблицу в начало
for i:=1 to form12.adotable2.recordcount do // от 1 (первая запись) до recordcoun (число записей вообще)
begin
if (form12.adotable2.fieldbyname('Specialnost').asstring=spec) then form12.adotable2.fieldbyname('Specialnost').asstring:=newspec; // проверка и замена
form12.adotable2.post; // сохранить изменения записи
form12.adotable2.next; // перейти к следующей
Form13.Close;
end;
end;



Может я дурачек и не правильно определяю старое значение 
Код

spec:=form12.ADOTable1.FieldByName('Specialnost').Value;

Автор: 14SatanA88 17.6.2011, 09:55
Код

procedure TForm13.Button1Click(Sender: TObject);
var spec,newspec:string; I:integer;
begin
spec:=form12.ADOTable1.FieldByName('Specialnost').Value;
if dbedit1.text='' then begin  messagebox(0,'Введите специальность!','Внимание',MB_OK); Abort; end  else
newspec:=dbedit1.Text;
form12.adotable1.post;

form12.adotable2.edit;        // разрешаем редактирование, иначе вылетит
form12.adotable2.first; // таблицу в начало
for i:=1 to form12.adotable2.recordcount do // от 1 (первая запись) до recordcoun (число записей вообще)
begin
if (form12.adotable2.fieldbyname('Specialnost').asstring=spec) then form12.adotable2.fieldbyname('Specialnost').asstring:=newspec; // проверка и замена
form12.adotable2.post; // сохранить изменения записи
form12.adotable2.next; // перейти к следующей
Form13.Close;
end;
end;


ну попробуй строку 9 перенести в начало процедуры.

Цитата

Может я дурачек и не правильно определяю старое значение 
spec:=form12.ADOTable1.FieldByName('Specialnost').Value;


тогда другой тип еррора был бы.
тут именно попытка изменения данных таблицы, доступ к которой не открыт

Автор: RuthlessD 17.6.2011, 09:59
Не помогло, я даже при нажатии на кнопку - вызове формы с кнопкой изменения, добавил кол Adotable2.edit...

Автор: 14SatanA88 17.6.2011, 10:03
ну тогда надо отслеживать где ошибка
прицепи исходник, я посмотрю

Автор: RuthlessD 17.6.2011, 10:08
Хорошо, вот. Только может еще 1 проблема быть, delphi embarcadero.delphi.xe.rtm.v15.0.3890.34076.lite.v4.0, столкнулся с тем что его проекты не каждый delphi открывает.

Автор: chip_and_dayl 17.6.2011, 10:20
Если посмотреть код, то видим следующее

Добавлено через 31 секунду
Метод ЕДит мы вызываем один раз. А метод сохранения ПОСТ больше одного раза

Добавлено через 1 минуту и 35 секунд
Вообще не понятно зачем вызывать ЕДит когда мы еще не уверены в том, будут данные для редактирования или нет

Добавлено через 2 минуты и 47 секунд
Кстати.... закрытие Формы в цикле тоже меня удивило

Автор: RuthlessD 17.6.2011, 10:29
Эдитов там нормальное количество раз вызывается. И для каждой эдита - свой пост в зависимости какой ADOtable мы пользуемся.
А про закрытие, вы о чем?

Автор: 14SatanA88 17.6.2011, 10:30
Цитата

Вообще не понятно зачем вызывать ЕДит когда мы еще не уверены в том, будут данные для редактирования или нет


да, логично

надо бы заменить 
Код

if (adotable1.fieldbyname('spec').asstring=old_spec) then adotable1.fieldbyname('spec').asstring:=new_spec; // проверка и замена 
adotable1.post;

на
Код

if (adotable1.fieldbyname('spec').asstring=old_spec) then begin
adotable1.fieldbyname('spec').asstring:=new_spec; // проверка и замена 
adotable1.post;
end;


Добавлено @ 10:32
у меня проблемы с открытием твоего сырца.

Добавлено @ 10:34

Цитата(RuthlessD @  17.6.2011,  10:29 Найти цитируемый пост)
А про закрытие, вы о чем?


ты Form13.Close; в цикл положил

Автор: chip_and_dayl 17.6.2011, 10:35
Цитата(RuthlessD @  17.6.2011,  10:29 Найти цитируемый пост)
Эдитов там нормальное количество раз вызывается. И для каждой эдита - свой пост в зависимости какой ADOtable мы пользуемся.

Код

procedure TForm13.Button1Click(Sender: TObject);
var spec,newspec:string; I:integer;
begin
spec:=form12.ADOTable1.FieldByName('Specialnost').Value;
if dbedit1.text='' then begin  messagebox(0,'Введите специальность!','Внимание',MB_OK); Abort; end  else
newspec:=dbedit1.Text;
form12.adotable1.post;

form12.adotable2.edit;        // разрешаем редактирование, иначе вылетит
form12.adotable2.first; // таблицу в начало
for i:=1 to form12.adotable2.recordcount do // от 1 (первая запись) до recordcoun (число записей вообще)
begin
if (form12.adotable2.fieldbyname('Specialnost').asstring=spec) then form12.adotable2.fieldbyname('Specialnost').asstring:=newspec; // проверка и замена
form12.adotable2.post; // сохранить изменения записи
form12.adotable2.next; // перейти к следующей
Form13.Close;
end;
end;

form12.adotable2.edit; вызывается один раз. Так как он вне цикла. Что такое цикл пояснить?
А ПОСТ идет в цикле и бцудет вызываться столько, сколько будет старых записей

14SatanA88, 
Почти
Должно быть так
Код

if (adotable1.fieldbyname('spec').asstring=old_spec) then begin
adotable1.edit;
adotable1.fieldbyname('spec').asstring:=new_spec; // проверка и замена 
adotable1.post;
end;

А тот что выше убрать

Цитата(RuthlessD @  17.6.2011,  10:29 Найти цитируемый пост)
А про закрытие, вы о чем?

ФОрма закроется сразу после изменения первой записи и весь цикл прервется

Автор: 14SatanA88 17.6.2011, 10:35
Цитата(chip_and_dayl @  17.6.2011,  10:20 Найти цитируемый пост)
Метод ЕДит мы вызываем один раз. А метод сохранения ПОСТ больше одного раза

все верно. разве нет?

Edit дает возможность писать в таблицу данных
а Post сохраняет текущую запись

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

Автор: chip_and_dayl 17.6.2011, 10:39
Нормально оно сработает один раз. Так как после вызова метода Пост, метод Едит как бы отменяется. То беж для каждого Поста, точнее перед каждым ПОСТОМ нужно вызывать свой Едит

Автор: 14SatanA88 17.6.2011, 10:42
Цитата(chip_and_dayl @  17.6.2011,  10:39 Найти цитируемый пост)
Нормально оно сработает один раз

хм... у меня так несколько прог работает...

Edit;
for... begin
  изменение
  Post;
end;

Автор: RuthlessD 17.6.2011, 10:49
chip_and_dayl, я вставил в цикл эдит:
Код

procedure TForm13.Button1Click(Sender: TObject);
var spec,newspec:string; I:integer;
begin
form12.adotable1.edit;
form12.adotable2.edit;
spec:=form12.ADOTable1.FieldByName('Specialnost').Value;
if dbedit1.text='' then begin  messagebox(0,'Введите специальность!','Внимание',MB_OK); Abort; end  else
newspec:=dbedit1.Text;
form12.adotable1.post;

        // разрешаем редактирование, иначе вылетит
form12.adotable2.first; // таблицу в начало
for i:=1 to form12.adotable2.recordcount do // от 1 (первая запись) до recordcoun (число записей вообще)
begin
if (form12.adotable2.fieldbyname('Specialnost').asstring=spec) then begin
form12.adotable2.edit;
form12.adotable2.fieldbyname('Specialnost').asstring:=newspec; // проверка и замена
form12.adotable2.post;// сохранить изменения записи
end;
form12.adotable2.next; // перейти к следующей
end;
Form13.hide;
end;



14SatanA88,  chip_and_dayl,  теперь ошибки нет, но он не заменяет (

Автор: Akella 17.6.2011, 10:50
ты когда-нибудь код научишься форматировать?

Автор: chip_and_dayl 17.6.2011, 10:55
Цитата(14SatanA88 @  17.6.2011,  10:42 Найти цитируемый пост)
хм... у меня так несколько прог работает...Edit;for... begin  изменение  Post;end;

А кто-то головою стенки разбивает, и что!?! И мы будем теперь стенку головой бить, вместо того чтобы взять специальный инструмент для этого?smile

Я не знаю как оно работает у тебя... но всему есть объяснение. или запись тогда одна или еще что-то

Автор: 14SatanA88 17.6.2011, 10:58
Цитата(chip_and_dayl @  17.6.2011,  10:55 Найти цитируемый пост)
Я не знаю как оно работает у тебя

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

Добавлено через 13 минут и 48 секунд
Цитата(RuthlessD @  17.6.2011,  10:49 Найти цитируемый пост)
но он не заменяет

судя по коду, должен заменять.
где-то накосячил

Автор: RuthlessD 17.6.2011, 11:14
14SatanA88, Он заменяет значение для первой таблицы, но не заменяет на новые во второй...
Может я не правильно с переменными работаю, наверное старые и новые значение определять как то по другому надо?
Но во второй таблице он переходит к последней записи.

Автор: 14SatanA88 17.6.2011, 11:26
они не меняются скорей всего потому, что у тебя значения одинаковые и при сравнении не выполняется замена.
проверь свои строковые переменные, то есть их значения конкретно.

Автор: RuthlessD 17.6.2011, 11:44
14SatanA88,  Кажется ясно ) еще 2 обычных эдита добавил, и им присвоил значения переменных. Значения в переменных одинаковые, они обе новые.... Как выудить все таки старое значение до его изменения ?

Автор: 14SatanA88 17.6.2011, 11:51
Цитата

Как выудить все таки старое значение до его изменения ?


spec:=form12.ADOTable1.FieldByName('Specialnost').Value;

но делай это до того, как меняешь в первой таблице. 

Автор: RuthlessD 17.6.2011, 11:51
smile ура решил эту проблему, всё заработало !!!

Добавлено @ 11:53
14SatanA88,  Да можно так сказать и сделал =) вызываю форму для редактирования
Код

procedure TForm12.Button2Click(Sender: TObject);
begin
edit1.Text:=adotable1.FieldByName('Specialnost').Value; //в эдите хранится старое значение
Form13.show;
Adotable1.Edit;
adotable2.Edit;
end;
 
После вызываю процедуру изменения и заменяю. =) пользуясь значением из эдита =)

Автор: 14SatanA88 17.6.2011, 11:55
ну все, ставь галочку что вопрос решен

Автор: RuthlessD 17.6.2011, 12:04
Огромнейшее тебе спасибо! Просто спас меня...!!!

Автор: 14SatanA88 17.6.2011, 12:05
не за что

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)