Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Проектирование БД Новый топик    Ответить
 Создание двух связанных записей  [new]
Tar_As
Member

Откуда:
Сообщений: 28
Долго искал где открыть тему, ну да ладно...

Собственно вопрос к знатокам.
Как классически грамотно решается стандартная задача.
Человек делает покупку. В покупке несколько товаров.
Есть таблица orders и таблица orders_items.
В таблице orders лежат заказы, а в таблицу orders_items нужно положить единицы каждого заказа, привязанные к id заказа таблицы orders.
Как правильно создать заказ и получить его уникальный id, сгенерированный автоинкрементом, чтобы потом с этим id ложить единицы в таблицу orders_items?
16 апр 19, 10:32    [21863360]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Serguei
Member

Откуда: Papua New Guinea
Сообщений: 681
Tar_As
Долго искал где открыть тему, ну да ладно...

Плохо искали. Есть раздел Программирование.
16 апр 19, 11:26    [21863438]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2108
Tar_As
Долго искал где открыть тему, ну да ладно...

Собственно вопрос к знатокам.
Как классически грамотно решается стандартная задача.
Человек делает покупку. В покупке несколько товаров.
Есть таблица orders и таблица orders_items.
В таблице orders лежат заказы, а в таблицу orders_items нужно положить единицы каждого заказа, привязанные к id заказа таблицы orders.
Как правильно создать заказ и получить его уникальный id, сгенерированный автоинкрементом, чтобы потом с этим id ложить единицы в таблицу orders_items?

Думаю, вам вот это надо использовать:
https://docs.oracle.com/cd/B28359_01/server.111/b28310/views002.htm#ADMIN11792
16 апр 19, 11:31    [21863450]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Tar_As
Member

Откуда:
Сообщений: 28
s_ustinov
Думаю, вам вот это надо использовать:
https://docs.oracle.com/cd/B28359_01/server.111/b28310/views002.htm#ADMIN11792


А можно, так сказать, в двух словах - чего он хочет (классика)...?
О чем там, о каком механизме?
16 апр 19, 18:36    [21864183]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 48154

Tar_As
Как правильно создать заказ и получить его уникальный id, сгенерированный автоинкрементом,
чтобы потом с этим id ложить единицы в таблицу orders_items?

а) returning
б) выкинуть автоинкремент

Posted via ActualForum NNTP Server 1.5

16 апр 19, 18:48    [21864192]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Tar_As
Member

Откуда:
Сообщений: 28
Dimitry Sibiryakov
а) returning
б) выкинуть автоинкремент


Это вроде как только для сохраненных функций? Или нет?

А если без функций, то ничего лучше в голову не лезет

START TRANSACTION;
INSERT INTO orders (a,b,c) VALUES(1,2,3);
SELECT MAX(id) as max_id FROM orders;
COMMIT;


т.е. без транзакции никак?

еще пишут про С API
https://dev.mysql.com/doc/refman/8.0/en/mysql-insert-id.html

Других решений нет?
А ведь задача с автоинкрементом не только частая, но я бы сказал постоянная. Такое впечатление, что разрабы как страусы, головы в песок воткнули и типа не видят и не знают о страданиях....
17 апр 19, 01:05    [21864338]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 7063
Tar_As,
for MySQL
CREATE TABLE a_table1 (
  id INT(11) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,
  name VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE INDEX id (id)
);

insert into a_table1(name) values('123');SELECT LAST_INSERT_ID();
17 апр 19, 01:44    [21864341]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2108
Люди, вы чего?
Sequences именно для таких задач и придуманы. Нафиг автоинкремент и потом читать последнее значение?

Получаем новое значение последовательности и присваиваем переменной. И потом делаем ДВА инсерта в ДВЕ таблицы в одной транзакции, используя эту переменную как значение ID. Всё.
И автоинкремент из таблицы убрать, разумеется.
17 апр 19, 11:18    [21864632]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
skyANA
Member

Откуда: Зеленоград
Сообщений: 26636
s_ustinov
Люди, вы чего?
Sequences именно для таких задач и придуманы. Нафиг автоинкремент и потом читать последнее значение?

Так ведь речь про MySQL, там Sequence через AUTO_INCREMENT
17 апр 19, 13:38    [21864923]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2108
skyANA
s_ustinov
Люди, вы чего?
Sequences именно для таких задач и придуманы. Нафиг автоинкремент и потом читать последнее значение?

