PostgreSQL에서 마지막 id를 테이블에 삽입하려면 어떻게합니까?
MS SQL에는 SCOPE_IDENTITY ()가 있습니다.
다음과 같은 것을 사용하도록 조언하지 마십시오.
select max(id) from table
PostgreSQL에서 마지막 id를 테이블에 삽입하려면 어떻게합니까?
MS SQL에는 SCOPE_IDENTITY ()가 있습니다.
다음과 같은 것을 사용하도록 조언하지 마십시오.
select max(id) from table
답변:
( tl;dr
: goto 옵션 3 : RETURNING과 함께 삽입)
postgresql에는 테이블에 대한 "id"개념이 없으며 시퀀스 (일반적으로 SERIAL 의사 유형 의 대리 기본 키의 기본값으로 사용되는 것은 아님 ) 만 있습니다.
새로 삽입 된 행의 ID를 얻는 데 관심이있는 경우 몇 가지 방법이 있습니다.
옵션 1 : CURRVAL(<sequence name>);
.
예를 들면 다음과 같습니다.
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
시퀀스의 이름을 알고 있어야합니다. 실제로는 임의적입니다. 이 예에서는 테이블 에 의사 유형으로 작성된 열 persons
이 있다고 가정합니다 . 이것에 의존하지 않고 더 깨끗하게 느끼려면 대신 다음을 사용할 수 있습니다 .id
SERIAL
pg_get_serial_sequence
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
주의 사항 : 같은 세션에서 ( 실행 한 ) currval()
후에 만 작동합니다 .INSERT
nextval()
옵션 2 : LASTVAL();
이것은 이전과 비슷하지만 시퀀스 이름을 지정할 필요가 없습니다. 가장 최근에 수정 된 시퀀스를 찾습니다 (세션 내에서 항상 위와 동일한 경고).
모두 CURRVAL
와 LASTVAL
완전히 동시 안전합니다. PG의 시퀀스 동작은 다른 세션이 방해하지 않도록 설계되어 경쟁 조건의 위험이 없습니다 (다른 세션이 내 INSERT와 내 SELECT 사이에 다른 행을 삽입하면 여전히 올바른 값을 얻습니다).
그러나 미묘한 잠재적 인 문제가 있습니다. 데이터베이스에 TRIGGER (또는 RULE)가 있으면 persons
테이블 에 삽입 할 때 다른 테이블에 추가로 삽입 LASTVAL
하는 경우 잘못된 값을 줄 수 있습니다. CURRVAL
여분의 삽입이 동일한 persons
테이블에서 수행되면 문제는 심지어 발생할 수 있습니다 (이는 훨씬 덜 일반적이지만 위험은 여전히 존재합니다).
옵션 3 : INSERT
와RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
이것은 ID를 얻는 가장 깨끗하고 효율적이며 안전한 방법입니다. 이전의 위험은 없습니다.
단점? 거의 없음 : INSERT 문을 호출하는 방식을 수정해야 할 수도 있습니다 (최악의 경우 API 또는 DB 계층에서 INSERT가 값을 반환하지 않을 것으로 예상 함). 표준 SQL이 아닙니다. Postgresql 8.2 (2006 년 12 월 ...)부터 사용 가능합니다.
결론 : 가능하면 옵션 3으로 가십시오. 다른 곳에서는 1을 선호하십시오.
참고 : 마지막으로 삽입 된 ID를 전역 적으로 가져 오려는 경우 (세션이 반드시 필요하지는 않음) 이 모든 방법은 쓸모가 없습니다 . 이를 위해서는 의지해야합니다 SELECT max(id) FROM table
(물론 다른 거래에서 커밋되지 않은 삽입물을 읽지 않습니다).
반대로, 당신이해야 결코 사용하지 SELECT max(id) FROM table
당신의에 의해 생성 된 ID를 얻기 위해, 대신 위의 3 개 가지 옵션 중 하나를 INSERT
(분리 성능에서)이 동시 안전이 아니기 때문에, 문을 : 당신의 사이 INSERT
와 SELECT
다른 세션 다른 레코드를 삽입 할 수도 있습니다.
SELECT max(id)
불행히도 행 삭제를 시작하자마자 작업을 수행하지 않습니다.
1,2,3,4,5
및 행 4와 5를 삭제하고, 마지막으로 삽입 된 ID는 여전히 5하지만, max()
반환 3.
RETURNING id;
이것을 다른 테이블에 삽입 하는 방법에 대한 샘플을 환영합니다!
RETURNING id
에 제공된 SQL 스크립트 내에서 어떻게 사용할 수 psql
있습니까?
INSERT 문의 RETURNING 절을 참조하십시오 . 기본적으로 INSERT는 쿼리로 두 배가되고 삽입 된 값을 반환합니다.
insert into names (firstname, lastname) values ('john', 'smith') returning id;
을 실행하면 마치 select id from names where id=$lastid
직접 실행 한 것처럼 단순히 id를 출력 합니다. 당신이 할 경우 AA 변수로 수익을 저장 한 후 insert into names (firstname, lastname) values ('john', 'smith') returning id into other_variable;
복귀를 포함하는 문이 경우 함수의 마지막 문장이 다음 ID가되는 returning
'에드는 전체 함수에 의해 반환됩니다.
다음과 같이 INSERT 문에서 RETURNING 절을 사용할 수 있습니다.
wgzhao=# create table foo(id int,name text);
CREATE TABLE
wgzhao=# insert into foo values(1,'wgzhao') returning id;
id
----
1
(1 row)
INSERT 0 1
wgzhao=# insert into foo values(3,'wgzhao') returning id;
id
----
3
(1 row)
INSERT 0 1
wgzhao=# create table bar(id serial,name text);
CREATE TABLE
wgzhao=# insert into bar(name) values('wgzhao') returning id;
id
----
1
(1 row)
INSERT 0 1
wgzhao=# insert into bar(name) values('wgzhao') returning id;
id
----
2
(1 row)
INSERT 0
Leonbloy의 답변 은 매우 완전합니다. OPTION 3이 정확히 맞지 않는 PL / pgSQL 함수 내에서 마지막으로 삽입 된 값을 가져와야하는 특별한 경우 만 추가합니다.
예를 들어 다음 표가있는 경우
CREATE TABLE person(
id serial,
lastname character varying (50),
firstname character varying (50),
CONSTRAINT person_pk PRIMARY KEY (id)
);
CREATE TABLE client (
id integer,
CONSTRAINT client_pk PRIMARY KEY (id),
CONSTRAINT fk_client_person FOREIGN KEY (id)
REFERENCES person (id) MATCH SIMPLE
);
고객 기록을 삽입해야하는 경우 개인 기록을 참조해야합니다. 그러나 새 레코드를 클라이언트에 삽입하고 새 개인 레코드를 삽입하는 PL / pgSQL 함수를 고안하려고한다고 가정 해 봅시다. 이를 위해 우리는 leonbloy의 OPTION 3의 약간의 변형을 사용해야합니다.
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO [new_variable];
두 개의 INTO 절이 있습니다. 따라서 PL / pgSQL 함수는 다음과 같이 정의됩니다.
CREATE OR REPLACE FUNCTION new_client(lastn character varying, firstn character varying)
RETURNS integer AS
$BODY$
DECLARE
v_id integer;
BEGIN
-- Inserts the new person record and retrieves the last inserted id
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO v_id;
-- Inserts the new client and references the inserted person
INSERT INTO client(id) VALUES (v_id);
-- Return the new id so we can use it in a select clause or return the new id into the user application
RETURN v_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
이제 다음을 사용하여 새 데이터를 삽입 할 수 있습니다.
SELECT new_client('Smith', 'John');
또는
SELECT * FROM new_client('Smith', 'John');
그리고 우리는 새로 만든 id를 얻습니다.
new_client
integer
----------
1
아래 예를 참조하십시오
CREATE TABLE users (
-- make the "id" column a primary key; this also creates
-- a UNIQUE constraint and a b+-tree index on the column
id SERIAL PRIMARY KEY,
name TEXT,
age INT4
);
INSERT INTO users (name, age) VALUES ('Mozart', 20);
그런 다음 마지막으로 삽입 된 ID를 얻으려면 테이블 "user"seq 열 이름 "id"에 이것을 사용하십시오.
SELECT currval(pg_get_serial_sequence('users', 'id'));
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))
물론 테이블 이름과 열 이름을 제공해야합니다.
이것은 현재 세션 / 연결에 대한 것입니다 http://www.postgresql.org/docs/8.3/static/functions-sequence.html
이 시도:
select nextval('my_seq_name'); // Returns next value
이 값이 1 (또는 시퀀스의 start_value가 무엇이든)을 반환하면 시퀀스를 원래 값으로 다시 설정하여 false 플래그를 전달하십시오.
select setval('my_seq_name', 1, false);
그렇지 않으면,
select setval('my_seq_name', nextValue - 1, true);
그러면 시퀀스 값이 원래 상태로 복원되고 "setval"이 원하는 시퀀스 값과 함께 반환됩니다.
Postgres에는 동일한 메커니즘에 내장 메커니즘이 있으며, 동일한 쿼리에서 ID 또는 쿼리가 반환하려는 항목을 반환합니다. 여기 예가 있습니다. column1과 column2라는 2 개의 열이있는 테이블을 작성하고 모든 삽입 후에 column1을 리턴하려고합니다.
# create table users_table(id serial not null primary key, name character varying);
CREATE TABLE
#insert into users_table(name) VALUES ('Jon Snow') RETURNING id;
id
----
1
(1 row)
# insert into users_table(name) VALUES ('Arya Stark') RETURNING id;
id
----
2
(1 row)
Java 및 Postgres 에서이 문제가 발생했습니다. 새로운 Connector-J 버전을 업데이트하여 수정했습니다.
postgresql-9.2-1002.jdbc4.jar
https://jdbc.postgresql.org/download.html : 버전 42.2.12