Страница 2 из 2

Re: Добавление новых записей в 2 таблицы

Добавлено: 25 авг 2009, 15:48
Yurich
Duncon писал(а):В даном случае даже без блокировки внесёться конкретное значение исходя из очереди кто первый, провторов быть не может - смысл в транзакции нулевой...
Не вижу смысла комментировать этот [sarcasm] пост [/sarcasm]. Учите мат.часть...

Re: Добавление новых записей в 2 таблицы

Добавлено: 25 авг 2009, 15:51
Laba
natariga писал(а):понятно. спасибо!
я подумаю, как лучше.
Склоняюсь, к генерированию номера заказа, и запись его как поля в обе таблицы, а не auto_increment ID.

или все же values (LAST_INSERTED_ID(), 567, 2)..... :confused:

а не посоветуете, в каком из способов больше плюсов, а в каком минусов. :rolleyes:
В твоём случае auto_increment лучше. Есть его альтернатива

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 будет вводится юзером. :D

Re: Добавление новых записей в 2 таблицы

Добавлено: 25 авг 2009, 19:08
Yurich
Хвост ветки не относящийся к теме обсуждения был перенесен в форум "Флейм".

Re: Добавление новых записей в 2 таблицы

Добавлено: 25 авг 2009, 19:36
natariga
Сейчас поняла, что все гораздо интереснее!
Ладно заказы, там вариант генерирования номера, а потом внесение этого поля в обе таблицы нормален.

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

Я почитала про транзакции и выполнение их в php.

Это надо использовать тогда еще и команды SET AUTOCOMMIT=0; и SET AUTOCOMMIT=0; ?

Ок, попробую такой вариант. Не зря же такие средства предусмотрены. Если нет выйдет, будем изобретать велосипед.

Re: Добавление новых записей в 2 таблицы

Добавлено: 26 авг 2009, 10:17
Игорь Акопян
смысл в транзакции есть всегда, когда нужно обеспечить атомарность изменения

Re: Добавление новых записей в 2 таблицы

Добавлено: 26 авг 2009, 11:20
Yurich
natariga писал(а): Это надо использовать тогда еще и команды SET AUTOCOMMIT=0; и SET AUTOCOMMIT=0; ?
SET AUTOCOMMIT=0; выключает режим AUTOCOMMIT, в котором каждый отдельный запрос рассматривается как отдельная транзакция. Поэтому если ты хочешь использовать транзакции, состоящие из нескольких запросов, то надо выполнить SET AUTOCOMMIT=0; перед этим.

Re: Добавление новых записей в 2 таблицы

Добавлено: 26 авг 2009, 11:42
Duncon
Не буду переубеждать в глупости для данного случая, гении мысли.. auto_increment в 1 таблицу 2 таблица ведомая ей auto_increment не нужен id обычное поле. Внесли в 1 проверили внесенее без LAST_INSERTED_ID внесли во 2, всё.. (И даже если следом выполнить LAST_INSERTED_ID команда пройдёт следом, время примерно 0.000х и меньше, нужна ацкая нагрузка чтоб начались пролёты мимо..)


Автор сделай всё 1 запросом, зачем список покупок хранить в отдельной таблице?


Yurich в игнор уходит, за мат часть.. Хам.

Re: Добавление новых записей в 2 таблицы

Добавлено: 26 авг 2009, 12:49
Yurich
Duncon писал(а):Внесли в 1 проверили внесенее без LAST_INSERTED_ID внесли во 2, всё.. (И даже если следом выполнить LAST_INSERTED_ID команда пройдёт следом, время примерно 0.000х и меньше, нужна ацкая нагрузка чтоб начались пролёты мимо..)
LAST_INSERTED_ID() гарантирует получение последнего вставленного значения поля AUTO_INCREMENT именно в этой коннекции, так что даже если сервер очень нагружен "пролетов" не будет.
Duncon писал(а): Автор сделай всё 1 запросом, зачем список покупок хранить в отдельной таблице?
Просто автор следует правилам нормализации структуры БД и правильно делает. Я бы проигнорировал данный совет.
Duncon писал(а): Yurich в игнор уходит, за мат часть.. Хам.
Duncon, не зарывайся... Иди лучше сюда.

Re: Добавление новых записей в 2 таблицы

Добавлено: 26 авг 2009, 13:19
Laba
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 :D