Так ведь речь про MySQL, там Sequence через AUTO_INCREMENT

Блин, я почему-то подумал, что оракл.
17 апр 19, 14:05    [21864990]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Cane Cat Fisher
Member

Откуда:
Сообщений: 1800
skyANA
s_ustinov
Люди, вы чего?
Sequences именно для таких задач и придуманы. Нафиг автоинкремент и потом читать последнее значение?

Так ведь речь про MySQL, там Sequence через AUTO_INCREMENT


Так там вроде сто лет назад было что-то вроде LAST_INSERT_ID() для этого случая?
17 апр 19, 15:37    [21865162]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Tar_As
Member

Откуда:
Сообщений: 28
insert into a_table1(name) values('123');SELECT LAST_INSERT_ID();


этот вариант есть и существует, но не влезет ли между ними другой insert от другого вопрошающего без транзакции?
17 апр 19, 17:44    [21865445]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Cane Cat Fisher
Member

Откуда:
Сообщений: 1800
Tar_As
insert into a_table1(name) values('123');SELECT LAST_INSERT_ID();


этот вариант есть и существует, но не влезет ли между ними другой insert от другого вопрошающего без транзакции?


Нет, не влезет. Ибо сказано:

MySQL 8.0 Reference Manual
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions.


Правда, надо учитывать:

Is MySql's LAST_INSERT_ID() function guaranteed to be correct?

A couple caveats I'd like to point out when using LAST_INSERT_ID:

I know you mentioned single-row inserts. But when doing multiple-row inserts, LAST_INSERT_ID() will return the value of the first row inserted (not the last).

If the insert failed, LAST_INSERT_ID() would be undefined. The same is true for automatic rollbacks of transactions (due to errors).

If you do an insert in a transaction that succeeds, and you still issue a ROLLBACK, LAST_INSERT_ID() would be left as it was prior to the rollback.

There are a couple caveats when using AUTO_INCREMENT and LAST_INSERT_ID in statement-based replication. The first being when used in a trigger or function. The second being the less-common scenario where your auto_increment column is part of a composite primary key and is not the first column in the key.

17 апр 19, 18:38    [21865497]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 7063
s_ustinov
skyANA
пропущено...

Так ведь речь про MySQL, там Sequence через AUTO_INCREMENT

Блин, я почему-то подумал, что оракл.


Даже если бы там был 300 раз Оракел этоже полный ппц по дизайну. В оракле поле id никак не защищено, т.к. это не автоинкремент и программеры могут залить туда любой мусор. Откуда программеры знают, какую сиквенс дергать, ведь они никак не привязаны к таблицам? Поэтому во вменяемом дизайне никtо даже права на сиквенсы не выдаёт. Второе, на поле id почти всегда есть триггер, в котором и обязано генерироваться id, и какое он там сгенерит значение - большой вопрос. insert ... returning into ... наше все. За приведенный вами метод заполнения id нужно бить линейкой по рукам, уж извините.
17 апр 19, 18:57    [21865508]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 7063
Cane Cat Fisher
Tar_As
insert into a_table1(name) values('123');SELECT LAST_INSERT_ID();


этот вариант есть и существует, но не влезет ли между ними другой insert от другого вопрошающего без транзакции?


Нет, не влезет. Ибо сказано:

MySQL 8.0 Reference Manual
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions.


Правда, надо учитывать:

Is MySql's LAST_INSERT_ID() function guaranteed to be correct?
A couple caveats I'd like to point out when using LAST_INSERT_ID:

I know you mentioned single-row inserts. But when doing multiple-row inserts, LAST_INSERT_ID() will return the value of the first row inserted (not the last).

If the insert failed, LAST_INSERT_ID() would be undefined. The same is true for automatic rollbacks of transactions (due to errors).

If you do an insert in a transaction that succeeds, and you still issue a ROLLBACK, LAST_INSERT_ID() would be left as it was prior to the rollback.

There are a couple caveats when using AUTO_INCREMENT and LAST_INSERT_ID in statement-based replication. The first being when used in a trigger or function. The second being the less-common scenario where your auto_increment column is part of a composite primary key and is not the first column in the key.



