LINUX.ORG.RU

PostgreSQL получить следующий номер


0

0

PostgreSQL 8.1.9, Apache/mod_perl/Apache::DBI
У таблицы два поля:
- id(serial) - автоприращение;
- name(character varying(65).

Добавляю запись: insert into ttt (name) values ($name).

Как узнать номер id добавленной записи,
если name может повторяться и работают много пользователей?

Нужно передать id в скрипт AJAX2 для создания записи без запроса
к базе.


Лучше так: "Нужно передать id в скрипт AJAX2 для создания записи без ПОВТОРНОГО запроса к базе".

WinLin
() автор топика

> получить следующий номер

> узнать номер id добавленной записи

непонятно, что нужно ? получить следующее значение последовательности или текущее значение в текущей сессии которое было использовано при вставке ?

Eshkin_kot ★★
()

Наиболее очевидное решение - не использовать serial. Вместо этого самому доставать nextval из последовательности и явно помещать его в таблицу в качестве id.

anonymous
()
Ответ на: комментарий от anonymous

> Наиболее очевидное решение - не использовать serial. Вместо этого самому доставать nextval из последовательности и явно помещать его в таблицу в качестве id.

совершенно не очевидное решение. у вас сотни/тысячи распределенных по сети клиентов, которые друг с другом никак не связаны и каждый что-то пишет в базу. как будете на стороне клиента назначать unique record id?

// wbr

klalafuda ★☆☆
()

1) Накопал man DBI
$rv = $dbh->last_insert_id($catalog, $schema, $table, $field);
Пока разбираюсь...

2) Возможно можно запросить следующее значение, последовательность
увеличится и потом добавлять по известному id. Или последовательность
не увеличивается без добавления?

WinLin
() автор топика

Классический способ: - получить nextval - явно вставить так делают даже в Oracle.

В PostgreSQL 8.2 появилось расширение синтаксиса, можно делать селект из инсерта.

anonymous
()
Ответ на: комментарий от anonymous

Как говорите в Oracle:
Insert, а дальше как получить id добавленной записи?

Сейчас Pg 8.1.9.
Один раз уже была у меня проблема с получением id,
тогда просто заново искал по name и обновлял всю страницу :)

WinLin
() автор топика
Ответ на: комментарий от klalafuda

> как будете на стороне клиента назначать unique record id?

Насколько я понял, автору вопроса этого совершенно не требуется.

Ему нужно на сервере узнать id записи, которую на сервере же только что вставили. Вот я и предлагаю отказаться от serial и доставать значение из последовательности самому.

anonymous
()
Ответ на: комментарий от anonymous

id - должен быть уникальным в таблице.
Общаемся так: Javascript -> Apache -> mod_perl -> PgSQL.
Javascript должны вернуть заполненный id для изменения страницы.

WinLin
() автор топика
Ответ на: комментарий от anonymous

Запрашиваем id:
$id = $dbh->selectrow_array("SELECT nextval('internat_id_seq')");
Далее добавляем запись с уже известным id.

Работает :)

WinLin
() автор топика
Ответ на: комментарий от WinLin

Всего двенадцать постов и все все поняли ;)

anonymous
()
Ответ на: комментарий от WinLin

> Запрашиваем id:
> $id = $dbh->selectrow_array("SELECT nextval('internat_id_seq')");
> Далее добавляем запись с уже известным id.

> Работает :)

может быть я конечно что-то не до конца понимаю - даже скорее всего это так - но как в этом случае разруливаются race conditions? в случае, когда два или более клиентов одновременно пытаются добавить счётчик с AUTOINCREMENT? ведь после того, как вы получили по SELECT internal_id_seq другой клиент может аналогично обратиться к базе, внести в неё свои изменения и на момент, когда вы будете добавлять свою "уникальную" запись внутренний счётчик уже поменяется и его значение будет скорее всего присвоено другой записи.

или выборка следующего ID и добавление новой записи - это атомарная операция? но если это так, как оно реализовано? блокировкой таблицы? не приведи господи всей базы? и как это сказывается на производительности базы?

в общем, как работает сия кухня?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Нет никакого autoincrement. Есть sequence. Не нужно никакой атомарности. Природа sequence такова, что он все время возвращает новое значение.

Естественно, id будут идти не по порядку и с возможными дырками.

anonymous
()
Ответ на: комментарий от anonymous

> Нет никакого autoincrement. Есть sequence. Не нужно никакой атомарности. Природа sequence такова, что он все время возвращает новое значение.

mmm.. дык вот ты какой - северный олень. ну в принципе то-же вариант.

> Естественно, id будут идти не по порядку и с возможными дырками.

ну строгой равномерности по-идее и не требуется.

ps: я никогда особо не вникал в стандарт на SQL so вопрос чайника: sequence - это стандартная фишка SQL или от базе к базе всё сильно меняется? ну допустим в джентльменском наборе MySQL/PgSQL/MSSQL/Oracle.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Меняется...

MySQL - sequences нету, можно сделать в таблице auto_increment column чтоб туда значения подставлялись

Oracle - sequences есть, но синтаксис вроде отличается от PostgreSQL.

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

Ага. Все верно. В MSSQL нет AFAIK.

Мне почему-то кажется, что в новых стандартах SQL есть какие-то слова про sequence, но могу ошибаться.

К тому же, стандарт SQL - один из самых нестандартных стандартов ;)

anonymous
()
Ответ на: комментарий от anonymous

Если имя таблицы table1, а имя поля типа serial - id, то получить id вставленной записи можно как: currval(''table1_id_seq'')

посмотри это в базе эти сиквенсы, они там есть - все станет ясно. полюбознательней будь )

ft
()
Ответ на: комментарий от ft

> Если имя таблицы table1, а имя поля типа serial - id, то получить id вставленной записи можно как: currval(''table1_id_seq'')

тогда уж лучше имхо так: currval(pg_get_serial_sequence('table1', 'id'))

Eshkin_kot ★★
()
Ответ на: комментарий от ft

В плане любознательности да, конечно. А в плане использования нужно понимать, что currval вернет id записи, вставленной неизвестно какой сессией.

anonymous
()
Ответ на: комментарий от anonymous

> В плане любознательности да, конечно. А в плане использования нужно
> понимать, что currval вернет id записи, вставленной неизвестно какой
> сессией

Это Ваше предположение или прочитали где то ? :) currval вернёт значение
последовательности полученное последним nextval В ТЕКУЩЕЙ сессии и к
настоящему текущему значению последовательности currval отношения не имеет :)

postgres=# select currval('tmp123');
ERROR:  currval (текущее значение) последовательности "tmp123" ещё не определено в этой сессии

обрати внимание на слова "в этой сессии" =)

Eshkin_kot ★★
()
Ответ на: комментарий от Eshkin_kot

> currval вернёт значение последовательности полученное последним nextval В ТЕКУЩЕЙ сессии

Понял. Спасибо.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.