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

Автор AlexSPB, 26 января 2015, 14:44

0 Пользователи и 1 гость просматривают эту тему.

AlexSPB

Имеется база описывающее некоторые события и их участников.
Соответственно, таблицы "события" и "участники".

Для удобства операторов хочется делать копии существующего события для последующей правки.

Хочется написать последовательность SQL операторов для выполнения задачи.
Для копирования в таблицу "События" введены метки S1 - то, что нужно скопировать и S2 - Полученная копия

Я предположил, что можно сделать следующую последовательность действий:

1. По метке S1 найти нужную строчку в таблице "События" И создать ее копию в таблице события пометив ее меткой в поле S2
2. По метке S1 найти строки в таблице "Участники" и сделать их копию, вставив значение связывающего поля IDevent  из значения  найденного в таблице "События" по метке S2

Запрос копирующий строку  в таблице "События" собрался довольно легко:
ЦитироватьINSERT INTO "События" ( "Дата", "Время", "Событие", "S2" )
SELECT "Дата", "Время", "Событие", "S1"
FROM "События"
WHERE ("S1"=True)

Как написать копирование строчек "Участники"?
может есть еще какой-либо способ решить задачку?

Базочка прилагается


rami

Трудно понять что вы хотите.
Цитата: AlexSPB от 26 января 2015, 12:44Для удобства операторов хочется делать копии существующего события для последующей правки.

Хочется написать последовательность SQL операторов для выполнения задачи.
Операторы — это люди или куски кода?
Цитата: AlexSPB от 26 января 2015, 12:44Запрос копирующий строку  в таблице "События" собрался довольно легко:
Запрос работает, но результат нулевой, если не отрицательный: дублирование строк — это зло.
Цитата: AlexSPB от 26 января 2015, 12:44Как написать копирование строчек "Участники"?
Втиснуть данные из "Участники" в "События" невозможно, но можно создать новую таблицу(или запрос) включающую данные из обеих таблиц.
Цитата: AlexSPB от 26 января 2015, 12:44может есть еще какой-либо способ решить задачку?
Если задачка — править данные сгруппированные по "Событиям", то лучше править данные в субформе "События".

AlexSPB

Цитата: rami от 26 января 2015, 23:23

Если задачка — править данные сгруппированные по "Событиям", то лучше править данные в субформе "События".

Лучше, давать ответ на поставленный вопрос. С общими рекомендациями у меня все в порядке, я их тоже могу давать.

AlexSPB

Двигаюсь вперед

Вот такой оператор создает выборку по тексту соответствующую тому, что нужно "затолкать" в таблицу "Участники":
SELECT IDevent, "ИмяУчастника", "РольУчастника","Начислено","Списано"FROM (SELECT "ИмяУчастника", "РольУчастника","Начислено","Списано" FROM "Участники"  WHERE "КодСобытия"=(SELECT IDevent FROM "События" WHERE  "S1"=TRUE)),(SELECT IDevent FROM "События" WHERE  "S2"=TRUE)

Однако результат запроса никак не удается записать в таблицу

Запросы вида:
INSERT INTO "Участники" SELECT "КодСобытия", "ИмяУчастника", "РольУчастника","Начислено","Списано" FROM ( SELECT IDevent , "ИмяУчастника", "РольУчастника","Начислено","Списано"FROM (SELECT "ИмяУчастника", "РольУчастника","Начислено","Списано" FROM "Участники"  WHERE "КодСобытия"=(SELECT IDevent FROM "События" WHERE  "S1"=TRUE)),(SELECT IDevent FROM "События" WHERE  "S2"=TRUE))

Дают ошибку :  Column not found: IDEVENT in statement .......

CREATE TABLE TMP (IDevent INT, "ИмяУчастника" VARCHAR (50), "РольУчастника" VARCHAR(50),"Начислено" INT,"Списано" INT);
INSERT INTO TMP SELECT * FROM ( SELECT IDevent , "ИмяУчастника", "РольУчастника","Начислено","Списано"FROM (SELECT "ИмяУчастника", "РольУчастника","Начислено","Списано" FROM "Участники"  WHERE "КодСобытия"=(SELECT IDevent FROM "События" WHERE  "S1"=TRUE)),(SELECT IDevent FROM "События" WHERE  "S2"=TRUE))

Та же ошибка


rami

