Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
4-1083680287
Sir Kik
2004-05-04 18:18
2004.06.06
Скопировать Desktop - окно


6-1082063283
Dimedrol
2004-04-16 01:08
2004.06.06
Самый простенький Telnet клиент


1-1085303046
G_U_N
2004-05-23 13:04
2004.06.06
Видеокарта


3-1084544113
kalliopiy
2004-05-14 18:15
2004.06.06
Про BLOB ы


3-1084454956
Адмирал
2004-05-13 17:29
2004.06.06
Создание БД из приложения или выполнение скрипта





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский