Oracle에서 AUTO_INCREMENT로 ID를 만드는 방법은 무엇입니까?


422

Oracle에는 버전 11g까지 AUTO_INCREMENT의 개념이없는 것으로 보입니다.

Oracle 11g에서 자동 증분처럼 동작하는 열을 어떻게 만들 수 있습니까?


3
BEFORE INSERT테이블 에서 트리거를 생성하고 시퀀스에서 값을
가져와

7
신원 열은 이제 오라클 12C의에서 사용할 수있는 docs.oracle.com/cd/E16655_01/gateways.121/e22508/...
데이비드 드리지


Oracle RAC를 사용하고 있습니까? 명령문 끝에 CACHED를 사용하면 성능을 향상시킬 수 있습니다. 단기간에 많은 인서트를 수행하는 경우 (및 주문이 중요하지 않은 경우) 추가 성능 이점을 위해 스 태거 시퀀스 인서트 트리거를 고려하십시오. 참조 : dba-oracle.com/t_rac_proper_sequence_usage.htm
Peeter Kokk

답변:


596

Oracle 11g부터 Oracle 에는 "auto_increment"또는 "identity"열과 같은 것은 없습니다 . 그러나 시퀀스와 트리거로 쉽게 모델링 할 수 있습니다.

테이블 정의 :

CREATE TABLE departments (
  ID           NUMBER(10)    NOT NULL,
  DESCRIPTION  VARCHAR2(50)  NOT NULL);

ALTER TABLE departments ADD (
  CONSTRAINT dept_pk PRIMARY KEY (ID));

CREATE SEQUENCE dept_seq START WITH 1;

트리거 정의 :

CREATE OR REPLACE TRIGGER dept_bir 
BEFORE INSERT ON departments 
FOR EACH ROW

BEGIN
  SELECT dept_seq.NEXTVAL
  INTO   :new.id
  FROM   dual;
END;
/

최신 정보:

IDENTITY 열은 이제 Oracle 12c에서 사용할 수 있습니다.

create table t1 (
    c1 NUMBER GENERATED by default on null as IDENTITY,
    c2 VARCHAR2(10)
    );

또는 시작 및 증분 값을 지정하여 식별 열에 삽입하지 못하도록합니다 ( GENERATED ALWAYS) (Oracle 12c + 만 해당)

create table t1 (
    c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
    c2 VARCHAR2(10)
    );

또는 Oracle 12에서는 시퀀스를 기본값으로 사용할 수 있습니다.

CREATE SEQUENCE dept_seq START WITH 1;

CREATE TABLE departments (
  ID           NUMBER(10)    DEFAULT dept_seq.nextval NOT NULL,
  DESCRIPTION  VARCHAR2(50)  NOT NULL);

ALTER TABLE departments ADD (
  CONSTRAINT dept_pk PRIMARY KEY (ID));

5
나는 n00b dept_seq입니다. 어디에서 왔는지 알려주세요 !
J86

3
시퀀스 생성 dept_seq; 테이블과 같은 dept_seq ...를 생성하지만이 경우 dept_seq.NEXTVAL으로 증가시킬 수있는 유일한 숫자는 트리거를 참조하십시오.
Benjamin Eckstein

언급 한 바와 같이, ID가 지정된 행을 발견하면 원래 코드가 실패합니다. 그러나이 경우는 어떻습니까 : 트리거는 INSERT에 명시 적으로 지정된 ID가없는 경우에만 ID를 자동으로 할당합니다. 이게 실패할까요? 그리고 이것을 수행하는 올바른 방법은 무엇입니까?
FanaticD

10
나와 같은 오라클 초보자의 경우 'new.id'의 'id'부분은 위 표의 'id'열을 나타냅니다. 'new'는 생성 된 새 행을 가리키는 예약어입니다.
Hoppe

2
당신은 당신이 SELECT .. INTO할 수있는 방아쇠 에 사용할 필요가 없습니다 :new.id := dept_seq.NEXTVAL;.
MT0

90

SYS_GUIDGUID (전역 적으로 고유 한 ID)를 반환합니다. A SYS_GUID는입니다 RAW(16). 증분 숫자 값을 생성하지 않습니다.

증분 숫자 키를 만들려면 시퀀스를 만들어야합니다.

CREATE SEQUENCE name_of_sequence
  START WITH 1
  INCREMENT BY 1
  CACHE 100;

그런 다음 INSERT진술서 에서 해당 순서를 사용하십시오 .

INSERT INTO name_of_table( primary_key_column, <<other columns>> )
  VALUES( name_of_sequence.nextval, <<other values>> );

또는 시퀀스를 사용하여 기본 키 값을 자동으로 채우는 트리거를 정의 할 수 있습니다.

CREATE OR REPLACE TRIGGER trigger_name
  BEFORE INSERT ON table_name
  FOR EACH ROW
