programing

Oracle: max(id)+1과 sequence.nextval의 차이

codeshow 2023. 7. 31. 22:00
반응형

Oracle: max(id)+1과 sequence.nextval의 차이

Oracle을 사용하고 있습니다.

생성할 때 차이점은 무엇ID사용.max(id)+1및 사용sequance.nexval,언제 어디서 사용해야 합니까?

예:

insert into student (id,name) values (select max(id)+1 from student, 'abc');

그리고.

insert into student (id,name) values (SQ_STUDENT.nextval, 'abc');

SQ_STUDENT.nextval때때로 중복된 레코드에 오류가 발생합니다...

이 의심에 대해 저를 도와주세요.

와 함께select max(id) + 1접근하면 두 세션을 동시에 삽입하면 테이블에서 동일한 현재 최대 ID가 표시되고 두 세션 모두 동일한 새 ID 값이 삽입됩니다.이를 안전하게 사용할 수 있는 유일한 방법은 트랜잭션을 시작하기 전에 테이블을 잠그는 것입니다. 이는 번거롭고 트랜잭션을 직렬화합니다. (Stijn이 지적했듯이, 가장 높은 레코드가 삭제되면 값을 재사용할 수 있습니다.)기본적으로 이 접근 방식을 사용하지 마십시오. (아주 가끔 그렇게 해야 하는 강력한 이유가 있을 수 있지만, 저는 그것을 본 적이 있는지 확신할 수 없습니다.)

시퀀스는 두 세션이 서로 다른 값을 얻음을 보장하며 직렬화할 필요가 없습니다.더 나은 성능과 더 안전하고, 코드화하기 쉽고, 유지보수하기 쉽습니다.

시퀀스를 사용하여 중복 오류를 발생시킬 수 있는 유일한 방법은 시퀀스 값보다 ID가 높은 레코드가 테이블에 이미 존재하거나 시퀀스를 사용하지 않고 레코드를 계속 삽입하는 경우입니다.따라서 ID를 수동으로 입력한 기존 테이블(예: 1 ~ 10)이 있고 기본 시작 값이 1인 시퀀스를 만든 경우 시퀀스를 사용하는 첫 번째 삽입은 이미 존재하는 ID 1을 삽입하려고 합니다.10번 시도해본 결과, 11번의 시퀀스가 주어질 것이고, 그것은 효과가 있을 것입니다.그런 다음 max-ID 접근법을 사용하여 12를 사용하는 다음 삽입을 수행했지만 시퀀스는 여전히 11에 있을 것이고 다음에 전화를 걸 때도 12를 제공할 것입니다.nextval.

시퀀스와 테이블은 관련이 없습니다.수동으로 생성된 ID 값을 테이블에 삽입하면 시퀀스가 자동으로 업데이트되지 않으므로 두 가지 접근 방식이 혼합되지 않습니다. (특히 문서에서 언급한 것처럼 동일한 시퀀스를 사용하여 여러 테이블에 대한 ID를 생성할 수 있습니다.)

수동 접근 방식에서 시퀀스 접근 방식으로 변경하는 경우, 테이블의 기존 모든 ID보다 높은 시작 값으로 시퀀스가 생성되고 삽입을 수행하는 모든 항목이 이후에만 시퀀스를 사용하는지 확인해야 합니다.

사용자가 여러 명인 경우 시퀀스를 사용하면 됩니다.사용max하지 않다.

만약 당신이max(id) + 1그리고 여러 사용자를 허용하면 두 개의 세션이 동시에 작동하는 경우 정기적으로 동일한 세션이 표시됩니다.max따라서 동일한 새 키가 생성됩니다.제약 조건을 올바르게 구성했다고 가정하면 오류가 발생하여 이를 처리해야 합니다.다시 시도하여 처리할 수 있습니다.INSERT세션이 재시도되기 전에 다른 세션이 차단되면 계속해서 실패할 수 있지만 모든 세션에 많은 추가 코드가 있습니다.INSERT작동.

또한 코드를 직렬화합니다.세션에 새 행을 삽입하고 커밋하기 전에 점심을 먹으러 가는 경우(또는 커밋하기 전에 클라이언트 애플리케이션이 충돌하는 경우), 사용자가 돌아와서 커밋하거나 DBA가 세션을 종료할 때까지 다른 모든 사용자가 새 행을 삽입하지 못하도록 하여 강제로 재부팅합니다.

다른 답변에 추가하자면, 몇 가지 문제가 있습니다.

테이블에 행이 이미 없는 경우 max(id)+1 구문도 실패하므로 다음을 사용합니다.

Coalesce(Max(id),0) + 1

데이터 웨어하우스 로드의 경우처럼 테이블에 삽입하는 단일 프로세스만 있고 max(id)가 빠른 경우(아마도 빠른 경우) 이 기술에는 아무런 문제가 없습니다.

또한 예를 들어 복원 데이터를 테스트 시스템으로 이동하는 경우 테이블과 시퀀스 간에 값을 동기화하는 코드가 필요하지 않습니다.

다음을 사용하여 이 방법을 다중 행 삽입으로 확장할 수 있습니다.

Coalesce(max(id),0) + rownum

그럼에도 불구하고 병렬 인서트가 직렬화될 수도 예상됩니다.

일부 기술은 이러한 방법에서 잘 작동하지 않습니다.물론 이들은 select 문을 발행할 수 있기 때문에 SQL*Loader는 제외될 수 있습니다.그러나 SQL*Loader는 일반적으로 열 사양의 SEQUENCE 매개 변수를 통해 이 기술을 지원합니다. http://docs.oracle.com/cd/E11882_01/server.112/e22490/ldr_field_list.htm#i1008234

MAX(ID)가 실제로 충분히 빠르다고 가정하면 다음과 같은 작업이 가능하지 않을까요?

  • 먼저 MAX(ID)+1을 가져옵니다.
  • 그러면 NEXTVAL을 구합니다.
  • 이 두 가지를 비교하여 NEXTVAL이 MAX(ID)+1보다 작을 경우 시퀀스를 늘립니다.
  • INSERT 문에 NEXTVAL 사용

그런 경우, 저는 완전히 안정적인 절차를 가질 것이고 시퀀스 업데이트에 대한 걱정 없이 수동 삽입도 허용될 것입니다.

언급URL : https://stackoverflow.com/questions/17210835/oracle-difference-between-maxid1-and-sequence-nextval

반응형