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

SQL во всех проявлениях - от ANSI-92 до TSQL.

Модераторы: Yurich, Absurd

natariga
Сообщения: 4
Зарегистрирован: 25 авг 2009, 09:24

Добрый день!
Есть 2 таблицы:
1 - ORDER:
id_order;
date;
status.
2 - ORDER_ITEMS:
id_order;
id_product;
amount.

Как правильно сделать запрос (или запросы), чтоб реализовать следующее:
1. Добавляем запись в таблицу ORDER (id_order уникальный ключ - номер заказа)
2. Добавляем записИ в таблицу ORDER_ITEMS, где id_order - номер заказа присвоенный при добавлении записи в первой таблмце.

Понятно, что я знаю, как добавить запись в одну таблицу. Но тут что-то никак не соображу.
Спасибо заранее за ответ!
С уважением
Наталья
Аватара пользователя
Duncon
Сообщения: 2085
Зарегистрирован: 10 окт 2004, 14:11
Откуда: Питер
Контактная информация:

1 Я делаю генерацию по дате + рандом, далее в цикле проверяю существует ли номер заказа и перегенерирую его если нужно..
2 Ещё один запрос сделай.
[syntax=Delphi] [/syntax]
natariga
Сообщения: 4
Зарегистрирован: 25 авг 2009, 09:24

Спасибо. Я немножко уточню свой вопрос.
Есть ли в MySQL возможность, при выполнении запроса INSERT INTO получить назад значение auto_increment ID (в моем случае это ID_ORDER)?
Yurich
Сообщения: 107
Зарегистрирован: 23 фев 2004, 19:07

natariga писал(а): Есть ли в MySQL возможность, при выполнении запроса INSERT INTO получить назад значение auto_increment ID (в моем случае это ID_ORDER)?
При выполнении нет, после выполнения это можно сделать с помощью функции LAST_INSERT_ID().
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
natariga писал(а):Добрый день!
Есть 2 таблицы:
1 - ORDER:
id_order;
date;
status.
2 - ORDER_ITEMS:
id_order;
id_product;
amount.

Как правильно сделать запрос (или запросы), чтоб реализовать следующее:
1. Добавляем запись в таблицу ORDER (id_order уникальный ключ - номер заказа)
2. Добавляем записИ в таблицу ORDER_ITEMS, где id_order - номер заказа присвоенный при добавлении записи в первой таблмце.

Понятно, что я знаю, как добавить запись в одну таблицу. Но тут что-то никак не соображу.
Спасибо заранее за ответ!
С уважением
Наталья
Примерный план такой:

BEGIN TRANSACTION
insert into ORDER (date, status) values (now(), 1);
insert into ORDER_ITEMS (id_order,id_product,amount) values (LAST_INSERTED_ID(), 567, 2);
COMMIT
Аватара пользователя
Duncon
Сообщения: 2085
Зарегистрирован: 10 окт 2004, 14:11
Откуда: Питер
Контактная информация:

LAST_INSERT_ID() - нужно учитывать что функция возращает последний индексный элемент, если поле номера не является индексом - бесполезно..

Транзакции тут вообще не нужны..
Генерируешь номер делаешь 2 запроса.. всё.
[syntax=Delphi] [/syntax]
Yurich
Сообщения: 107
Зарегистрирован: 23 фев 2004, 19:07

Duncon писал(а):LAST_INSERT_ID() - нужно учитывать что функция возращает последний индексный элемент, если поле номера не является индексом - бесполезно..
Хорошая поправка, только не совсем правильная. :) LAST_INSERTED_ID() возвращает первое автоматически cгенерированное значение, которое было присвоено полю AUTO_INCREMENT в результате выполнения самого последнего запроса. AUTO_INCREMENT поле должно быть включено в индекс.
Duncon писал(а):Транзакции тут вообще не нужны..
Генерируешь номер делаешь 2 запроса.. всё.
Если допустима ситуация, когда была вставлена запись в таблицу ORDER, и не вставлена соответствующая запись в таблицу ORDER_ITEMS, то можно не использовать транзакции.
natariga
Сообщения: 4
Зарегистрирован: 25 авг 2009, 09:24

понятно. спасибо!
я подумаю, как лучше.
Склоняюсь, к генерированию номера заказа, и запись его как поля в обе таблицы, а не auto_increment ID.

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

а не посоветуете, в каком из способов больше плюсов, а в каком минусов. :rolleyes:
Аватара пользователя
Duncon
Сообщения: 2085
Зарегистрирован: 10 окт 2004, 14:11
Откуда: Питер
Контактная информация:

Суть транзакций в выполнении большого количества запросов, при этом блокируется таблица, для 2 запросов это бессмысленно больше времени уйдёт на блокировку...
[syntax=Delphi] [/syntax]
Yurich
Сообщения: 107
Зарегистрирован: 23 фев 2004, 19:07

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

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

а не посоветуете, в каком из способов больше плюсов, а в каком минусов. :rolleyes:
Лучше использовать auto_increment, это избавит тебя от проблем генерации ключа и проверки на его уникальность. Эта задача не супер сложная, но надо сделать все очень аккуратно, особенно в случае когда записи добавляет не один клиент, а несколько одновременно. Собственно auto_increment избавляет тебя от всего этого и собственно именно для таких случаев оно и сделано. Зачем изобретать велосипед? :) Другое дело, когда поле id_order не является auto_increment и структуру таблицы ORDER нельзя менять, в этом случае надо генерировать уникальное значение самому.
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
Duncon писал(а):Суть транзакций в выполнении большого количества запросов, при этом блокируется таблица, для 2 запросов это бессмысленно больше времени уйдёт на блокировку...
Ты совершенно не прав! Суть транзакции заключается в выполнении нескольких запросов как одного целого. То есть либо все insert/update данной транзакции будут выполнены, либо ни одно из них. То что ты описываешь называется блокировками. Они бывают разных типов (блокировка всей таблицы, блокировка блока данных, блокировка одной записи, блокировка страницы индекса и т.д.). Они используются как при внесении изменений в БД (не важно каким образом: одним запросом или в транзакции), так и чтении данных из БД. Какая именно блокировка будет использоваться зависит от многого. Программист может контролировать этот процесс установкой различных уровней изоляции (TRANSACTION ISOLATION LEVEL).
Аватара пользователя
Duncon
Сообщения: 2085
Зарегистрирован: 10 окт 2004, 14:11
Откуда: Питер
Контактная информация:

В даном случае даже без блокировки внесёться конкретное значение исходя из очереди кто первый, провторов быть не может - смысл в транзакции нулевой...
[syntax=Delphi] [/syntax]
Ответить