BEGIN
  SELECT name_of_sequence.nextval
    INTO :new.primary_key_column
    FROM dual;
END;

Oracle 11.1 이상을 사용하는 경우 트리거를 약간 단순화 할 수 있습니다

CREATE OR REPLACE TRIGGER trigger_name
  BEFORE INSERT ON table_name
  FOR EACH ROW
BEGIN
  :new.primary_key_column := name_of_sequence.nextval;
END;

정말로 사용하고 싶다면 SYS_GUID

CREATE TABLE table_name (
  primary_key_column raw(16) default sys_guid() primary key,
  <<other columns>>
)

1
무엇을 CACHE 100; in CREATE SEQUENCE name_of_sequence START WITH 1 INCREMENT BY 1 CACHE 100;합니까?
Angelina

3
CACHE 100 : 키워드는 다음 100 개의 숫자를 메모리로 가져옵니다. 일반적으로 SEQUENCE는 값이 변경 될 때마다 데이터베이스에 저장되며, 캐시하는 경우 캐시 된 값이 소진 된 경우에만 저장되고 검색됩니다. 성능이 크게 향상되지만 데이터베이스가 실패하면 사용하지 않은 모든 캐시 된 값이 손실됩니다.
Ramazan Polat 2018 년

2
A SYS_GUID()RAW(16)32가 아닌 a 입니다 .
turbanoff

2
@ turbanoff-잘 잡았습니다. 내 답변을 업데이트했습니다. SYS_GUID문서는 선언 raw(32)저를 혼동하는합니다.
Justin Cave

@JustinCave 시퀀스와 트리거를 만드는 데 귀하의 접근 방식을 사용했습니다. 프로그래밍 방식으로 행을 삭제하면 (java) ID (기본 키)도 조정됩니까?
kittu

52

Oracle 12c에서는 다음과 같은 작업을 수행 할 수 있습니다.

CREATE TABLE MAPS
(
  MAP_ID INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL,
  MAP_NAME VARCHAR(24) NOT NULL,
  UNIQUE (MAP_ID, MAP_NAME)
);

그리고 오라클에서 (Pre 12c).

-- create table
CREATE TABLE MAPS
(
  MAP_ID INTEGER NOT NULL ,
  MAP_NAME VARCHAR(24) NOT NULL,
  UNIQUE (MAP_ID, MAP_NAME)
);

-- create sequence
CREATE SEQUENCE MAPS_SEQ;

-- create tigger using the sequence
CREATE OR REPLACE TRIGGER MAPS_TRG 
BEFORE INSERT ON MAPS 
FOR EACH ROW
WHEN (new.MAP_ID IS NULL)
BEGIN
  SELECT MAPS_SEQ.NEXTVAL
  INTO   :new.MAP_ID
  FROM   dual;
END;
/

2
@ JonHeller 개인적 IDENTITY으로이 대답에서 예가 훨씬 명확 하다고 말합니다 .
EpicPandaForce

5
WHEN (new.MAP_ID IS NULL)허용 대답에 있지 않습니다. 공감.
dcsohl

1
@dcsohl, WHEN ( new.MAP_ID is null)이 경우에 좋은 코드가 아닙니다 이미 허용 대답에서 @ABCade에 의해 코멘트 섹션에 설명되어 있습니다 .. 읽기가)
ajmalmhd04

에서에서 CREATE OR REPLACE TRIGGER를 실행 END;하면 "바인드 입력"창이 나타납니다. "적용"을 클릭하고 해당 창에서 다른 작업을 수행하지 않고 ALTER TRIGGER명령 을 실행하면 모든 것이 잘되지만 프로그래밍 방식으로 해당 팝업을 제거하고 모든 것을 함께 실행할 수있는 방법이 있었으면 좋겠습니다. 당신이 그것을 모두 시도한다면, 당신은 PLS-00103: Encountered the symbol 'ALTER'그것을 얻지 못하고 좋아하지도 않습니다 EXECUTE IMMEDIATE(같은 오류, Encountered the symbol 'EXECUTE'대신 말해보십시오 ).
vapcguy

[42000][907] ORA-00907: missing right parenthesisOracle 12c 버전을 실행할 때 얻었습니다 . 어떤 아이디어?
belgoros

32

세 가지 맛이 있습니다.

  1. 숫자 . 단순 증가 숫자 값 (예 : 1,2,3, ....)
  2. GUID . RAW데이터 형식 으로 사용되는 전역 범용 식별자 .
  3. GUID (문자열) . 위와 동일하지만 일부 언어에서는 다루기가 더 쉬운 문자열입니다.

xID 열입니다. FOO각 예에서 테이블 이름으로 대체 하십시오.

-- numerical identity, e.g. 1,2,3...
create table FOO (
    x number primary key
);
create sequence  FOO_seq;

