Czy coś takiego jest możliwe?
INSERT INTO Table2 (val)
VALUES ((INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id));
jak użycie wartości zwracanej jako wartości do wstawienia wiersza w drugiej tabeli z odniesieniem do pierwszej tabeli?
Czy coś takiego jest możliwe?
INSERT INTO Table2 (val)
VALUES ((INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id));
jak użycie wartości zwracanej jako wartości do wstawienia wiersza w drugiej tabeli z odniesieniem do pierwszej tabeli?
Odpowiedzi:
Możesz to zrobić, zaczynając od Postgres 9.1:
with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val)
SELECT id
FROM rows
W międzyczasie, jeśli interesuje Cię tylko identyfikator, możesz to zrobić za pomocą wyzwalacza:
create function t1_ins_into_t2()
returns trigger
as $$
begin
insert into table2 (val) values (new.id);
return new;
end;
$$ language plpgsql;
create trigger t1_ins_into_t2
after insert on table1
for each row
execute procedure t1_ins_into_t2();
rows
z (some_query returning ...)
pracy może w dzisiejszych czasach (nie próbowałem).
Najlepsza praktyka w tej sytuacji. Użyj RETURNING … INTO
.
INSERT INTO teams VALUES (...) RETURNING id INTO last_id;
Zwróć uwagę, że dotyczy to PLPGSQL
RETURNING ... INTO
.
Zgodnie z odpowiedzią udzieloną przez Denisa de Bernardy.
Jeśli chcesz, aby identyfikator został również zwrócony później i chcesz wstawić więcej rzeczy do Tabeli2:
with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val, val2, val3)
SELECT id, 'val2value', 'val3value'
FROM rows
RETURNING val
Możesz użyć lastval()
funkcji:
Zwracana wartość ostatnio uzyskana
nextval
dla dowolnej sekwencji
Więc coś takiego:
INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val) VALUES (lastval());
Będzie to działać dobrze, o ile nikt nie wywoła nextval()
żadnej innej sekwencji (w bieżącej sesji) między Twoimi INSERTami.
Jak Denis zauważył poniżej, a ja ostrzegałem powyżej, użycie lastval()
może nextval()
spowodować kłopoty, jeśli uzyskasz dostęp do innej sekwencji, używając między swoimi INSERTami. Mogłoby się to zdarzyć, gdyby istniał wyzwalacz INSERT na Table1
tym, który ręcznie wywołał nextval()
sekwencję, lub, co bardziej prawdopodobne, wykonał INSERT na tabeli z kluczem podstawowym SERIAL
lubBIGSERIAL
. Jeśli chcesz być naprawdę paranoikiem (dobrze, w końcu oni naprawdę są tobą, aby cię dopaść), możesz użyć, currval()
ale musisz znać nazwę odpowiedniej sekwencji:
INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val) VALUES (currval('Table1_id_seq'::regclass));
Sekwencja generowana automatycznie jest zwykle nazywana, t_c_seq
gdzie t
jest nazwą tabeli i c
jest nazwą kolumny, ale zawsze możesz się tego dowiedzieć, wchodząc do psql
i mówiąc:
=> \d table_name;
a następnie spojrzeć na domyślną wartość danej kolumny, na przykład:
id | integer | not null default nextval('people_id_seq'::regclass)
FYI: lastval()
jest mniej więcej wersją MySQL dla PostgreSQL LAST_INSERT_ID
. Wspominam o tym tylko dlatego, że wiele osób lepiej zna MySQL niż PostgreSQL, więc odsyłanie lastval()
do czegoś znajomego może wyjaśnić sprawę.
lastval
polega na tym, że za plecami może znajdować się sekwencja oparta na INSERT z wyzwalacza AFTER INSERT w Table1. Byłoby to w bieżącej sesji i prawdopodobnie zmieniłoby się, lastval()
gdy się tego nie spodziewasz.