powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вытянуть из insert значение вставленно по умолчанию
35 сообщений из 35, показаны все 2 страниц
вытянуть из insert значение вставленно по умолчанию
    #33647069
Алексей Ключников
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.
Есть таблица
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
create table obj (
id serial,
name varchar,
comment varchar,
class int,
PRIMARY KEY(id)
);
Где поле id имеет тип serial, т.е. по умолчанию принимает уникальное значение (обычно +1 от последнего)

Есть ХП
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create or replace function cls_copy(int,varchar,varchar) returns boolean as
$$
declare
cls_id int;
begin
insert into obj (name,comment,class) values ($ 2 ,$ 3 , 1 );
cls_id=?????
return true;
end;
$$
language plpgsql;

Как в этой ХП получить в cls_id значение id только что вставленной
в таблицу obj строки.
При условии что поля name,comment,class могут быть не уникальными.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33647094
ChameLe0n
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
 p_id:= nextval('public.id_seq'::text) // твоя последовательность для id obj
 insert into obj (id,name,comment,class) values (p_id,$ 2 ,$ 3 , 1 );
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33647101
Алексей Ключников
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Большое спасибо!
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33647344
.Guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
можно и "постфактум": сделать INSERT обычнам образом, т.е., без указания значения SERIAL-поля, а затем получить его текущее значение, вызвав функцию currval (по аналогии с nextval).
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33653266
victor_kr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если не ошибаюсь, то "постфактум" лучше не делать. :-) Может так получиться, что между операцией вставки и операцией получения текущего значения последовательности это текущее значение изменится. Т.к. последовательность одна для всех транзакций.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33653444
raul_83
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно делать и curval - если вы просто напишете curval без вставки - вам выдаст ошибку - следовательно curval действует в пределах транзации и только после insert - если уровень изоляции транзакций по умолчанию
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33655180
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
curval выдает последнее выделенное значение последовательности в текущей транзакции и абсолютно безопасен.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33655215
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_Falconcurval выдает последнее выделенное значение последовательности в текущей транзакции и абсолютно безопасен.не совсем точно
currval
Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Notice that because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.
а "сессия" и "транзакция" - вещи разные.
например вполне работает в одном окне pgAdmina:
Код: plaintext
1.
2.
3.
4.
5.
6.
Begin;
SELECT nextval('t1_id_seq'::regclass);
rollback ; 

BEGIN;
SELECT currval('t1_id_seq'::regclass);
ROLLBACK;
причем счетчик наваривается независимо от ROLLBACK - ибо счетчики не транзакционны.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33656698
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сори, облажался.
Но и смысла запрашивать curval, если случился rollback не вижу (думаю и не бывает так Ж-)
По-этому curval так и остается безопасным (если прямыми руками использовать).
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33657037
Фотография Кувалдин Роман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не остается. Скажем, пока ты выполнял операцию вставки, джедай в соседней транзакции вызовет nextval. И currval вернет тебе не твое значение, а приросшее.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33657090
.Guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кувалдин РоманНе остается. Скажем, пока ты выполнял операцию вставки, джедай в соседней транзакции вызовет nextval. И currval вернет тебе не твое значение, а приросшее.
Currval выдаст most recently obtained by nextval for this sequence in the current session . А не в "чужой" сессии. Не се па? Или я глубоко заблудился?
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33657329
Фотография Кувалдин Роман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не, это я облажался :-)
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33657574
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не, ну я могу придумать, как кажецца можно навернуть логику с каррвал. Скажем - завести глобальный уникальный индификатор уровня базы на счетчике, а по вставке в какую-то табличку вызывать триггер "до вставки", порождающий вставку в другую табличку неких служебных объектов (т.е. в свою очередь наваривающих этот же глобальный уникальный индификатор.
дальше вроде все понятно но это довольно искусственный пример.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #33659132
Алексей Ключников
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
логику с некствал, я так понял тоже можно навернуть.
Так что особой разницы между курвал и некствал нет.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
вытянуть из insert значение вставленно по умолчанию
    #34723736
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
аналогичная проблема, но с тем, что есть UNIQUE поля. После INSERT-а (если он не удачен, т.е. UNIQUE VIOLATION по какому-то полю) - как получить id (serial) записи, которая вызвала VIOLATION? SELECT не предлагать. Не верю, что нельзя получить все поля записи, на которой возник UNIQUE VIOLATION без SELECT-а.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34723848
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victor_krЕсли не ошибаюсь, то "постфактум" лучше не делать. :-) Может так получиться, что между операцией вставки и операцией получения текущего значения последовательности это текущее значение изменится. Т.к. последовательность одна для всех транзакций.

аналогично и nextval <здесь кто-то может влезть> insert
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34723879
drunk2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Winnipuhаналогично и nextval <здесь кто-то может влезть> insertЕсли получили номер с помощью nextval никто уже не влезет и не заберет.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34723975
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Начиная с версии 8.2 появилась возможность сделать это без nextval() или currval() с помощью "INSERT ... RETURNING ...".
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34724582
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LeXa NalBatНачиная с версии 8.2 появилась возможность сделать это без nextval() или currval() с помощью "INSERT ... RETURNING ...".