create or replace trigger FOO_trg
before insert on FOO
for each row
begin
  select FOO_seq.nextval into :new.x from dual;
end;
/

-- GUID identity, e.g. 7CFF0C304187716EE040488AA1F9749A
-- use the commented out lines if you prefer RAW over VARCHAR2.
create table FOO (
    x varchar(32) primary key        -- string version
    -- x raw(32) primary key         -- raw version
);

create or replace trigger FOO_trg
before insert on FOO
for each row
begin
  select cast(sys_guid() as varchar2(32)) into :new.x from dual;  -- string version
  -- select sys_guid() into :new.x from dual;                     -- raw version
end;
/

최신 정보:

Oracle 12c에는 트리거에 의존하지 않는 다음 두 가지 변형이 도입되었습니다.

create table mytable(id number default mysequence.nextval);
create table mytable(id number generated as identity);

첫 번째는 전통적인 방식으로 시퀀스를 사용합니다. 두 번째는 내부적으로 가치를 관리합니다.


7

SQL Server ID 열과 같은 열을 의미한다고 가정합니까?

Oracle에서는 SEQUENCE를 사용하여 동일한 기능을 수행합니다. 좋은 링크를 찾아 여기에 게시 할 수 있는지 확인하겠습니다.

업데이트 : 직접 찾은 것처럼 보입니다. 어쨌든 링크는 다음과 같습니다. http://www.techonthenet.com/oracle/sequences.php


7

Oracle Database 12c는 자동 증분 (시스템 생성) 열인 Identity를 도입했습니다. 이전 데이터베이스 버전 (11g까지)에서는 일반적으로 시퀀스와 트리거를 만들어 Identity를 구현합니다. 12c부터는 고유 한 테이블을 생성하고 ID로 생성해야하는 열을 정의 할 수 있습니다.

다음 기사에서는이를 사용하는 방법에 대해 설명합니다.

ID 열-Oracle Database 12c의 새로운 항목


5
이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다.
Bridge

5

Trigger그리고 Sequence당신이 누구나 쉽게 / 기억 / 읽고 이해할 수있는 일련 번호를하고자 할 때 사용할 수 있습니다. 그러나 이런 식으로 ID 열 (emp_id와 같은)을 관리하지 않고이 열의 값이 그다지 중요하지 않은 경우 SYS_GUID()테이블 생성에서이를 사용 하여 자동 증분을 얻을 수 있습니다 .

CREATE TABLE <table_name> 
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));

이제 emp_id열에 "글로벌 고유 식별자 값"이 적용됩니다. 이와 같이 emp_id 열을 무시하여 테이블에 값을 삽입 할 수 있습니다.

INSERT INTO <table_name> (name) VALUES ('name value');

따라서 emp_id열에 고유 한 값을 삽입합니다 .


행을 삭제하면 어떻게됩니까? 의지 SYS_GUID()의 ID 값도?
kittu

5

Oracle 12c부터는 다음 두 가지 방법 중 하나로 ID 열이 지원됩니다.

  1. 시퀀스 + 테이블 -이 솔루션에서는 평상시처럼 시퀀스를 생성 한 후 다음 DDL을 사용합니다.

    테이블 MyTable 만들기 (ID NUMBER DEFAULT MyTable_Seq.NEXTVAL , ...)

  2. 테이블 만 -이 솔루션에서는 시퀀스가 ​​명시 적으로 지정되지 않습니다. 다음과 같은 DDL을 사용합니다.

    CREATE TABLE MyTable (ID 번호가 ID로 생성됨 , ...)

첫 번째 방법을 사용하면 기존 방식으로 이전 버전과 호환됩니다. 두 번째는 조금 더 간단하고 나머지 RDMS 시스템과 더 일치합니다.


5

그것은이라고 Identity Columns하며이 가능합니다 에만 오라클 오라클 12C에서

CREATE TABLE identity_test_tab
(
   id            NUMBER GENERATED ALWAYS AS IDENTITY,
   description   VARCHAR2 (30)
);

Identity Columns아래 에 삽입하는 예

INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');

1 행이 생성되었습니다.

아래처럼 삽입 할 수 없습니다

INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');

1 행 오류 : ORA-32795 : 생성 된 상시 식별 열에 삽입 할 수 없습니다.

INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');

1 행 오류 : ORA-32795 : 생성 된 상시 식별 열에 삽입 할 수 없습니다.

유용한 링크


1

다음은 자동 증분에 대한 완전한 솔루션 wrt 예외 / 오류 처리입니다.이 솔루션은 이전 버전과 호환되며 특히 응용 프로그램이 프로덕션 환경 인 경우 11g 및 12c에서 작동합니다.

'TABLE_NAME'을 (를) 적절한 테이블 이름으로 바꾸십시오