Создаёте таблицу "TMP" (если ещё не создана):
Цитата: AlexSPB от 27 января 2015, 17:55CREATE TABLE TMP (IDevent INT, "ИмяУчастника" VARCHAR (50), "РольУчастника" VARCHAR(50),"Начислено" INT,"Списано" INT);
И заполняете её соответствующими данными из таблиц "События" и "Участники":
INSERT INTO "TMP" SELECT  "IDevent", "ИмяУчастника", "РольУчастника", "Начислено", "Списано"FROM "События" FULL JOIN "Участники" ON "IDevent" = "КодСобытия" AND "S1" = TRUE

AlexSPB


AlexSPB

Продолжу Вас мучить


Таблица создана
Почему-то поле IDEvent  при создании заголовка столбца преобразуется в UpperCase , возможно с этим связаны предыдущие проблемы. HSQLDB вообще чуствителен к Case?

Пытаюсь сапдейтить поле IDEVENT значением из таблицы "События"

UPDATE TMP SET IDEVENT=(SELECT IDevent FROM "События" WHERE  "S2"=TRUE)

Система сообщает, что команда выполнена успешно, но реально значение в таблице не меняется (было 11 и осталось 11, а должно стать 14)
SELECT отдельно выдает значение 14, как и должен.


Попробовал с явным преобразованием типа:

UPDATE TMP SET IDEVENT=CAST((SELECT IDevent FROM "События" WHERE  "S2"=TRUE) as INT)

Результат тот же "Выполнено успешно" но значение не изменяется.

Вариация на тему "А вдруг обязательно WHERE )

Пример практически идентичного синтаксиса http://www.cyberforum.ru/mysql/thread1104894.html приведен как правильный

UPDATE TMP SET IDEVENT=(SELECT IDevent FROM "События" WHERE  "S2"=TRUE) WHERE IDEVENT>0

Тоже не помогла

UPDATE TMP SET IDEVENT=(SELECT DISTINCT IDevent FROM "События" WHERE  "S2"=TRUE) WHERE IDEVENT>0

Тоже без результата.

UPDATE TMP SET IDEVENT=14

Работает.


На всякий случай прилагаю свежий экземпляр базы.


rami

Цитата: AlexSPB от 28 января 2015, 11:02Почему-то поле IDEvent  при создании заголовка столбца преобразуется в UpperCase
Поля и названия таблиц(запросов) надо заключать в кавычки: "ВотТак"
Цитата: AlexSPB от 28 января 2015, 11:02Система сообщает, что команда выполнена успешно, но реально значение в таблице не меняется (было 11 и осталось 11, а должно стать 14)
SELECT отдельно выдает значение 14, как и должен.
Причина таже.


AlexSPB

В результате получилось следующее решение:
Для копирования строки таблицы вместе со со связанными с ней строками в "дочерней таблице", в данном случае "События" и "Участники" событий оказалось удобно сделать следующее ввести в головную таблицу дополнительные поля:
-  метку строк подлежащих копированию S1
- метку скопированных строк S2   (без этого поля можно легко обойтись, но так проще писать запросы)
- поле для запоминания ключа "родительской" строки FromID

Тогда запросы для создания копии не требуют промежуточной таблицы, кроме того автоматически обрабатываются несколько помеченных строк:

INSERT INTO "События" ( "Дата", "Время", "Событие", "S2", "FromID" ) SELECT "Дата", "Время", "Событие", "S1", "IDevent" FROM "События" WHERE ("S1"=True)

INSERT INTO "Участники" ("КодСобытия", "ИмяУчастника", "Начислено", "Списано", "РольУчастника")SELECT  "События"."IDevent" AS "КодСобытия", "Участники"."ИмяУчастника", "Участники"."Начислено", "Участники"."Списано", "Участники"."РольУчастника" FROM "Участники", "События" WHERE "Участники"."КодСобытия" = "События"."FromID" AND "События"."S2" = TRUE

UPDATE "События"  SET "S1" = FALSE, "S2" = FALSE


Для "украшения банкета"  создана дополнительная таблица "ДатыДляКопирования" содержащая последовательность календарных дат и поле для пометки требуемых дат

Тогда запрос может создать копии требуемых событий и в требуемом списке дней календаря:

INSERT INTO "События" ("Дата", "Время", "Событие", "S2", "FromID" ) SELECT  "ДатаДляКопирования"."Дата", "Время", "Событие", "S1", "IDevent" FROM "События", "ДатаДляКопирования" WHERE ("S1"=True) AND ("S3"=True)

Естественно после копирования флажок выбранных дат можно тоже сбросить.
Запись оставленная в поле ссылки на родительскую запись (FromID) может быть использована для поиска и коррекции всех событий календарной серии.