это хорошо работает только если не возникло UNIQUE VIOLATION. При вставке с возникновением UNIQUE VIOLATION значение не возвращается.
Неужели без select-а никак?
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34724713
Dan Black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Robert Ayrapetyanэто хорошо работает только если не возникло UNIQUE VIOLATION. При вставке с возникновением UNIQUE VIOLATION значение не возвращается.
Неужели без select-а никак?

Поясните свой вопрос примером. Мне, например, сложно понять, что именно Вы хотите получить и в каком виде.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34724749
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется таблица
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34724762
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется таблица:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CREATE TABLE families
(
  "FamilyID" integer NOT NULL DEFAULT nextval('"families_FamilyID_seq"'::regclass),
  "FamilyName" character varying( 100 ) NOT NULL,
  CONSTRAINT pk_families PRIMARY KEY ("FamilyID")
) 
WITHOUT OIDS;
ALTER TABLE families OWNER TO postgres;


-- Index: "Index_3"

-- DROP INDEX "Index_3";

CREATE UNIQUE INDEX "Index_3"
  ON families
  USING btree
  ("FamilyName");

Выполняется INSERT INTO families(FamilyName) VALUES (blablalba);

Необходимо: получить FamilyID в той записи, которая была вставлена, либо сгенерировала DUPLICATE VIOLATION.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34724799
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Robert Ayrapetyan Необходимо: получить FamilyID в той записи, которая была вставлена, либо сгенерировала DUPLICATE VIOLATION.очевидно, при ошиппке никакого FamilyID сгенерено не будет. ПО части наращивания счетчика, если произошло, спрашиваейте curval.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34726424
Nick Gazaloff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
INSERT ... RETURNING ... не годится?
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34726506
Thamerlan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nick GazaloffINSERT ... RETURNING ... не годится?
Чукча не читатель ....
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34726563
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторINSERT ... RETURNING ... не годится?

блин, ну сколько раз можно одно и то же! Повторяю в последний раз:

INSERT... RETURNING возвращает значение только когда вставка прошла удачно.
При неудачной (UNIQUE VIOLATION) возвращается NULL

Ок, я понял что без select-а после insert-а не обойтись (что есть очень херово).
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34726600
Thamerlan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Robert Ayrapetyan
Ок, я понял что без select-а после insert-а не обойтись (что есть очень херово).

Простите, но зачем вам ID после UNIQUE VIOLATION? Что вы с ним будете делать апосля?
Опять же, если очень надо, то 4321 верно сказал: юзайте CURVAL...
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34726772
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Robert AyrapetyanОк, я понял что без select-а после insert-а не обойтись (что есть очень херово).Не понятно, какой именно select вы имеете в виду, поясните плиз на вашем примере с таблицей families.

И еще вопрос: командой инсерт вы пытаетесь вставить одну строку или несколько?
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34726906
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторПростите, но зачем вам ID после UNIQUE VIOLATION? Что вы с ним будете делать апосля?
Опять же, если очень надо, то 4321 верно сказал: юзайте CURVAL...

Существуют таблицы и ключи:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
CREATE TABLE families
(
  "FamilyID" integer NOT NULL DEFAULT nextval('"families_FamilyID_seq"'::regclass),
  "FamilyValue" character varying( 100 ) NOT NULL,
  CONSTRAINT pk_families PRIMARY KEY ("FamilyID")
) 


CREATE TABLE names
(
  "NameID" integer NOT NULL DEFAULT nextval('"names_NameID_seq"'::regclass),
  "NameValue" character varying( 100 ) NOT NULL,
  CONSTRAINT pk_names PRIMARY KEY ("NameID")
) 

CREATE TABLE fn
(
  "FnID" integer NOT NULL DEFAULT nextval('"fn_fnID_seq"'::regclass),
  "FamilyID" integer,
  "NameID" integer
)

CREATE UNIQUE INDEX "Index_1"
  ON families
  USING btree
  ("FamilyValue");

CREATE UNIQUE INDEX "Index_2"
  ON names
  USING btree
  ("NameValue");

CONSTRAINT fk_fn_ref_families FOREIGN KEY ("FamilyID")
      REFERENCES families ("FamilyID")

CONSTRAINT fk_fn_ref_names FOREIGN KEY ("NameID")
      REFERENCES families ("NameID")


Есть функция по добавлению новых записей в fn, которая в настоящий момент выглядит так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
CREATE OR REPLACE FUNCTION "add_fn" (          _Name      varchar,
                                                          _Family      varchar,
)
RETURNS INTEGER AS $$
DECLARE

     Family_ID integer; 
     Name_ID integer; 
    flag integer;
     