--checking if table already exisits
BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE TABLE_NAME';
    EXCEPTION WHEN OTHERS THEN NULL;
END;
/

--creating table
CREATE TABLE TABLE_NAME (
       ID NUMBER(10) PRIMARY KEY NOT NULL,
       .
       .
       .
);

--checking if sequence already exists
BEGIN
    EXECUTE IMMEDIATE 'DROP SEQUENCE TABLE_NAME_SEQ';
    EXCEPTION WHEN OTHERS THEN NULL;
END;

--creating sequence
/
CREATE SEQUENCE TABLE_NAME_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 1 NOMAXVALUE NOCYCLE CACHE 2;

--granting rights as per required user group
/
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE_NAME TO USER_GROUP;

-- creating trigger
/
CREATE OR REPLACE TRIGGER TABLE_NAME_TS BEFORE INSERT OR UPDATE ON TABLE_NAME FOR EACH ROW
BEGIN    
    -- auto increment column
    SELECT TABLE_NAME_SEQ.NextVal INTO :New.ID FROM dual;

    -- You can also put some other required default data as per need of your columns, for example
    SELECT SYS_CONTEXT('USERENV', 'SESSIONID') INTO :New.SessionID FROM dual;
    SELECT SYS_CONTEXT('USERENV','SERVER_HOST') INTO :New.HostName FROM dual;
    SELECT SYS_CONTEXT('USERENV','OS_USER') INTO :New.LoginID FROM dual;    
    .
    .
    .
END;
/

0

이것이 기존 테이블과 열 (이름이 id) 에서이 작업을 수행 한 방법입니다.

UPDATE table SET id=ROWNUM;
DECLARE
  maxval NUMBER;
BEGIN
  SELECT MAX(id) INTO maxval FROM table;
  EXECUTE IMMEDIATE 'DROP SEQUENCE table_seq';
  EXECUTE IMMEDIATE 'CREATE SEQUENCE table_seq START WITH '|| TO_CHAR(TO_NUMBER(maxval)+1) ||' INCREMENT BY 1 NOMAXVALUE';
END;
CREATE TRIGGER table_trigger
  BEFORE INSERT ON table
  FOR EACH ROW
BEGIN
  :new.id := table_seq.NEXTVAL;
END;

0
FUNCTION GETUNIQUEID_2 RETURN VARCHAR2
AS
v_curr_id NUMBER;
v_inc NUMBER;
v_next_val NUMBER;
pragma autonomous_transaction;
begin 
CREATE SEQUENCE sequnce
START WITH YYMMDD0000000001
INCREMENT BY 1
NOCACHE
select sequence.nextval into v_curr_id from dual;
if(substr(v_curr_id,0,6)= to_char(sysdate,'yymmdd')) then
v_next_val := to_number(to_char(SYSDATE+1, 'yymmdd') || '0000000000');
v_inc := v_next_val - v_curr_id;
execute immediate ' alter sequence sequence increment by ' || v_inc ;
select sequence.nextval into v_curr_id from dual;
execute immediate ' alter sequence sequence increment by 1';
else
dbms_output.put_line('exception : file not found');
end if;
RETURN 'ID'||v_curr_id;
END;

0
FUNCTION UNIQUE2(
 seq IN NUMBER
) RETURN VARCHAR2
AS
 i NUMBER := seq;
 s VARCHAR2(9);
 r NUMBER(2,0);
BEGIN
  WHILE i > 0 LOOP
    r := MOD( i, 36 );
    i := ( i - r ) / 36;
    IF ( r < 10 ) THEN
      s := TO_CHAR(r) || s;
    ELSE
      s := CHR( 55 + r ) || s;
    END IF;
  END LOOP;
  RETURN 'ID'||LPAD( s, 14, '0' );
END;


-1
  create trigger t1_trigger
  before insert on AUDITLOGS
  for each row
   begin
     select t1_seq.nextval into :new.id from dual;
   end;

테이블 이름으로 테이블 이름 (AUDITLOGS)을 변경하고 new.column_name으로 new.id를 변경하면됩니다.


-2

아마도이 간단한 스크립트를 사용해보십시오.

http://www.hlavaj.sk/ai.php

결과는 다음과 같습니다

CREATE SEQUENCE TABLE_PK_SEQ; 
CREATE OR REPLACE TRIGGER TR_SEQ_TABLE BEFORE INSERT ON TABLE FOR EACH ROW 

BEGIN
SELECT TABLE_PK_SEQ.NEXTVAL
INTO :new.PK
FROM dual;
END;

3
이것이 eugnio의 답변과 어떻게 다릅니 까? 또한 select최신 Oracle 버전이 필요하지 않습니다 . 간단히 사용할 수 있습니다:new.pk := TABLE_PK_SEQ.NEXTVAL
a_horse_with_no_name
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.