Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.06.06;
Скачать: CL | DM;

Вниз

Копирование данных   Найти похожие ветки 

 
Вопрошающий   (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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.027 c
4-1083428532
Vin_Ghost
2004-05-01 20:22
2004.06.06
Создание полнокранного приложения


1-1085631998
Вованчик
2004-05-27 08:26
2004.06.06
загрузка dll


14-1085319910
QHread
2004-05-23 17:45
2004.06.06
Где поток (TThread)


14-1083753233
Думкин
2004-05-05 14:33
2004.06.06
Новосибирск - месяц май


14-1084925158
Serzh ml
2004-05-19 04:05
2004.06.06
(win XP) vs (win NT+9x)