Ну много строчные инсерты как-то не интересны. А вот при исползовании пула соединений могут быть варианты. Поэтому нужно делать, как я написал, inset и select в одной команде, и не отпускать соединение в пул до получения id.
17 апр 19, 19:05    [21865511]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Дмитрий Мух
Member

Откуда: Зеленоград
Сообщений: 2063
Cane Cat Fisher
skyANA
пропущено...

Так ведь речь про MySQL, там Sequence через AUTO_INCREMENT


Так там вроде сто лет назад было что-то вроде LAST_INSERT_ID() для этого случая?

Так-то за 4 сообщения до вашего пример с AUTO_INCREMENT и LAST_INSERT_ID().
Зачем на сто лет назад смотреть? :)
17 апр 19, 22:18    [21865604]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2108
Relic Hunter
s_ustinov
пропущено...

Блин, я почему-то подумал, что оракл.


Даже если бы там был 300 раз Оракел этоже полный ппц по дизайну. В оракле поле id никак не защищено, т.к. это не автоинкремент и программеры могут залить туда любой мусор. Откуда программеры знают, какую сиквенс дергать, ведь они никак не привязаны к таблицам? Поэтому во вменяемом дизайне никtо даже права на сиквенсы не выдаёт. Второе, на поле id почти всегда есть триггер, в котором и обязано генерироваться id, и какое он там сгенерит значение - большой вопрос. insert ... returning into ... наше все. За приведенный вами метод заполнения id нужно бить линейкой по рукам, уж извините.

То есть разработчики СУБД, специально создавшие сиквенсы именно для таких целей - идиоты, а вы крутой спец, знающий про правильный дизайн. :))
А уж про программистов, не знающих "какую сиквенс дергать, ведь они никак не привязаны к таблицам" - это вообще зашибись аргумент.
18 апр 19, 00:54    [21865641]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 7063
s_ustinov
Relic Hunter
пропущено...


Даже если бы там был 300 раз Оракел этоже полный ппц по дизайну. В оракле поле id никак не защищено, т.к. это не автоинкремент и программеры могут залить туда любой мусор. Откуда программеры знают, какую сиквенс дергать, ведь они никак не привязаны к таблицам? Поэтому во вменяемом дизайне никtо даже права на сиквенсы не выдаёт. Второе, на поле id почти всегда есть триггер, в котором и обязано генерироваться id, и какое он там сгенерит значение - большой вопрос. insert ... returning into ... наше все. За приведенный вами метод заполнения id нужно бить линейкой по рукам, уж извините.

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


А где я говорил про разработчиков СУБД, например? Я говорил, что конечным пользователям на сиквенсы прав выдавать нельзя. Накосячат с именами в коде так, что админа отправят на принудительное психиатрическое лечение. Сиквенсы нужно прятать в триггеры. Это многолетняя практика, мэн. Но вам можно делать и по-своему, как говорится "приятного хождения по граблям". )) Я в своей роте такого не допускал.
18 апр 19, 01:13    [21865643]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
Ivan Durak
Member

Откуда: Minsk!!!
Сообщений: 3618
а потом с целью оптимизации трегеры заменяются на

Create table table1
(
COLUMN_ID number default on null seq_table1,nextval not null
...
)
и получаем красивый автоинкремент как в лучших домах Ms & My сиквелов.
18 апр 19, 08:50    [21865720]     Ответить | Цитировать Сообщить модератору
 Re: Создание двух связанных записей  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2108
Relic Hunter
s_ustinov
пропущено...

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


А где я говорил про разработчиков СУБД, например? Я говорил, что конечным пользователям на сиквенсы прав выдавать нельзя. Накосячат с именами в коде так, что админа отправят на принудительное психиатрическое лечение. Сиквенсы нужно прятать в триггеры. Это многолетняя практика, мэн. Но вам можно делать и по-своему, как говорится "приятного хождения по граблям". )) Я в своей роте такого не допускал.



Ну и как к задаче, описанной ТС (запись документа с заголовком и строками) автоинкремент или триггер подойдет лучше, чем обычная последовательность? Тем, что в транзакцию нужно лишний селект добавлять? :))
18 апр 19, 09:25    [21865740]     Ответить | Цитировать Сообщить модератору
Все форумы / Проектирование БД Ответить