BEGIN

     flag =  1 ;
   
     BEGIN
     INSERT INTO families
         ("FamilyValue") VALUES(_Family);
     EXCEPTION WHEN UNIQUE_VIOLATION THEN
              Family_ID = (SELECT "FamilyID" FROM families WHERE "FamilyValue" = _Family);
          flag =  0 ;
       END;
          
     IF flag THEN
          Family_ID = (SELECT currval('"families_FamilyID_seq"'));
     END IF;
     flag =  1 ;

     BEGIN
     INSERT INTO names ("NameValue") VALUES(_Name);
     EXCEPTION WHEN UNIQUE_VIOLATION THEN
              Name_ID = (SELECT "NameID" FROM names WHERE "NameValue" = _Name);
          flag =  0 ;
       END;

     IF flag THEN
          Name_ID = (SELECT currval('"names_NameID_seq"'));
     END IF;
     flag =  1 ;

     BEGIN
     INSERT INTO fn ("FamilyID","NameID") 
          VALUES(Family_ID,Name_ID);

 ....

Необходимость исопльзовать идиотскую конструкцию с flag из-за того, что:
1. Невозможно использовать FOUND (в любом случае он равен 1)
2. Невозможно использовать GET DIAGNOSTICS integer_var = ROW_COUNT; т.к. ROW_COUNT также равен нулю.

Но вопрос в другом (но был бы рад избавиться от flag).

Как получить xxx_ID в Exception БЕЗ select-а??? Currval тут поможет (и используется в процедуре выше) только если вставка прошла удачно.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34727090
Thamerlan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Скажите, а что это:
flag = 1;
???
Странная булева алгебра ...
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34727096
Thamerlan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или pl/sql стал понимать сишные присвоения?
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34727216
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как насчет избавиьтся от flag и currval?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
     BEGIN
     INSERT INTO families ("FamilyValue") VALUES(_Family);
     END;
     Family_ID = (SELECT "FamilyID" FROM families WHERE "FamilyValue" = _Family);

     BEGIN
     INSERT INTO names ("NameValue") VALUES(_Name);
     END;
     Name_ID = (SELECT "NameID" FROM names WHERE "NameValue" = _Name);

     BEGIN
     INSERT INTO fn ("FamilyID","NameID") 
          VALUES(Family_ID,Name_ID);

Видимо вам подошло бы "UPSERT RETURNING". Смотри UPSERT в TODO .
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34727666
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторИли pl/sql стал понимать сишные присвоения?

а когда он их не понимал?

авторКак насчет избавиьтся от flag и currval?

понимаете, база все время растет, и делать SELECT для каждого INSERT-а из набирающей каждый день миллионы записей базы не хочется. Использование в данном случае currval ускоряет процесс в несколько раз (для тех случаев, когда нет DUPLICATE VIOLATION). Проблема в том, что я не знаю (и пока никто не подсказал) как вытащить нужное мне поле при DUPLICATE VIOLATION (без select-а есесно). Я 100% уверен что есть решение, просто никто почему-то не сталкивался (хотя на мой взгляд все просто забили и использовали неэффективный SELECT, такая проблема встречается в каждой второй БД).

авторВидимо вам подошло бы "UPSERT RETURNING". Смотри UPSERT в TODO.
Незнаю, это все решение другой проблемы. Моя задача - достать поля из записи, которая сгенерячила DUPLICATE VIILATION при INSERT-е без SELECT-а. Сомневаюсь что UPSERT будет такое возвращать.
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34728082
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не примите за наезд, но действительно SELECT _сразу после_ DUPLICATE VIOLATION не эффективен ? Тесты это доказывают ? Я просто подумал что после DUPLICATE VIOLATION возможно запись уже в кеше и возможно SELECT для неё отработает мгновенно ? хотя может я ошибаюсь...

--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
вытянуть из insert значение вставленно по умолчанию
    #34728615
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Robert Ayrapetyanделать SELECT для каждого INSERT-а из набирающей каждый день миллионы записей базы не хочется.При селекте выполняется выборка одной записи по уникальному индексу? И это работает медленно? Сколько миллисекунд?

Robert AyrapetyanИспользование в данном случае currval ускоряет процесс в несколько разПопробуйте реализовать алгоритм "SELECT || INSERT RETURNING", в этом случае не в каждом случае будет выполняться INSERT, что возможно даст гораздо более существенное ускорение, чем "currval vs select".

Robert AyrapetyanПроблема в том, что я не знаю (и пока никто не подсказал) как вытащить нужное мне поле при DUPLICATE VIOLATION (без select-а есесно). Я 100% уверен что есть решениеА может и нет решения. Не сделали разработчики постгреса соответствующего интерфейса, нет и решения.

Robert Ayrapetyan авторВидимо вам подошло бы "UPSERT RETURNING". Смотри UPSERT в TODO.Незнаю, это все решение другой проблемы. Моя задача - достать поля из записи, которая сгенерячила DUPLICATE VIILATION при INSERT-е без SELECT-а. Сомневаюсь что UPSERT будет такое возвращать.Вроде UPSERT RETURNING вам бы подошел: "MERGE INTO families AS a USING families AS b ON b.FamilyValue=$FamilyValue WHEN NOT MATCHED THEN INSERT (a.FamilyValue) VALUES ($FamilyValue) RETURNING FamilyID". (Синтаксис придумал сам на основе SQL2003//MERGE и PG8.2//RETURNING.)
...
Рейтинг: 0 / 0
35 сообщений из 35, показаны все 2 страниц
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вытянуть из insert значение вставленно по умолчанию
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]