Осложненное добавление новой записи в БД

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

java73
постоялец
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Осложненное добавление новой записи в БД

Сообщение java73 »

Привет, друзья.
Кто как решает проблему добавления новой записи в БД, если при этом возникает одновременная необходимость добавить отношения многие-ко-многим? Поясню. Есть запись допустим об объекте. Пока она новая, она не имеет уникального индекса, то есть сначала нужно запись сохранить, чтобы в таблице сопоставления ссылок отношений таблиц можно было добавлять записи уже с использованием нового индекса.
Я пока сделал так, как в 1С: основные поля таблицы заполняются, затем пользователь должен сохранить запись в БД, только после этого он снова открывает на редактирование и добавляет необходимые связи.
Я думал, с помощью каких-то объектных оберток можно это удобнее организовать. Сижу курю документацию к tiOPF, но чтобы перейти на эти рельсы мне нужно будет полностью весь проект перелопатить(((( одновременно изучаю C#, быть может там что лучше.
pupsik
энтузиаст
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13
Контактная информация:

Сообщение pupsik »

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

Обёртки, большей частью, пишутся для себя. Иногда "в общем". Но что то, что то один леший требует знакомства. И всё это из-за скрипта и 6 строк кода (которые плавно перетекут в процедуру и образуют 1 строку)? Плюс некоторые вещи можно решить на стороне сервера.

одновременно изучаю C#, быть может там что лучше
а смена коня повлияет на трамплин?
java73
постоялец
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Сообщение java73 »

pupsik писал(а):и..и? Ну а что не так?

хочется без промежуточного сохранения. Как вариант, конечно, наплодить дополнительных компонентов, которые не будут DB look up компонентами, а обычными, и из них потом уже копировать выбранные данные в саму БД.
pupsik писал(а):а смена коня повлияет на трамплин?

ДА, хотя бы из-за того, чтоб перестать сталкиваться с недопиленными для лазаруса компонентами (хотя бы html-читалка или встроенный webbrowser), кривыми поддержками печати на принтерах, и отсутствия приятного для кодинга экспорта в форматированные и редактируемые документы (хотя тут я уже решил все проблемы с помощью html шаблонов).

P.S.
Сразу после создания новой записи сохранить и уже сохраненную начать редактировать я не могу, т.к. встроил уже многочисленные проверки корректности введенных данных..
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

В нормальных базах обычно можно заранее знать (получить) ID будущей записи
java73
постоялец
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Сообщение java73 »

alexs писал(а):В нормальных базах обычно можно заранее знать (получить) ID будущей записи

А про mysql если поподробнее?

Добавлено спустя 9 минут 15 секунд:
При этом, если пользователь передумает запись сохранять, но добавит несколько связей, то их еще придется удалять ((( даже не знаю, может оставить как есть всё
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

java73 писал(а):А про mysql если поподробнее?

Код: Выделить всё

SELECT LAST_INSERT_ID();
//ВАЖНО!
//если есть вероятность работы с таблицей несколькими пользователями, то обязательно управлять транзакциями, иначе вы можете получить ID записи, добавленной кем-то другим, а не вами.

java73 писал(а):При этом, если пользователь передумает запись сохранять, но добавит несколько связей, то их еще придется удалять ((( даже не знаю, может оставить как есть всё

Транзакции?
pupsik
энтузиаст
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13
Контактная информация:

Сообщение pupsik »

LAST_INSERT_ID ну вернёт оно последнюю запись. И..и? Один пользователь узнал индекс, пока дошло до сохранения остальные десяток записей добавили. Что станет с индексом?

Сразу после создания новой записи сохранить и уже сохраненную начать редактировать я не могу..
а нет варианта использовать отдельную таблицу для идентификации записи, и от неё "отталкиваться"?

п.с.
Чёт всегда думал что смена наездника может повлиять на качество. Ну да ладно. Это не столь важно.
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

pupsik писал(а):LAST_INSERT_ID ну вернёт оно последнюю запись. И..и? Один пользователь узнал индекс, пока дошло до сохранения остальные десяток записей добавили. Что станет с индексом?

Я основываюсь на: https://dev.mysql.com/doc/refman/5.7/en ... ue-id.html
В частности:
For LAST_INSERT_ID(), the most recently generated ID is maintained in the server on a per-connection basis. It is not changed by another client. It is not even changed if you update another AUTO_INCREMENT column with a nonmagic value (that is, a value that is not NULL and not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns simultaneously from multiple clients is perfectly valid. Each client will receive the last inserted ID for the last statement that client executed.

А на чем основан ваш вывод?

То есть я предлагал стартовать транзакцию, вставить запись, получить ID и спокойно делать с ним, что душе угодно (например,создавать связанные записи в других таблицах). Если мы передумали сохранять, то просто откатить транзакцию. Как может измениться кем-то ID уже вставленной записи да еще и в чужой транзакции?

p.s. или я не правильно понял смысл абзаца?
pupsik
энтузиаст
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13
Контактная информация:

Сообщение pupsik »

Угу... Сморозил глупость.
Но не катит...
Т.е. вы предложили:
1. старт транзакции
2. сохранение записи
3. получения индекса
4. откат или сохранение.
Но..:
хочется без промежуточного сохранения.
а это п.2. Или я не верно понял?
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

java73 писал(а):А про mysql если поподробнее?

Вот это тот случай :-)
Как я понял - стоит задача сформировать несколько связанных между собой данных на стороне клиента в разные таблицы. Автоинкрементные колонки вам не подойдут.
Лучше всего ID объектов генерить с помощью механизма генераторов/последовательностей.
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

pupsik писал(а):а это п.2. Или я не верно понял?

Наверное криво написал...
п.2 читать как создание записи в таблице (в рамках открытой транзакции).
Это не "промежуточное сохранение". Это резервирование ID для последующего использования в связанных таблицах. В случае отката транзакции запись просто перестанет существовать.

alexs писал(а):Как я понял - стоит задача сформировать несколько связанных между собой данных на стороне клиента в разные таблицы. Автоинкрементные колонки вам не подойдут.

Просветите, пожалуйста, отчего так категорично? Ведь мы можем сделать поле с автоинкрементом первичным ключем.
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

wofs писал(а):Просветите, пожалуйста, отчего так категорично? Ведь мы можем сделать поле с автоинкрементом первичным ключем.

А как автоинкрементными полями получить гарантированно уникальные значения ключей без физического добавления записей?
Т.е. если параллельно идёт работа нескольких процессов по формированию пакетов данных? И чтобы этот пакет сохранить единым махом?

Простейший пример
Создаём карточку товара, которая содержит атрибуты
Т.е. есть основная запись и подчинённые -которые ссылаются на основную. Т.е. при создании новой карточки просим у генератора следующее значение
Потом (после редактирования) добавляем основную запись и подчинённые.
Ну или не добавляем.

Я понимаю что для этого примера автоинкрементные поля применять не сложно. Но значение ключ от основной записи увидим только после её добавления.
А в случае с генератором - значение PK увидим тогда, когда нам удобно.
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

alexs писал(а):Но значение ключ от основной записи увидим только после её добавления.

А в чем трагедия добавления записи и ее удаление по откату транзакции в случае нежелания сохранить?

p.s. Притом, что у ТС Mysql, а там целый велосипед с генераторами.
Mirage
энтузиаст
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

"Не имеет уникального индекса" означает "не имеет ID"? Почему бы не использовать общепринятую терминологию...
А в чем проблема-то? Ну создал сущность, создал доп. сущности.
При нажатии "Сохранить" все сущности отправились на сохранение: основная, те, что многие-ко-многим, теперь, имея ID всех записей, сохраняем их в таблицу связей.
В качестве бонуса, если что-то при сохранении упало, транзакция откатится и мусора в БД не останется.
ORM типа mORMot сделает это автоматически, но и вручную тоже не особо сложно.
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

wofs писал(а):А в чем трагедия добавления записи и ее удаление по откату транзакции в случае нежелания сохранить

При большой интенсивности операций - зачем лишняя нагрузка на сервер?
Ответить