Search

[필수:정합]방금 INSERT한 번호를 MAX로 조회

BAD

MAX()로 채번 값 재조회
SESSION-A
-- 세션A TRUNCATE TABLE startdbpg.tr_ord_refund_seq RESTART IDENTITY; -- 1 BEGIN; -- 2 INSERT INTO startdbpg.tr_ord_refund_seq (ord_no, refund_amt, refund_reason, req_st, req_dtm) VALUES (1, 1000, '상품 누락 환불', 'REQ', CURRENT_TIMESTAMP); -- 7 (A의 채번 값은 1이지만, B가 커밋한 뒤 MAX는 2가 조회됨) SELECT MAX(refund_req_no) new_refund_req_no FROM startdbpg.tr_ord_refund_seq; -- 8 COMMIT;
SQL
복사
SESSION-B
-- 세션B -- 3 BEGIN; -- 4 INSERT INTO startdbpg.tr_ord_refund_seq (ord_no, refund_amt, refund_reason, req_st, req_dtm) VALUES (1, 1000, '상품 누락 환불', 'REQ', CURRENT_TIMESTAMP); -- 5 (B의 채번 값은 2, MAX 조회 결과도 2) SELECT MAX(refund_req_no) new_refund_req_no FROM startdbpg.tr_ord_refund_seq; -- 6 COMMIT;
SQL
복사
•
A가 MAX를 조회하는 시점에는 B가 커밋한 번호 2까지 보입니다. 그래서 A는 자기 번호(1)가 아닌 2를 받습니다.
•
이 번호로 상세 데이터를 INSERT하면 남의 데이터에 붙습니다.

GOOD ①

INSERT RETURNING으로 값 반환
SESSION-A
-- 세션A TRUNCATE TABLE startdbpg.tr_ord_refund_seq RESTART IDENTITY; -- 1 BEGIN; -- 2 (입력된 값 1이 바로 출력됨) INSERT INTO startdbpg.tr_ord_refund_seq (ord_no, refund_amt, refund_reason, req_st, req_dtm) VALUES (1, 1000, '상품 누락 환불', 'REQ', CURRENT_TIMESTAMP) RETURNING refund_req_no; -- 6 COMMIT;
SQL
복사
SESSION-B
-- 세션B -- 3 BEGIN; -- 4 (입력된 값 2가 바로 출력됨) INSERT INTO startdbpg.tr_ord_refund_seq (ord_no, refund_amt, refund_reason, req_st, req_dtm) VALUES (1, 1000, '상품 누락 환불', 'REQ', CURRENT_TIMESTAMP) RETURNING refund_req_no; -- 5 COMMIT;
SQL
복사
•
INSERT ... RETURNING refund_req_no는 방금 INSERT한 행에 부여된 번호를 즉시 반환합니다.
•
추가 조회가 없고 다른 세션이나 다른 시퀀스의 영향을 받지 않아 가장 권장하는 방식입니다.

GOOD ②

LASTVAL()로 세션 값 조회 (차선책)
SESSION-A
-- 세션A TRUNCATE TABLE startdbpg.tr_ord_refund_seq RESTART IDENTITY; -- 1 BEGIN; -- 2 INSERT INTO startdbpg.tr_ord_refund_seq (ord_no, refund_amt, refund_reason, req_st, req_dtm) VALUES (1, 1000, '상품 누락 환불', 'REQ', CURRENT_TIMESTAMP); -- 7 (1 조회됨) SELECT LASTVAL(); -- 8 COMMIT;
SQL
복사
SESSION-B
-- 세션B -- 3 BEGIN; -- 4 INSERT INTO startdbpg.tr_ord_refund_seq (ord_no, refund_amt, refund_reason, req_st, req_dtm) VALUES (1, 1000, '상품 누락 환불', 'REQ', CURRENT_TIMESTAMP); -- 5 (2 조회됨) SELECT LASTVAL(); -- 6 COMMIT;
SQL
복사
•
LASTVAL()은 현재 세션에서 마지막으로 사용한 시퀀스의 값을 조회합니다.
•
다른 세션의 INSERT에는 영향을 받지 않아 SESSION-A는 1, SESSION-B는 2를 조회합니다. 다만 아래 TIP의 주의사항이 있어 차선책입니다.

실행 결과 비교

구분
SESSION-A 채번 값
SESSION-A 조회 결과
SESSION-B 채번 값
SESSION-B 조회 결과
BAD — MAX()
1
2 (잘못된 값)
2
2
GOOD ① — RETURNING
1
1
2
2
GOOD ② — LASTVAL()
1
1
2
2
각 BAD/GOOD 테스트는 테이블과 시퀀스를 초기화한 상태에서 별도로 실행하며, 주석의 번호 순서(1~8 또는 1~6)를 따라 두 세션을 교대로 실행합니다. SESSION-A의 TRUNCATE ... RESTART IDENTITY는 먼저 완료해야 합니다. 실습 테이블의 refund_req_no는 GENERATED BY DEFAULT AS IDENTITY로 자동 채번됩니다.
💡

KEY POINT

•
MAX(채번 컬럼)은 내가 INSERT한 번호가 아닐 수 있습니다. 다른 세션이 커밋한 번호까지 보이기 때문입니다.
•
방금 INSERT한 번호는 INSERT ... RETURNING으로 받습니다.
•
LASTVAL()은 같은 세션에서 다른 시퀀스가 실행되면 값이 바뀔 수 있어 차선책입니다.
✏️

TIP-1. LASTVAL()의 주의사항

•
LASTVAL()은 INSERT 이후 같은 세션에서 다른 시퀀스의 nextval()이 실행되면 그 값으로 바뀔 수 있습니다. 트리거가 다른 시퀀스를 사용하는 경우에도 주의해야 합니다.
•
특정 시퀀스의 현재 세션 값은 CURRVAL(시퀀스명)으로 확인할 수 있지만, 내가 INSERT한 행의 번호는 RETURNING으로 받는 것이 가장 명확합니다.
🔗