November 2019

S M T W T F S
      12
34 5 678 9
10111213141516
17181920212223
24252627282930

Style Credit

Expand Cut Tags

No cut tags
Thursday, October 13th, 2005 12:21 pm
Ну вылитый паскаль.

Кроме того много думал о менталитете авторов Оракла. Он у них получился весь такой логичный-логичный. Но в некоторых местах всё-таки очень ненатуральный..

Вот, например, там нет автоинкрементируемых полей. Вместо них есть sequence, из которых при необходимости можно извлечь очередное значение и засунуть его в нужное поле. При добавлении записи это можно сделать автоматически, например, триггером.
Но вот как клиент может узнать, какое именно значение попало в свежедобавленную запись? Посмотреть в sequence можно, но если в это время кто-нибудь еще вставлял запись в ту же таблицу, то sequence мог уже поменяться.
[livejournal.com profile] cybernatic_cat предложил весь процесс вставки завернуть в хранимую функцию, которая будет сама извлекать очередное значение из sequence, и потом его возвращать.
Да, это будет надёжно работать, но.. как-то оно совсем ненатурально по сравнению с простым и логичным MySQLным SELECT LAST_INSERT_ID() или MSSQLным SELECT @@IDENTITY.

Или я просто не умею правильно готовить этих кошек?
Thursday, October 13th, 2005 11:47 am (UTC)
внутри одной транзакции get_curr_val(seqname) вернет то же значение, что и предыдущий вызов get_next_val(seqname) в той же транзакции.
имена функций - приблизительные.
Thursday, October 13th, 2005 12:01 pm (UTC)
они называются seqname.CURRVAL и seqname.NEXTVAL.
Только там нигде явно не написано, что CURRVAL поддерживается неизменным для сессии/транзакции.

Thursday, October 13th, 2005 12:08 pm (UTC)
а ты попытайся CURRVAL получить, не получив предварительно NEXTVAL в этой сессии/транзакции....
Thursday, October 13th, 2005 12:11 pm (UTC)
это ты к чему? я же не говорил, что nextval совсем не использовался, я интересуюсь, стабильным ли будет currval.
Thursday, October 13th, 2005 12:16 pm (UTC)
а тыт попробуй. и посмотри на то, что тебе скажут :)
Thursday, October 13th, 2005 12:16 pm (UTC)
Да, будет стабильным. В пределахъ транзакцыйы.
То есть если ты сказал
INSERT INTO mytable(ID, x) VALUES(seqname.NEXTVAL, 'a');
COMMIT
SELECT seqnane.CURRVAL FROM DUAL;

