Programing

마지막으로 삽입 된 ID에 대한 PostgreSQL 함수

lottogame 2020. 3. 17. 08:33
반응형

마지막으로 삽입 된 ID에 대한 PostgreSQL 함수


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있다고 가정합니다 . 이것에 의존하지 않고 더 깨끗하게 느끼려면 대신 다음을 사용할 수 있습니다 .idSERIALpg_get_serial_sequence

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval(pg_get_serial_sequence('persons','id'));

주의 사항 : 같은 세션에서 ( 실행 한 ) currval()후에 만 작동합니다 .INSERTnextval()


옵션 2 : LASTVAL();

이것은 이전과 비슷하지만 시퀀스 이름을 지정할 필요가 없습니다. 가장 최근에 수정 된 시퀀스를 찾습니다 (세션 내에서 항상 위와 동일한 경고).


모두 CURRVALLASTVAL완전히 동시 안전합니다. PG의 시퀀스 동작은 다른 세션이 방해하지 않도록 설계되어 경쟁 조건의 위험이 없습니다 (다른 세션이 내 INSERT와 내 SELECT 사이에 다른 행을 삽입하면 여전히 올바른 값을 얻습니다).

그러나 미묘한 잠재적 인 문제가 있습니다. 데이터베이스 테이블 에 삽입 할 때 다른 테이블에 추가로 삽입 하는 TRIGGER (또는 RULE)가 있는 경우 잘못된 값을 제공 할 수 있습니다. 여분의 삽입이 동일한 테이블에서 수행되면 문제는 심지어 발생할 수 있습니다 (이는 훨씬 덜 일반적이지만 위험은 여전히 ​​존재합니다).personsLASTVALCURRVALpersons


옵션 3 : INSERTRETURNING

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(분리 성능에서)이 동시 안전이 아니기 때문에, 문을 : 당신의 사이 INSERTSELECT다른 세션 다른 레코드를 삽입 할 수도 있습니다.


INSERT 문의 RETURNING 절을 참조하십시오 . 기본적으로 INSERT는 쿼리로 두 배가되고 삽입 된 값을 반환합니다.


다음과 같이 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');

그리고 우리는 새로 생성 된 아이디를 얻습니다.

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


모든 데이터 레코드를 가져와야하는 사람들을 위해

returning *

ID를 포함한 모든 객체를 얻으려면 쿼리 끝까지.


이 시도:

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)

참고 URL : https://stackoverflow.com/questions/2944297/postgresql-function-for-last-inserted-id

반응형