Не вижу смысла комментировать этот [sarcasm] пост [/sarcasm]. Учите мат.часть...Duncon писал(а):В даном случае даже без блокировки внесёться конкретное значение исходя из очереди кто первый, провторов быть не может - смысл в транзакции нулевой...
Добавление новых записей в 2 таблицы
В твоём случае auto_increment лучше. Есть его альтернативаnatariga писал(а):понятно. спасибо!
я подумаю, как лучше.
Склоняюсь, к генерированию номера заказа, и запись его как поля в обе таблицы, а не auto_increment ID.
или все же values (LAST_INSERTED_ID(), 567, 2).....
а не посоветуете, в каком из способов больше плюсов, а в каком минусов.![]()
select max( id_order)+1 into :x from order;
insert into order (id_order,...) values( :x, ...);
insert into order_item( ..., id_order, ...) value( ..., :x, ...)
...
В случае с last_inserted и max()+1 транзакцию объявлять обязательно (правила хорошего тона)
Идеальный случай когда id_order будет вводится юзером.

Хвост ветки не относящийся к теме обсуждения был перенесен в форум "Флейм".
Сейчас поняла, что все гораздо интереснее!
Ладно заказы, там вариант генерирования номера, а потом внесение этого поля в обе таблицы нормален.
А сейчас увидела, что и при регистрации нового пользователя мне в сессию надо также сохранять присвоенный ему ID, чтоб он зарегистрировавшись сразу авторизировался, а не вводил потом еще раз логин и пароль.
Я почитала про транзакции и выполнение их в php.
Это надо использовать тогда еще и команды SET AUTOCOMMIT=0; и SET AUTOCOMMIT=0; ?
Ок, попробую такой вариант. Не зря же такие средства предусмотрены. Если нет выйдет, будем изобретать велосипед.
Ладно заказы, там вариант генерирования номера, а потом внесение этого поля в обе таблицы нормален.
А сейчас увидела, что и при регистрации нового пользователя мне в сессию надо также сохранять присвоенный ему ID, чтоб он зарегистрировавшись сразу авторизировался, а не вводил потом еще раз логин и пароль.
Я почитала про транзакции и выполнение их в php.
Это надо использовать тогда еще и команды SET AUTOCOMMIT=0; и SET AUTOCOMMIT=0; ?
Ок, попробую такой вариант. Не зря же такие средства предусмотрены. Если нет выйдет, будем изобретать велосипед.
- Игорь Акопян
- Сообщения: 1440
- Зарегистрирован: 13 окт 2004, 17:11
- Откуда: СПБ
- Контактная информация:
смысл в транзакции есть всегда, когда нужно обеспечить атомарность изменения

