Postgresql и PHP:является ли currval эффективным способом извлечения идентификатора последней вставленной строки в многопользовательском приложении?
-
23-08-2019 - |
Вопрос
Мне интересно, эффективен ли способ, который я использую для извлечения идентификатора последней строки, вставленной в таблицу postgresql..
Очевидно, что это работает, но ссылка на значение последовательной последовательности currval может быть проблематичной, когда у меня много пользователей, добавляющих строки в одну и ту же таблицу одновременно.
Мой настоящий путь таков:
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
pg_close($pgConnection);
Ну, это всего лишь тестовый банкомат.Но в любом случае, я вижу 3 проблемы с этим способом:
- Ссылка на customer_id_seq, если два пользователя делают одно и то же в одно и то же время, может случиться так, что они оба получат один и тот же идентификатор таким образом...или нет?
- Я должен знать имя последовательности таблицы.Потому что pg_get_serial_sequence у меня не работает (я новичок в postgresql, вероятно, проблема с конфигурацией)
Есть какие-нибудь предложения / способы получше?
p.s:я не могу использовать PDO, потому что, похоже, немного не хватает точки сохранения транзакции;Я не буду использовать zend и, в конце концов, я предпочту использовать функции php pg_ * (возможно, я создам свои классы в конце)
Редактировать:
@SpliFF(тет удалил свой ответ):это сработало бы лучше?
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
pg_query("BEGIN");
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
//do somethings with the new customer id
pg_query("COMMIT");
pg_close($pgConnection);
Решение
Если вы используете более новую версию PostgreSQL (> 8.1), вам следует использовать ВОЗВРАЩАЕМОЕ предложение команды INSERT (и UPDATE).
OTOH если вы настаиваете на использовании одной из функций манипулирования последовательностью, пожалуйста, прочтите прекрасное руководство.Указатель:"Обратите внимание, что, поскольку это возвращает локальное значение сеанса, это дает предсказуемый ответ, выполняли ли другие сеансы nextval или нет с момента выполнения текущего сеанса".
Другие советы
Вставьте и проверьте curval (seq) внутри одной транзакции.Перед фиксацией транзакции вы увидите curval (seq) для вашего запроса и независимо от того, кто еще вставил его одновременно.
Не помню точно синтаксис - почитайте в руководстве (последний раз использовал pgsql около 3 лет назад), но в целом это выглядит так:
BEGIN TRANSACTION;
INSERT ...;
SELECT curval(seq);
COMMIT;
бывший.повторно введите значения журнала (desc, user_id) ('отбросьте ее мысли', 6), возвращающие идентификатор