Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];
ВнизКопирование данных Найти похожие ветки
← →
Вопрошающий (2004-05-14 09:53) [0]Необходимо скопировать данные из одной таблицы в другую по условию.
Запрос:UPDATE
Выполнение_Таблица ET
SET
КодВыполнившего=(SELECT
EH.КодВыполнившего
FROM
Выполнение_Шапка EH
WHERE
EH.Код=ET.КодШапки)
не проходит. Сообщение: В операции должен использоваться обновляемый запрос.
Подскажите, что надо поменять?
← →
Курдль © (2004-05-14 10:00) [1]Копировать одним скриптом - это так (но не уверен, что Access это съест):
insert into TABLE1 (...)
select from TABLE2 (...)
← →
Вопрошающий (2004-05-14 10:13) [2]Не совсем так. Похоже, я неправильно сормулировал вопрос.
Есть две таблицы. Одна из них - шапка документа. Вторая - табличная часть. Связь - по полям Шапка.Код=Таблица.КодШапки.
После изменения заказчиком требований к хранимым данным, необходимо переместить некоторые данные из шапки в строки табличной части. Конкретно: раньше по одному документу проходил один исполнитель. Теперь по разным строкам могут быть разные исполнители.
БД реорганизована. Все работает. Теперь просто необходимо в старых документах перекинуть данные (код исполнителя) из шапки документа - в каждую строку.
То-есть, не просто скопировать строки из таблицы в таблицу, а данные одного поля одной таблицы - в другое поле другой таблицы. И сделать это по условию, дескать, Таблица.КодШапки = Шапка.Код
← →
Курдль © (2004-05-14 10:23) [3]Не правильно спроектированная база. Налицо денормализация.
Надо не перемещать "из шапки в строки табличной части" а "выбирать...".
← →
Jee © (2004-05-14 10:38) [4]UPDATE ET
SET ЕТ.КодВыполнившего = EH.КодВыполнившего
FROM Выполнение_Таблица ET
INNER JOIN Выполнение_Шапка EH ON EH.Код=ET.КодШапки
WHERE <добавляй свое условие, иначе у всех строк будет исполнитель из шапки>
← →
Вопрошающий (2004-05-14 10:41) [5]Да со структурой БД все ОК.
Я же говорю: раньше по одному документу проходил один исполнитель. Поэтому в шапке было поле "КодИсполнителя". Теперь по одному документу могут проходить несколько исполнителей - по одному исполнителю на каждую строку табличной части документа. Поэтому в строки добавлено поле "КодИсполнителя".
Показываю "на пальцах".
Было:
Шапка:
Объект: Огород тети Люси
Исполнитель: Вася
Табличная часть:
Вскопка огорода - 100 руб.
Посадка картошки - 200 руб.
Внесение удобрений - 120 руб.
...
Теперь нужно:
Шапка:
Объект: Огород тети Люси
Табличная часть:
Вскопка огорода - Вася - 100 руб.
Посадка картошки - Петя - 200 руб.
Внесение удобрений - корова Мурка - 0 руб.
Вопрос: Как в старых документах, переместить данные из шапки в табличную часть?
Шапка:
Объект: Огород тети Люси
Исполнитель: Вася
Табличная часть:
Вскопка огорода - Вася - 100 руб.
Посадка картошки - Вася - 200 руб.
Внесение удобрений - Вася - 120 руб.
Чтобы после этого вообще убрать поле исполнителя из шапки...
← →
Вопрошающий (2004-05-14 10:52) [6]2Jee
К сожалению, не проходит... :(
Насколько я понимаю, прежде чем писать FROM, надо написать SELECT.
UPDATE ET
SET ЕТ.КодВыполнившего = (SELECT EH.КодВыполнившего
FROM Выполнение_Таблица ET
INNER JOIN Выполнение_Шапка EH ON EH.Код=ET.КодШапки)
И получаем то же сообщение: В операции должен использоваться обновляемый запрос.
← →
Курдль © (2004-05-14 11:01) [7]
> Шапка...
> ...табличной части
Я что-то не силен в терминологии Access-а.
Но в терминологии Баз Данных это выглядело бы так:
1. Таблица "Исполнители":
ID_исполнителя первичный_ключ,
ФИО_исполнителя.
2. Таблица "Объекты":
ID_объекта первичный_ключ,
наименование_объекта.
3. Таблица "Услуги":
ID_услуги первичный_ключ,
наименование_услуги,
тариф_услуги.
4. Таблица "Счета":
ID_счета первичный_ключ,
ID_объекта внешний_ключ,
ID_исполнителя внешний_ключ,
ID_услуги внешний_ключ
Если Вы приведете свою "базу" хотя бы к такому виду, то и мысли Ваши встанут на свое место.
← →
Вопрошающий (2004-05-14 11:10) [8]1. Таблица "Исполнители":
ID_исполнителя первичный_ключ,
ФИО_исполнителя.
2. Таблица "Объекты":
ID_объекта первичный_ключ,
наименование_объекта.
3. Таблица "Услуги":
ID_услуги первичный_ключ,
наименование_услуги,
тариф_услуги.
4.1. Таблица "Шапка_Услуг"
ID_шапки первичный_ключ
ID_объекта внешний_ключ
4.2. Таблица "ТабличнаяЧасть_Услуг"
ID_шапки первичный_ключ
Номер_Строки первичный_ключ
ID_услуги внешний_ключ
ID_исполнпителя внешний_ключ
Комментарий к 4:
Докумен "услуги" имеет "Шапку", где указано где это делается, и "Табличную часть", в которой перечисляется, что делается. Это относится не к структурам БД, это относится к обыкновенному бумажному документообороту. Жизненный пример: Накладная.
P.S. В проекте более 30 разных таблиц, связанных при помощи синтетических ключей. Мне не структура БД нужна! Мне нужно конвертануть данные из старого формата в новый!...
← →
Курдль © (2004-05-14 11:19) [9]
> Докумен "услуги" имеет "Шапку", где указано где это делается,
> и "Табличную часть", в которой перечисляется, что делается.
> Это относится не к структурам БД, это относится к обыкновенному
> бумажному документообороту. Жизненный пример: Накладная.
Это уже предмет обсуждения не БД, а "...Report"-а типа Мастер-деталь.
> Мне нужно конвертануть данные из старого формата в новый!...
И кто это может сделать за Вас, не зная структуры источника и приемника? Обратитесь к местным телепатам!
Я вижу один способ - продумать структуру приложения, которое отработает один раз на благо конвертации.
← →
Mike Kouzmine © (2004-05-14 11:21) [10]А слабо в самом аксессе построить и посмотреть?
← →
Курдль © (2004-05-14 11:23) [11]
> А слабо в самом аксессе построить и посмотреть?
Мне? СлабО... :(
Один раз глянув на работу в аксессе решил его даже не устанавливать себе на комп.
← →
Danilka © (2004-05-14 11:29) [12]Я не силен в аццессе, но, думаю что для него возможны только 2 варианта:
1. тупым перебором на клиенте, в дельфях например. т.к. операция разовая, то ничего страшного.
2. через временную таблицу.
← →
Mike Kouzmine © (2004-05-14 11:31) [13]Курдль © (14.05.04 11:23) [11] Про вас речь не идет. Такой талантище и на этом форуме.....
← →
Курдль © (2004-05-14 11:35) [14]
> Mike Kouzmine © (14.05.04 11:31) [13]
Пропустим сарказЬм, но все же меня интересует вопрос, как можно делать проект, в котором более 30 разных таблиц, связанных при помощи синтетических ключей (последняя фраза мне не совсем ясна) на Ассеss-е? Я думал, что это инструмент для юзеров уровня "пользователь МС Офис", а программисты могут упростить себе (и заказчикам) жизнь.
← →
sniknik © (2004-05-14 11:36) [15]Danilka © (14.05.04 11:29) [12]
ошибаешся вариантов больше, один из них кстати был приведен и позже благополучно исковеркан (и естественно заклеймен как неработающий).
← →
Вопрошающий (2004-05-14 11:36) [16]Исполнители:
Код - первичный ключ
ФИО - строка
Шапка_Документа:
Код - первичный ключ
КодИсполнителя - вторичный индекс (на таблицу "Исполнители")
...
ТабличнаяЧасть_Документа:
КодШапки - вторичный индекс
НомерСтроки - вместе с КодомШапки составляет первичный ключ
КодИсполнителя - вторичный индекс (на таблицу "Исполнители")
...
Сейчас КодИсполнителя в ТабличнойЧасти пустой.
Алгоритм:
1. Выбираем строку Шапки_Документа.
2. Выбираем все строки из ТабличнойЧасти_Документа, у которых КодШапки = Шапка_Документа.Код
3. Устанавливаем: ТабличнаяЧасть_Документа.КодИсполнителя := Шапка_Документа.КодИсполнителя
Как сформулировать такой SQL-запрос?
P.S. Я с Aceess"ом не работаю. И никогда не работал. Я просто использую *.mdb файл БД Access"а. С доступом через ADO.
← →
Danilka © (2004-05-14 11:38) [17][15] sniknik © (14.05.04 11:36)
> один из них кстати был приведен и позже благополучно исковеркан
[4]?
← →
sniknik © (2004-05-14 11:43) [18]Danilka © (14.05.04 11:38) [17]
ну да, посмотри что давалось и что пробовалось > [6]
если в нем и есть неточности то это дело подгонки под конкретику, а не такое.
← →
Вопрошающий (2004-05-14 11:44) [19][4]:
Ошибка синтаксиса (пропущен оператор) в выражении запроса "EH.КодВыполнившего
FROM Выполнение_Таблица ET
INNER JOIN Выполнение_Шапка EH ON EH.Код=ET.КодШапки"
← →
Mike Kouzmine © (2004-05-14 11:44) [20]Курдль © (14.05.04 11:35) [14] Очень просто. Если голова на плечах есть, то инструмент не имеет значения.
← →
Курдль © (2004-05-14 11:44) [21]
> Вопрошающий (14.05.04 11:36) [16]
Это делается на клиенте?
> Алгоритм:
> 1. Выбираем строку Шапки_Документа.
> 2. Выбираем все строки из ТабличнойЧасти_Документа, у которых
> КодШапки = Шапка_Документа.Код
> 3. Устанавливаем: ТабличнаяЧасть_Документа.КодИсполнителя
> := Шапка_Документа.КодИсполнителя1. select * from DOCUMENT_HEADER where DH_ID = :DH_ID
Не зная конкретики я тупо перекодировал Ваш алгоритм.
2. select * from DOCUMENT_LINES where DH_ID = :DH_ID
3. update DOCUMENT_LINES set MAKER_ID = :MAKER_ID
← →
Johnmen © (2004-05-14 11:46) [22]Вижу 3 варианта:
1. [0]
2. [4]
3. [12].1
Если 1. не проходит по синтаксису, то 2.
Если 2. не проходит по синтаксису, то 3.
Вобщем зависит от реализации SQL в аксесе...
← →
Danilka © (2004-05-14 11:56) [23][18] sniknik © (14.05.04 11:43)
Понятно.
Вобщем-то, когда я писал, что возможны 2 варианта, то имел ввиду то, что все вышеперечисленное в аццессе не работает. :)
← →
Вопрошающий (2004-05-14 11:59) [24]Ладно. Делать нечего. Напишу конвертер. С тупым перебором строк.
Только вот что делать, если у заказчика опять мысли сменятся? Опять писать конвертер? Неужели нет запроса, при помощи которого можно копировать поля обной таблицы в поля другой таблицы с условием?
← →
Курдль © (2004-05-14 12:13) [25]Да полно! Вот пример:
Syntax 1
UPDATE WHERE CURRENT OF cursor-name
{ USING DESCRIPTOR sqlda-name | FROM hostvar-list }
Syntax 2
UPDATE table-list
SET set-item, ...
WHERE CURRENT OF cursor-name
Только это, увы, не Ассеss. Может удастся переубедить заказчика сменить СУБД?
А с другой, стороны... если "клиеент платит" каждый раз, как только мысли у него сменятся...
← →
Вопрошающий (2004-05-14 12:21) [26]Хорошо хоть мысли (заказчика) меняются вовремя. В таблице всего 2000 заказов. Конвертировало "вручную" секунд 40. Прочитало-записало-прочитало-записало... Построчно, блин! А на 20000 заказов что? А если больше? А транзакция всех других пользователей блокирует. Блин...
← →
Jee © (2004-05-14 12:21) [27]
> Вопрошающий (14.05.04 11:59) [24]
Да не надо никаких конверторов.
Давай по порядку. Варианта два.
1. У тебя нет строк в табличной части. И тебе из нужно вставить.
2. Строки есть, но нет поля с кодом исполнителя. Тогда нужно его добавить и заполнить значением из шапки.
Так какой вариант?
← →
Johnmen © (2004-05-14 12:26) [28]>Вопрошающий
Поднять тебе веки ?
Или голову сориентировать ?
[4]
← →
Вопрошающий (2004-05-14 12:30) [29]Почти 2:
Поле с кодом исполнителя я в табличную часть уже добавил. Теперь надо этот код скопировать из соответствующей шапки во все подчиненные ей (шапке) строки.
Вот что, что (теперь) делается "руками" (догадайтесь, откуда руки ростут?):var
M: TADOQuery;
D: TADOQuery;
begin
Kernel.xDS.BeginTransaction;
try
try
M := TADOQuery.Create(nil);
D := TADOQuery.Create(nil);
// выполнение -------------------------------------
M.Connection := Kernel.xDS.Connection;
M.SQL.Add("SELECT * FROM Выполнение_Шапка");
M.Open;
D.Connection := Kernel.xDS.Connection;
D.SQL.Add("SELECT * FROM Выполнение_Таблица");
D.Open;
M.First;
while not M.Eof do
begin
ShowStatus("Выполнения: " + IntToStr(M.RecNo) + " из " + IntToStr(M.RecordCount));
D.Filtered := false;
D.Filter := "КодШапки=""" + M.FieldByName("Код").AsString + """";
D.Filtered := true;
D.First;
while not D.Eof do
begin
D.Edit;
D.FieldByName("КодВыполнившего").AsString := M.FieldByName("КодВыполнившего").AsString;
D.Post;
D.Next;
end;
M.Next;
end;
// анализы --------------------------------------
M.Connection := Kernel.xDS.Connection;
M.SQL.Add("SELECT * FROM Анализы_Шапка");
M.Open;
D.Connection := Kernel.xDS.Connection;
D.SQL.Add("SELECT * FROM Анализы_Таблица");
D.Open;
M.First;
while not M.Eof do
begin
ShowStatus("Анализы: " + IntToStr(M.RecNo) + " из " + IntToStr(M.RecordCount));
D.Filtered := false;
D.Filter := "КодШапки=""" + M.FieldByName("Код").AsString + """";
D.Filtered := true;
D.First;
while not D.Eof do
begin
D.Edit;
D.FieldByName("КодЛаборатории").AsString := M.FieldByName("КодЛаборатории").AsString;
D.FieldByName("КодБиоматериала").AsString := M.FieldByName("КодБиоматериала").AsString;
D.Post;
D.Next;
end;
M.Next;
end;
finally
if (M <> nil) then FreeAndNil(M);
if (D <> nil) then FreeAndNil(D);
end;
Kernel.xDS.CommitTransaction;
except
Kernel.xDS.RollbackTransaction;
end;
end;
← →
Вопрошающий (2004-05-14 12:32) [30]2 Johnmen © (14.05.04 12:26) [28]
ЭТО [4] не работает в Jet SQL
← →
Johnmen © (2004-05-14 12:34) [31]>Вопрошающий (14.05.04 12:32) [30]
>ЭТО [4] не работает в Jet SQL
Конкретно, вид запроса приведи.
И что значит "не работает" подробно.
← →
Вопрошающий (2004-05-14 12:44) [32]2 Johnmen © (14.05.04 12:34) [31]
Запрос:UPDATE ET
SET ЕТ.КодВыполнившего = EH.КодВыполнившего
FROM Выполнение_Таблица ET
INNER JOIN Выполнение_Шапка EH ON EH.Код=ET.КодШапки
Дополнительного условия, как в [4] (WHERE <добавляй свое условие, иначе у всех строк будет исполнитель из шапки>) нет, так как мне нужно, чтобы во всех подчиненных строках был исполнитель из шапки.
Сообщение: [19]
← →
sniknik © (2004-05-14 13:11) [33]под access, тоже что в [31]
UPDATE Выполнение_Таблица ET INNER JOIN Выполнение_Шапка EH ON EH.Код=ET.КодШапки
SET ЕТ.КодВыполнившего = EH.КодВыполнившего
← →
Вопрошающий (2004-05-14 13:35) [34]2 sniknik
Во! Супер! Признал! Спасибо! :) (радости нет границ...)
2 All
Спасибо!.............
2 Jee
Спасибо!.... :))
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.026 c