SET AUTOCOMMIT=0; выключает режим AUTOCOMMIT, в котором каждый отдельный запрос рассматривается как отдельная транзакция. Поэтому если ты хочешь использовать транзакции, состоящие из нескольких запросов, то надо выполнить SET AUTOCOMMIT=0; перед этим.natariga писал(а): Это надо использовать тогда еще и команды SET AUTOCOMMIT=0; и SET AUTOCOMMIT=0; ?
Не буду переубеждать в глупости для данного случая, гении мысли.. auto_increment в 1 таблицу 2 таблица ведомая ей auto_increment не нужен id обычное поле. Внесли в 1 проверили внесенее без LAST_INSERTED_ID внесли во 2, всё.. (И даже если следом выполнить LAST_INSERTED_ID команда пройдёт следом, время примерно 0.000х и меньше, нужна ацкая нагрузка чтоб начались пролёты мимо..)
Автор сделай всё 1 запросом, зачем список покупок хранить в отдельной таблице?
Yurich в игнор уходит, за мат часть.. Хам.
Автор сделай всё 1 запросом, зачем список покупок хранить в отдельной таблице?
Yurich в игнор уходит, за мат часть.. Хам.
[syntax=Delphi] [/syntax]
LAST_INSERTED_ID() гарантирует получение последнего вставленного значения поля AUTO_INCREMENT именно в этой коннекции, так что даже если сервер очень нагружен "пролетов" не будет.Duncon писал(а):Внесли в 1 проверили внесенее без LAST_INSERTED_ID внесли во 2, всё.. (И даже если следом выполнить LAST_INSERTED_ID команда пройдёт следом, время примерно 0.000х и меньше, нужна ацкая нагрузка чтоб начались пролёты мимо..)
Просто автор следует правилам нормализации структуры БД и правильно делает. Я бы проигнорировал данный совет.Duncon писал(а): Автор сделай всё 1 запросом, зачем список покупок хранить в отдельной таблице?
Duncon, не зарывайся... Иди лучше сюда.Duncon писал(а): Yurich в игнор уходит, за мат часть.. Хам.
Этот вариант скорее всего ТС вполне подойдёт. Но может и нет.Duncon писал(а):Не буду переубеждать в глупости для данного случая, гении мысли.. auto_increment в 1 таблицу 2 таблица ведомая ей auto_increment не нужен id обычное поле. Внесли в 1 проверили внесенее без LAST_INSERTED_ID внесли во 2, всё.. (И даже если следом выполнить LAST_INSERTED_ID команда пройдёт следом, время примерно 0.000х и меньше, нужна ацкая нагрузка чтоб начались пролёты мимо..)
И прежде чем рассуждать нужна транзакция в данном случае или нет, то нужно знать для чего они вообще нужны.
Позволю быть многословным.
1) самое очевидное, чтобы обеспечить физическую запись данных. Проще говоря, чтобы команда insert прошла и никому не помешала

2) чтобы после внесения изменений можно было бы вернуться в исходное состояние. Порой откатить транзакцию нужно не только когда произошла ошибка, но и при успешном завершении.
3) чтобы обеспечить целостность данных. Типовой случай связка мастер-детайл.
4) чтобы была возможность подумать над "А вообще нужно ли вносить _такие_ изменения в таблицы?"

Всё это очень доступно описано вот в этом учебном курсе для начинающих ораклоидов. Щелкайте здесь -
Основы работы с базой данных Oracle
Подписывайтесь и читайте, ДУМАЙТЕ, примеряйте к своей практике. Очень полезно даже не для ораклоидов. Кстати, там и про первичные ключи расписано доходчиво.
Возвращаясь к случаю ТС, решение без транзакции будет хорошо работать если нет проблем с целостностью данных в связке мастер-детайл (см п.3).
И дело даже не в том, что связь есть по id_order. Это не та связь, которой надо остерегаться. Ведь нам ничто не мешает вставить запись в order, получить order_id, запомнить его где-то в недрах клиентского кода, ПОДУМАТЬ ЧАСИКА ДВА и добавить запись в order_item.
Дело в других зависимостях. Например, если бы в order хранилась сумма всех записей из order_item для id_order, то тогда всё было бы совершенно по другому. Нужно обязательно использовать транзакцию. Для успешной записи нужно гарантировать изменения сразу в двух таблицах. Скорее всего, этого у ТС нет.
И ещё один ньюанс в этом случае. Если ТС решит использовать автоинкрементную колонку и значение будет получать LAST_INSERTED_ID, то по хорошему транзакцию надо использовать (см п.1) Между вызовом insert и LAST_INSERTED_ID всё таки проходит время. Не час и даже не секунда. Но вызываются они из клиентского кода и никто не будет гарантировать, что он выполняется "без тормозов". Конечно, на это можно забить. Хотя...
...практика написания хорошего (читабельного, надежного и сопровождаемого) кода заключается в оформлении _всех_ изменений в формате _явных_ транзакций с _обязательной_ проверкой кода завершения _всех_ sql-команд (даже ROLLBACK, не говоря уже про COMMIT). В коде проверки у вас почти всегда есть возможность выполнить п.2

А явное оформление транзакций позволяет сопровождающему программисту спустя годы выполнить п.4
