Определение наилучшего метода обхода таблицы и обновления другой таблицы

Я использую Delphi 7, BDE и Interbase (тестирование), Oracle (производство).

У меня две таблицы (Мастер, Ответы)

Мне нужно пройтись по таблице Responses, использовать ее поле Master_Id, чтобы найти его в главной таблице (id) для соответствующей записи и обновить поле даты в таблице Master с полем даты в таблице Responses

Можно ли это сделать в SQL, или мне действительно нужно создать два TTables или TQueries и пройти через каждую запись?

Пример:

Откройте две таблицы (Таблица1, Таблица2)

with Table1 do
begin
 first;
 while not EOF do
 begin
  //get master_id field
  //locate in id field in table 2
  //edit record in table 2
  next;
 end;
end;  

Благодарность


person IElite    schedule 08.02.2011    source источник
comment
опубликуйте DDL для таблиц, кто-то напишет для вас один запрос   -  person Stephanie Page    schedule 08.02.2011
comment
НИКОГДА, НИКОГДА, НИКОГДА цикл для обработки строк ... хорошо, не никогда, иногда приходится, но это очень редко ... как GOTO.   -  person Stephanie Page    schedule 08.02.2011
comment
О, и выучите немного SQL ... это потрясающий язык ... одна команда ооочень мощно.   -  person Stephanie Page    schedule 08.02.2011
comment
это было поощрением, а не критикой.   -  person Stephanie Page    schedule 08.02.2011
comment
Вы не можете использовать Interbase в качестве тестовой базы данных для производственной базы данных Oracle. Есть много различий в поддерживаемом ими SQL.   -  person    schedule 08.02.2011
comment
BDE довольно старый и не поддерживается, если это новый проект, рассмотрите возможность использования текущего и поддерживаемого уровня подключения к базе данных, например dbExpress.   -  person jachguate    schedule 08.02.2011
comment
Два обходных шага: вы должны попытаться избежать BDE (если вы его используете, используйте его только для локальных баз данных на основе файлов, таких как Paradox или dBase), и постарайтесь избежать with, поместив код в блок with в функцию. OTOH: хороший вопрос (+1); вы должны сделать это в SQL, как показали ответы.   -  person Jeroen Wiert Pluimers    schedule 08.02.2011
comment
BDE здесь не имеет значения. Пока в базу данных отправляется правильный SQL, вы даже можете использовать pidgeon для отправки запроса, и все будет в порядке. Более того, dbExpress в Delphi 7 полон ошибок, а драйвер Oracle - шутка. Тогда SQLLINKS работал намного лучше.   -  person    schedule 09.02.2011


Ответы (2)


Одно небольшое изменение в запросе Криса: добавьте предложение where, чтобы выбрать только те записи, которые нуждаются в обновлении. В противном случае он установит остальные даты в NULL

UPDATE Master m
SET 
    m.date = (SELECT r.date FROM Reponses r WHERE r.master_id = m.id) 
WHERE m.id IN (SELECT master_id FROM Responses)

Обновлено для использования псевдонимов, чтобы избежать путаницы, какой столбец из какой таблицы. Это не готовый запрос, допускающий копирование, поскольку синтаксис UPDATE отличается от базы данных к базе данных. Вам может потребоваться обратиться к справочнику sql вашей базы данных для JOIN в синтаксисе оператора UPDATE.

Когда есть несколько ответов на одну и ту же главную запись

UPDATE Master m 
SET      m.date = (
    SELECT MAX(r.date) FROM Reponses r WHERE r.master_id = m.id)  
WHERE m.id IN (SELECT master_id FROM Responses) 

Я использовал MAX (), вы можете использовать все, что подходит для вашего бизнеса. Снова потратьте немного времени на понимание SQL. Это едва ли несколько дней усилий. Получите полную справку по PLSQL, если вы работаете в Oracle

person d-live    schedule 08.02.2011
comment
Я здесь немного запутался. Это будет ID для главной таблицы и Master_Id для таблицы Reponses. Это все еще верно с вашим ответом? - person IElite; 08.02.2011
comment
У меня это не работает. Переходит в исключение в команде ExecSQL - person IElite; 09.02.2011
comment
Общая ошибка SQL - несколько строк при выборе одиночного элемента. - person IElite; 09.02.2011
comment
Это должно было показать вам способ, это не должно было быть выполнимым запросом. Обновленный ответ с дополнительными пояснениями. - person d-live; 09.02.2011
comment
Ну, я утверждал, что это было для interbase и orac; e. Если вы можете получить его, чтобы он работал в Intgerbase, этого будет достаточно - person IElite; 10.02.2011
comment
даже с вашим обновлением я все равно получаю: Общая ошибка SQL - несколько строк при выборе синглтона - person IElite; 10.02.2011
comment
Это означает, что для данного основного идентификатора существует несколько записей ответа. В зависимости от вашего бизнеса вы можете использовать дату последнего ответа в таких случаях, снова просмотрите обновление. - person d-live; 11.02.2011

Попробуйте этот SQL (измените имена в соответствии с вашей ситуацией)

UPDATE Master m SET date = (ВЫБРАТЬ дату ИЗ ответов WHERE id = m.id)

person Chris Hogan    schedule 08.02.2011
comment
как в моем комментарии выше, разве это не было бы: UPDATE Master m SET bank_cleared = (SELECT bank_date FROM Responses WHERE master_id = m.id) - person IElite; 08.02.2011
comment
Да, я просто не был уверен на 100%, какие у вас были названия полей. - person Chris Hogan; 08.02.2011
comment
@Chris - У меня это не работает. Переходит в исключение в команде ExecSQL - person IElite; 09.02.2011
comment
Что ж, тогда вы должны опубликовать исключение :) Трудно угадать, пока оно находится на вашей машине ... - person ; 09.02.2011
comment
Да, пожалуйста. Что это за исключение? - person Chris Hogan; 09.02.2011
comment
Общая ошибка SQL - несколько строк при выборе одиночного элемента. Это сообщение встречается как в ответах Криса Хогана, так и в ответах d-live. - person IElite; 09.02.2011
comment
Я предполагаю, что это связано с тем, что отношение от мастера к ответам - 1 ко многим, поэтому подзапрос возвращает несколько значений для bank_date, но основной запрос ожидает, что одно значение будет присвоено bank_cleared. Вам нужно будет настроить подзапрос, чтобы он возвращал одну дату, например, измените SELECT bank_date на SELECT MAX (bank_date). - person Chris Hogan; 09.02.2011
comment
Что ж, это сработало без ошибок, к сожалению, он заполнил дату bank_cleared главной таблицы максимальной датой. Были даты 26.01.11, 27.01.11 и 28.01.11, которые следовало обновить, но поле было заполнено всеми датами 28.01.11 - спасибо - person IElite; 09.02.2011