Комментарии 36
столило ли ради этого писать пост?
+4
Что вернет этот запрос?
INSERT INTO test (name) VALUES ('My Name 1'), ('My Name 2'), ('My Name 3') RETURNING id;
+1
postgres=# INSERT INTO test (name) VALUES ('My Name 1'), ('My Name 2'), ('My Name 3') RETURNING id;
id
— 4
5
6
(3 rows)
Хабрапарсер немного накозявил, но должно быть понятно
+3
Странно… Я в мануале (www.postgresql.org/docs/8.3/interactive/plpgsql-statements.html) прочитал, что:
>> For INSERT/UPDATE/DELETE with RETURNING, PL/pgSQL reports an error for more than one returned row, even when STRICT is not specified. This is because there is no option such as ORDER BY with which to determine which affected row should be returned.
или я не так что-то понял…
>> For INSERT/UPDATE/DELETE with RETURNING, PL/pgSQL reports an error for more than one returned row, even when STRICT is not specified. This is because there is no option such as ORDER BY with which to determine which affected row should be returned.
или я не так что-то понял…
0
я использую версию PostgreSQL 8.3.8 и подобная запись у меня работает
0
Работает, можно напимер удаляя по какому то условию узнать id или name удалённых позиций для выдачи пользователю, или записи в лог.
+1
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted
www.postgresql.org/docs/8.2/static/sql-insert.html
www.postgresql.org/docs/8.2/static/sql-insert.html
+1
У меня работает только в таком виде:
Без fetchone() выдает ошибку
new_id = db.execute("INSERT INTO users (username, hash) VALUES (u_name, hashh) RETURNING id",).fetchone()
session["user_id"] = new_id
Без fetchone() выдает ошибку
0
Еще вопрос: в RETURNING id, я так понимаю, что id — это поле в таблице. Как насчет «RETURNING id, name»?
+2
>таким ништячком для меня стал элемент синтаксиса INSERT
RTFM ))
RTFM ))
+10
Я начал работать с pl/sql совсем недавно и каждый день узнаю такие «ништячки» от старших товарищей. И это приносить удовольствие, когда вместо 3-5 строк получаеш одну
+3
Достаточно было просто прочитать мануал по Постгре. Там об этом все сказано.
+2
Сорри за оффтоп, но можно ли подобную штуку на MySQL провернуть, может кто подскажет.
+2
вообще то получение последнего id при условии что поле имеет тип serial:
select currval('t_table_id_seq');
select currval('t_table_id_seq');
-2
Да, но ведь это отдельный запрос к БД!
0
Не совсем корректно. Как уже сказали это еще один запрос — это первое. Из этого же минуса вытекает то, что между инсертом и кьюрвалом может проскочить еще один инсерт. Раз уж вы хотите выбирать так, то наверное лучше получить некствал, и использовать его для инсерта.
+1
Вы не правы. Он не может проскочить, так как она возвращает значение в рамках одной сессии.
www.postgresql.org/docs/7.4/interactive/functions-sequence.html
www.postgresql.org/docs/7.4/interactive/functions-sequence.html
+1
К теме постгре, перед вставкой какого либо значения необходимо проверить его на существование в БД.
Пользуюсь таким шаблоном: Создаю процедуру.
CREATE OR REPLACE FUNCTION «public».«get_server» (varchar, integer) RETURNS integer AS
$body$
DECLARE serv_count integer;
newid bigint;
BEGIN
SELECT servers.id_server INTO newid FROM servers WHERE domain = $1;
IF newid IS NULL THEN
INSERT INTO servers (domain, ip) VALUES ($1, $2);
ELSE
return newid;
END IF;
SELECT lastval() INTO newid;
RETURN newid;
END;
$body$
LANGUAGE 'plpgsql'
теперь легко просто скриптом сделать так
SELECT get_server('habra.ru', 999)
И, если данных в БД нет — они вставяться, а если есть просто произойдет возврат ID записи.
Это удобно, не загромождает исполняемый код.
Пользуюсь таким шаблоном: Создаю процедуру.
CREATE OR REPLACE FUNCTION «public».«get_server» (varchar, integer) RETURNS integer AS
$body$
DECLARE serv_count integer;
newid bigint;
BEGIN
SELECT servers.id_server INTO newid FROM servers WHERE domain = $1;
IF newid IS NULL THEN
INSERT INTO servers (domain, ip) VALUES ($1, $2);
ELSE
return newid;
END IF;
SELECT lastval() INTO newid;
RETURN newid;
END;
$body$
LANGUAGE 'plpgsql'
теперь легко просто скриптом сделать так
SELECT get_server('habra.ru', 999)
И, если данных в БД нет — они вставяться, а если есть просто произойдет возврат ID записи.
Это удобно, не загромождает исполняемый код.
+1
а как-то так не проще?
INSERT INTO servers (domain, ip) SELECT 'habra.ru', 999 WHERE not exist(SELECT 1 FROM servers WHERE domain = 'habra.ru') LIMIT 1;
INSERT INTO servers (domain, ip) SELECT 'habra.ru', 999 WHERE not exist(SELECT 1 FROM servers WHERE domain = 'habra.ru') LIMIT 1;
+1
В данном случае между select и insert остаётся промежуток, в котором теоретически может возникнуть новая запись из другого потока. Так что для чистоты придётся использовать блокировку или искать другой путь.
0
Еще можно использовать функцию nextval(), которая возвращает следующее значение счетчика, и потом вставлять это значение в своем запросе.
-1
каждый вызов nextval() прибавляет единичку к сиквенсу вне зависимости от того сделали мы что-то с полученым id или нет.
0
хочу дополнить, что тем, кто пользуется Hibernate — это не к чему. Хотя тут можно и поспорить. Дело в том, что в Hibernate есть метод save, который вернёт вам id добавленной записи.
например так:
public Integer addComment(Comment comment) {
return (Integer) getHibernateTemplate().save(comment);
}
В данном случае используется Spring'овая обёртка.
например так:
public Integer addComment(Comment comment) {
return (Integer) getHibernateTemplate().save(comment);
}
В данном случае используется Spring'овая обёртка.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Получение id добавленной записи в PostgeSQL