오라클 시퀀스의 NEXTVAL과 CURRVAL을 실무에서 쓸 때 가장 헷갈리는 점은 둘의 차이와 예상치 못한 값 증가입니다. 간단히 말해, NEXTVAL은 시퀀스 값을 한 번 증가시키고 그 값을 반환하고, CURRVAL은 마지막으로 증가된 값을 조회만 합니다. 단, CURRVAL은 같은 세션에서 NEXTVAL을 먼저 호출한 후에만 사용할 수 있습니다. 또한 SELECT 문에서 NEXTVAL을 쓰면 시퀀스 값이 실제로 증가하므로, 조회용으로 쓸 때는 주의해야 합니다.
시퀀스 생성부터 NEXTVAL, CURRVAL 기본 사용법
우선 시퀀스를 생성해야 NEXTVAL과 CURRVAL을 사용할 수 있습니다. 기본 생성 구문은 다음과 같습니다.
CREATE SEQUENCE test_seq
INCREMENT BY 1
START WITH 1
MAXVALUE 999999
CYCLE
CACHE 20;
INCREMENT BY 1: 1씩 증가 (음수로 설정하면 감소)START WITH 1: 시작 값MAXVALUE: 최대값,NOMAXVALUE도 가능CYCLE또는NOCYCLE: 최대값 도달 시 다시 시작할지CACHE 20: 성능 향상을 위해 미리 20개 값을 메모리에 할당 (기본값 20)
이제 생성한 시퀀스로 NEXTVAL과 CURRVAL을 사용해 봅니다.
-- 첫 번째 호출: NEXTVAL로 시작값 1을 가져오고 시퀀스는 2로 증가
SELECT test_seq.NEXTVAL FROM DUAL; -- 결과: 1
-- 현재값 확인: CURRVAL은 마지막 NEXTVAL 값을 반환
SELECT test_seq.CURRVAL FROM DUAL; -- 결과: 1
-- 다시 NEXTVAL 호출: 시퀀스가 2로 증가하고 2를 반환
SELECT test_seq.NEXTVAL FROM DUAL; -- 결과: 2
INSERT 문에서도 동일하게 사용합니다.
INSERT INTO example_table (id, name) VALUES (test_seq.NEXTVAL, '홍길동');
이때 NEXTVAL은 INSERT 실행 시마다 값을 증가시키므로, 중복 없는 일련번호를 자동으로 생성할 수 있습니다.
SELECT 조회에서 NEXTVAL을 쓰면 값이 증가하는 이유
많은 분들이 SELECT 문에서 NEXTVAL을 조회용으로 썼다가 시퀀스 값이 예상보다 크게 증가해서 당황합니다. 오라클 시퀀스는 테이블과 독립적으로 동작하는 객체이기 때문입니다. SELECT에서 NEXTVAL을 호출하는 순간, 그 자체로 시퀀스가 증가합니다.
- SELECT로 NEXTVAL을 조회하면 시퀀스 값이 실제로 증가하고 그 증가된 값이 반환됩니다.
- 따라서 단순히 현재값만 확인하려면 반드시 CURRVAL을 사용해야 하며, 같은 세션 내에서 NEXTVAL을 먼저 호출한 이후에만 가능합니다.
- 실무에서는 주로 INSERT나 UPDATE 문에서만 NEXTVAL을 사용하고, 조회 화면에서 현재 시퀀스 값을 보여줘야 한다면 CURRVAL을 별도로 호출하는 방식으로 설계합니다.
시퀀스 현재값 확인 시 CACHE 때문에 값이 다르게 보이는 현상
시퀀스의 현재값을 확인하기 위해 USER_SEQUENCES 뷰의 LAST_NUMBER를 조회할 때가 있습니다.
SELECT LAST_NUMBER FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'TEST_SEQ';
그런데 조회 결과가 실제로 마지막으로 호출한 NEXTVAL 값과 차이가 나는 경우가 있습니다. 이는 시퀀스 생성 시 CACHE 설정 때문입니다.
- 기본값이 CACHE 20이라면, 오라클은 시퀀스가 처음 사용될 때 미리 20개의 값을 메모리에 할당합니다.
- 예를 들어 START WITH 1, CACHE 20이면 실제로 LAST_NUMBER는 21로 표시됩니다. (1-20을 미리 할당했으므로 다음에 할당될 값이 21)
- 따라서 LAST_NUMBER는 "다음에 할당될 값"이지, 현재까지 사용된 값이 아닙니다.
- 정확한 현재 사용값을 알고 싶다면
NOCACHE옵션으로 시퀀스를 생성하거나, CURRVAL을 직접 조회하는 것이 좋습니다.
시퀀스 값을 원하는 숫자로 초기화(재설정)하는 방법
시퀀스를 생성한 후 중간에 값을 강제로 변경해야 할 때가 있습니다. 예를 들어 데이터 이관 후 시퀀스를 특정 숫자로 맞추거나, 현재값을 1로 리셋해야 하는 상황입니다.
가장 실무에서 많이 쓰는 방법은 INCREMENT BY를 조정하는 것입니다. 예를 들어 현재 시퀀스 값이 10이고, 이를 1로 초기화하려면 다음과 같이 합니다.
-- 1. 현재값을 확인 (예: CURRVAL = 10)
SELECT test_seq.CURRVAL FROM DUAL;
-- 2. INCREMENT BY를 -9로 변경 (10에서 1로 가려면 9 감소)
ALTER SEQUENCE test_seq INCREMENT BY -9;
-- 3. NEXTVAL을 호출하면 현재값 10에서 -9가 적용되어 1이 됨
SELECT test_seq.NEXTVAL FROM DUAL; -- 결과: 1
-- 4. INCREMENT BY를 원래 값(1)으로 복구
ALTER SEQUENCE test_seq INCREMENT BY 1;
이렇게 하면 시퀀스를 삭제하고 다시 생성하지 않고도 값을 원하는 숫자로 재설정할 수 있습니다. 단, 이 작업 도중 다른 세션에서 NEXTVAL을 호출하면 의도치 않은 값이 나올 수 있으므로, 운영 중인 시스템에서는 트랜잭션을 걸거나 잠시 사용을 중단한 후 실행하는 것이 안전합니다.
FAQ
Q. CURRVAL을 세션 없이 다른 세션에서 조회할 수 있나요?
아니요, CURRVAL은 현재 세션이 마지막으로 NEXTVAL을 호출한 값만 반환합니다. 다른 세션에서 생성된 시퀀스 값은 CURRVAL로 조회할 수 없습니다. 다른 세션의 현재값을 확인하려면 USER_SEQUENCES 뷰의 LAST_NUMBER를 참고해야 하지만, 이 값도 CACHE 설정에 따라 실제 사용값과 다를 수 있습니다.
Q. 시퀀스를 생성할 때 NOCACHE로 설정하면 성능이 느려지나요?
네, CACHE를 사용하면 메모리에 미리 값을 할당해 두기 때문에 매번 디스크 I/O가 발생하지 않아 성능이 향상됩니다. NOCACHE로 설정하면 NEXTVAL 호출 시마다 디스크에 기록하므로 속도가 느려질 수 있습니다. 실무에서는 CACHE 20-100 정도를 기본값으로 사용하고, 시퀀스 갭 문제가 중요하지 않은 경우 CACHE를 유지하는 것이 일반적입니다.
Q. NEXTVAL을 호출했는데 시퀀스 값이 1이 아닌 21부터 시작합니다. 왜 그런가요?
시퀀스를 생성할 때 START WITH 1로 설정했더라도, CACHE 20이 기본값이면 오라클은 내부적으로 1-20까지의 값을 미리 할당합니다. 실제 첫 번째 NEXTVAL 호출은 1을 반환하지만, 두 번째 호출은 2가 아닌 상황에 따라 다릅니다. 따라서 값을 예측하기 어렵다면 START WITH 1 NOCACHE로 생성하거나, 필요한 경우 직접 초기화 방법을 사용하세요.