То тогда оно не сказать, чтобы определено. А вот пока коммит не сказал - CURRVAL абсолютно точно вернёт твоё значение, которое надо.
Thursday, October 13th, 2005 12:37 pm (UTC)
Ага. А если seqname.NEXTVAL сказал не я, а триггер, то я потом смогу вызвать SELECT seqnane.CURRVAL с правильным результатом?
Thursday, October 13th, 2005 12:40 pm (UTC)
Да.
Но вообще - не надо триггеры на это пользовать. Правильнее в инсерте сказать seqname.NEXTVAL
Thursday, October 13th, 2005 12:57 pm (UTC)
Не-а. Правильно, чтобы о целостности и непротиворечивости данных заботилась СУБД, а не приложение. Поэтому если автоинкремента нет, то пусть будет триггер.
Thursday, October 13th, 2005 01:17 pm (UTC)
Тогда тебе и currval не нужен. Делай insert, потом select его обратно, по каким-нибудь характерным признакам. Пусть база заботится.
Thursday, October 13th, 2005 01:23 pm (UTC)
Характерные признаки правильно называются "уникальный ключ". Если б он у меня был, известный клиенту, мне бы ID не понадобился :)
Thursday, October 13th, 2005 11:50 am (UTC)
в отличие от "грепа с sql-интерфейсом" нормальные субд это делают правильно.
в пг, например, это делается, через SELECT nextval(seq);
более того, результат селекта гарантированно правилен. т.е. каждая сессия из например цги получит правильное, уникальное число.
т.е. правильность транзакции обеспечивает сама субд. в отличие от.
хм. чот сумбурно как-то выходит. надеюсь донес мысль.
Thursday, October 13th, 2005 11:54 am (UTC)
мысль понял, но вопрос не в уникальности select nextval, он и в оракле уникален. а в том, как клиент может узнать тот конкретный val, который был приделан в свежедобавленную запись
Thursday, October 13th, 2005 11:59 am (UTC)
В PostgreSQL есть функция currval (http://www.postgresql.org/docs/7.4/static/functions-sequence.html), которая именно это и возвращает. В Oracle должно быть нечто аналогичное.
Thursday, October 13th, 2005 12:01 pm (UTC)
а как он это узнает в мускуле?
Thursday, October 13th, 2005 12:02 pm (UTC)
запоминает для текущей сессии
Thursday, October 13th, 2005 12:04 pm (UTC)
ну так curval/nextval, как уже коллеги подметили.
только давайте определимся с терминами. как понимать "для текущей сессии"? сессии или транзакции?
Thursday, October 13th, 2005 12:14 pm (UTC)
вопрос правильный, но в данном конкретном случае для меня не принципиальный. я пока не собираюсь в одной сессии параллельно вставлять несколько записей :)
Thursday, October 13th, 2005 12:02 pm (UTC)
да, вот в чем тонкий момент. а нахера оно?
Thursday, October 13th, 2005 12:12 pm (UTC)
как это нахера? это совершенно типичная ситуация - добавили в таблицу новую запись, а теперь по ее уникальному ID к ней надо привязать другие записи, добавляемые в другие таблицы.
Thursday, October 13th, 2005 12:06 pm (UTC)
AFAIR это пишется "insert into ... returning id into variable" и сработает просто со вставкой sequence и с триггером навешанным на таблицу.
Thursday, October 13th, 2005 12:55 pm (UTC)
о. давай в самом деле тут продолжим.
т.е. тебе надо быть увереным в целостности твоих новых данных. ты из связываешь по какому-то ключу и этот ключ должен быть валиден. т.е. одна логическая атомарная операция (сделать новую заявку, конкретный пример у меня) при спуске вниз рожает три инсерта в разные таблицы.
так AFAIK все нормальные субд обеспечивают правильность и уникальность curval/nextval внутри транзакции (заметь, не сессии), до комита.
Thursday, October 13th, 2005 12:59 pm (UTC)
угу. вот товарищи говорят, что и оракл в этом плане действует так же, но почему об этом явно не написано в документации?
Thursday, October 13th, 2005 01:18 pm (UTC)
..потому что об этом написано в другой документации, я подозреваю. SQL standart, называется :)
Thursday, October 13th, 2005 01:26 pm (UTC)
не-а. если б это было стандартом, оно было бы одинаково для всех стандартных СУБД, а оно разное.
Ссылка по теме: http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96590/adg03sch.htm#1263
Только она доступна залогиненным пользователям. Там описано, как пользоваться последовательностями, но насчет persistent'ности currval ничего не написано :(
Saturday, October 15th, 2005 12:23 pm (UTC)
во-первых у insert в оракле есть дополнение returning, как уже было сказано выше
во-вторых, доки оракла идут с сервером и доступны на OTN (регистрация бесплатная), и там сказано вот что:

Purpose

Use the CREATE SEQUENCE statement to create a sequence, which is a database object from which multiple users may generate unique integers. You can use sequences to automatically generate primary key values.

When a sequence number is generated, the sequence is incremented, independent of the transaction committing or rolling back. If two users concurrently increment the same sequence, then the sequence numbers each user acquires may have gaps, because sequence numbers are being generated by the other user. One user can never acquire the sequence number generated by another user. Once a sequence value is generated by one user, that user can continue to access that value regardless of whether the sequence is incremented by another user.

Sequence numbers are generated independently of tables, so the same sequence can be used for one or for multiple tables. It is possible that individual sequence numbers will appear to be skipped, because they were generated and used in a transaction that ultimately rolled back. Additionally, a single user may not realize that other users are drawing from the same sequence.

то есть, сиквенсы (возвращаемое значение currval) разделены по сессиям.

а PL/SQL вроде как сделан на основе Ады
Monday, October 17th, 2005 10:01 am (UTC)
Да, спасибо. Вот фразу про One user can never acquire the sequence number generated by another user я не углядел. Видимо, не там читал.
А на Аду это не похоже, она гораздо более сильно типизированная и пакетизированная. Это даже на модулу не тянет, это типичный паскаль с SQLными дополнениями :)