dil: (Default)
dil ([personal profile] dil) wrote2005-10-13 12:21 pm

Учился писать программы на PL/SQL

Ну вылитый паскаль.

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

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

Или я просто не умею правильно готовить этих кошек?

[identity profile] alexkuklin.livejournal.com 2005-10-13 11:47 am (UTC)(link)
внутри одной транзакции get_curr_val(seqname) вернет то же значение, что и предыдущий вызов get_next_val(seqname) в той же транзакции.
имена функций - приблизительные.

[identity profile] dil.livejournal.com 2005-10-13 12:01 pm (UTC)(link)
они называются seqname.CURRVAL и seqname.NEXTVAL.
Только там нигде явно не написано, что CURRVAL поддерживается неизменным для сессии/транзакции.

[identity profile] alexkuklin.livejournal.com 2005-10-13 12:08 pm (UTC)(link)
а ты попытайся CURRVAL получить, не получив предварительно NEXTVAL в этой сессии/транзакции....

[identity profile] dil.livejournal.com 2005-10-13 12:11 pm (UTC)(link)
это ты к чему? я же не говорил, что nextval совсем не использовался, я интересуюсь, стабильным ли будет currval.

[identity profile] alexkuklin.livejournal.com 2005-10-13 12:16 pm (UTC)(link)
а тыт попробуй. и посмотри на то, что тебе скажут :)

[identity profile] dma.livejournal.com 2005-10-13 12:16 pm (UTC)(link)
Да, будет стабильным. В пределахъ транзакцыйы.
То есть если ты сказал
INSERT INTO mytable(ID, x) VALUES(seqname.NEXTVAL, 'a');
COMMIT
SELECT seqnane.CURRVAL FROM DUAL;

То тогда оно не сказать, чтобы определено. А вот пока коммит не сказал - CURRVAL абсолютно точно вернёт твоё значение, которое надо.

[identity profile] dil.livejournal.com 2005-10-13 12:37 pm (UTC)(link)
Ага. А если seqname.NEXTVAL сказал не я, а триггер, то я потом смогу вызвать SELECT seqnane.CURRVAL с правильным результатом?

[identity profile] dma.livejournal.com 2005-10-13 12:40 pm (UTC)(link)
Да.
Но вообще - не надо триггеры на это пользовать. Правильнее в инсерте сказать seqname.NEXTVAL

[identity profile] dil.livejournal.com 2005-10-13 12:57 pm (UTC)(link)
Не-а. Правильно, чтобы о целостности и непротиворечивости данных заботилась СУБД, а не приложение. Поэтому если автоинкремента нет, то пусть будет триггер.

[identity profile] dma.livejournal.com 2005-10-13 01:17 pm (UTC)(link)
Тогда тебе и currval не нужен. Делай insert, потом select его обратно, по каким-нибудь характерным признакам. Пусть база заботится.

[identity profile] dil.livejournal.com 2005-10-13 01:23 pm (UTC)(link)
Характерные признаки правильно называются "уникальный ключ". Если б он у меня был, известный клиенту, мне бы ID не понадобился :)

не умеете.

[identity profile] lslarry.livejournal.com 2005-10-13 11:50 am (UTC)(link)
в отличие от "грепа с sql-интерфейсом" нормальные субд это делают правильно.
в пг, например, это делается, через SELECT nextval(seq);
более того, результат селекта гарантированно правилен. т.е. каждая сессия из например цги получит правильное, уникальное число.
т.е. правильность транзакции обеспечивает сама субд. в отличие от.
хм. чот сумбурно как-то выходит. надеюсь донес мысль.

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-13 11:54 am (UTC)(link)
мысль понял, но вопрос не в уникальности select nextval, он и в оракле уникален. а в том, как клиент может узнать тот конкретный val, который был приделан в свежедобавленную запись

Re: не умеете.

[identity profile] titov.livejournal.com 2005-10-13 11:59 am (UTC)(link)
В PostgreSQL есть функция currval (http://www.postgresql.org/docs/7.4/static/functions-sequence.html), которая именно это и возвращает. В Oracle должно быть нечто аналогичное.

Re: не умеете.

[identity profile] lslarry.livejournal.com 2005-10-13 12:01 pm (UTC)(link)
а как он это узнает в мускуле?

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-13 12:02 pm (UTC)(link)
запоминает для текущей сессии

Re: не умеете.

[identity profile] lslarry.livejournal.com 2005-10-13 12:04 pm (UTC)(link)
ну так curval/nextval, как уже коллеги подметили.
только давайте определимся с терминами. как понимать "для текущей сессии"? сессии или транзакции?

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-13 12:14 pm (UTC)(link)
вопрос правильный, но в данном конкретном случае для меня не принципиальный. я пока не собираюсь в одной сессии параллельно вставлять несколько записей :)

Re: не умеете.

[identity profile] lslarry.livejournal.com 2005-10-13 12:02 pm (UTC)(link)
да, вот в чем тонкий момент. а нахера оно?

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-13 12:12 pm (UTC)(link)
как это нахера? это совершенно типичная ситуация - добавили в таблицу новую запись, а теперь по ее уникальному ID к ней надо привязать другие записи, добавляемые в другие таблицы.

[identity profile] anatolix.livejournal.com 2005-10-13 12:06 pm (UTC)(link)
AFAIR это пишется "insert into ... returning id into variable" и сработает просто со вставкой sequence и с триггером навешанным на таблицу.

Re: не умеете.

[identity profile] lslarry.livejournal.com 2005-10-13 12:55 pm (UTC)(link)
о. давай в самом деле тут продолжим.
т.е. тебе надо быть увереным в целостности твоих новых данных. ты из связываешь по какому-то ключу и этот ключ должен быть валиден. т.е. одна логическая атомарная операция (сделать новую заявку, конкретный пример у меня) при спуске вниз рожает три инсерта в разные таблицы.
так AFAIK все нормальные субд обеспечивают правильность и уникальность curval/nextval внутри транзакции (заметь, не сессии), до комита.

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-13 12:59 pm (UTC)(link)
угу. вот товарищи говорят, что и оракл в этом плане действует так же, но почему об этом явно не написано в документации?

Re: не умеете.

[identity profile] dma.livejournal.com 2005-10-13 01:18 pm (UTC)(link)
..потому что об этом написано в другой документации, я подозреваю. SQL standart, называется :)

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-13 01:26 pm (UTC)(link)
не-а. если б это было стандартом, оно было бы одинаково для всех стандартных СУБД, а оно разное.
Ссылка по теме: http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96590/adg03sch.htm#1263
Только она доступна залогиненным пользователям. Там описано, как пользоваться последовательностями, но насчет persistent'ности currval ничего не написано :(

Re: не умеете.

[identity profile] mastre.livejournal.com 2005-10-15 12:23 pm (UTC)(link)
во-первых у 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 вроде как сделан на основе Ады

Re: не умеете.

[identity profile] dil.livejournal.com 2005-10-17 10:01 am (UTC)(link)
Да, спасибо. Вот фразу про One user can never acquire the sequence number generated by another user я не углядел. Видимо, не там читал.
А на Аду это не похоже, она гораздо более сильно типизированная и пакетизированная. Это даже на модулу не тянет, это типичный паскаль с SQLными дополнениями :)