Oracle'da AUTO_INCREMENT ile kimlik nasıl oluşturulur?


422

Görünüşe göre Oracle'da 11g sürümüne kadar olan AUTO_INCREMENT konsepti yok.

Oracle 11g'de otomatik artış gibi davranan bir sütunu nasıl oluşturabilirim?


3
BEFORE INSERTOtomatik artış oluşturmak için masada bir tetikleyici oluşturabilir ve değerleri bir diziden çıkarabilirsiniz
Hunter McMillen

7
Kimlik sütunları artık Oracle 12c'de
David Aldridge


Oracle RAC kullanıyor musunuz? İfadenin sonunda CACHED kullanılması performansı artırabilir. Kısa bir süre içinde çok fazla kesici uç yapıyorsanız (ve sipariş sizin için önemli değilse), ek performans avantajları için aşamalı dizi kesici uç tetikleyicisini düşünün. Bakınız: dba-oracle.com/t_rac_proper_sequence_usage.htm
Peeter Kokk

Yanıtlar:


596

"AUTO_INCREMENT" Oracle'da "kimlik" sütunlarında diye bir şey yoktur , Oracle 11g itibariyle . Ancak, bir dizi ve bir tetikleyici ile kolayca modelleyebilirsiniz:

Tablo tanımı:

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;

Tetikleyici tanımı:

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

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

GÜNCELLEME:

IDENTITY sütunu artık Oracle 12c'de kullanılabilir:

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

veya başlangıç ​​ve artış değerlerini GENERATED ALWAYSbelirterek kimlik sütununa ekleme yapılmasını da önler ( ) (yine yalnızca Oracle 12c +)

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

Alternatif olarak, Oracle 12 ayrıca bir dizinin varsayılan değer olarak kullanılmasına izin verir:

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
Ben bir n00b, lütfen bana nereden dept_seqgeldiğini söyleyebilir misin !
J86

3
CREATE SEQUENCE Instagram Hesabındaki Resim ve Videoları dept_seq; dept_seq oluşturur ... bir tablo gibi .. ama bu durumda dept_seq.NEXTVAL ile artırabileceğiniz tek sayı ... tetiğe bakın.
Benjamin Eckstein

Belirtildiği gibi, orijinal kod belirtilen kimliğe sahip bir satırla karşılaştığında başarısız olur. Ancak bu duruma ne dersiniz: Tetikleyici kimliği (otomatik olarak) yalnızca INSERT içinde açıkça belirtilmiş bir kimlik yoksa atayacaktır. Bu başarısız olur, değil mi? Ve bunu yapmanın uygun yolu nedir?
FanaticD

10
Benim gibi kehanet yeni başlayanlar için, "new.id" in "id" kısmı, yukarıdaki tabloda "id" sütununa karşılık gelir. 'yeni', oluşturulan yeni satıra atıfta bulunan ayrılmış bir kelimedir
Hoppe

2
Sadece yapabileceğiniz SELECT .. INTOtetikleyicide kullanmanıza gerek yoktur :new.id := dept_seq.NEXTVAL;.
MT0

90

SYS_GUIDbir GUID döndürür - global olarak benzersiz bir kimlik. A SYS_GUIDbir RAW(16). Artan bir sayısal değer oluşturmaz.

Artan bir sayısal anahtar oluşturmak istiyorsanız, bir sıra oluşturmak istersiniz.

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

Daha sonra ya bu diziyi kullanmak istiyorsunuz INSERTaçıklamada

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

Veya diziyi kullanarak birincil anahtar değerini otomatik olarak dolduran bir tetikleyici tanımlayabilirsiniz

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 veya üstünü kullanıyorsanız, tetikleyiciyi biraz basitleştirebilirsiniz.

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

Gerçekten kullanmak istiyorsan SYS_GUID

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

1
Ne yapar CACHE 100; in CREATE SEQUENCE name_of_sequence START WITH 1 INCREMENT BY 1 CACHE 100;?
Angelina

3
CACHE 100: Anahtar kelime sonraki 100 sayıyı belleğe getirir. Normalde, bir SEQUENCE değeri her değiştiğinde veritabanına kaydedilir, önbelleğe alırsanız, yalnızca önbelleğe alınmışlar tükendiğinde kaydedilir ve alınır. Size önemli bir performans artışı sağlar, ancak veritabanı başarısız olursa, kullanmadığınız tüm önbelleğe alınmış değerleri kaybedersiniz.
Ramazan Polat

2
A SYS_GUID(), RAW(16)32 değil.
türbanoff

2
@turbanoff - İyi yakaladım. Cevabım güncellendi. SYS_GUIDDokümantasyon bir beyan raw(32)beni karıştı hangi.
Justin Cave

@JustinCave Yaklaşımınızı ve tetikleyiciyi oluştururken yaklaşımınızı kullandım. Bir satırı programlı olarak (java) silersem, kimlik (birincil anahtar) da ayarlanır?
kittu

52

Oracle 12c ve sonrasında,

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)
);

Ve Oracle'da (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 Ben şahsen IDENTITYörnek bu cevapta çok daha net olduğunu söylüyorum .
23:15

5
WHEN (new.MAP_ID IS NULL)Kabul edilen cevap değildir. Upvoted.
dcsohl

1
@dcsohl, WHEN ( new.MAP_ID is null)bu durumda iyi bir kod değildir ve zaten yorum bölümünde @ABCade tarafından kabul edilen cevap altında açıklanmıştır .. bir okuma var;)
ajmalmhd04

Ben bu çalıştırdığınızda CREATE OR REPLACE TRIGGERiçin END;, bir "bağlayan Enter" penceresi çıkacaktır. "Uygula" yı tıklar ve o pencerede başka bir şey yapmaz ve sonra ALTER TRIGGERkomutu çalıştırırsam , her şey yolundadır, ancak programlı olarak bu pop-up'dan kurtulmanın ve her şeyi birlikte çalıştırmanın bir yolu olsaydı. Tamamen denerseniz, alırsınız PLS-00103: Encountered the symbol 'ALTER've beğenmezsiniz EXECUTE IMMEDIATE(aynı hata, bunun Encountered the symbol 'EXECUTE'yerine söyler ).
vapcguy

[42000][907] ORA-00907: missing right parenthesisOracle 12c için sürümü çalıştırırken aldım . Herhangi bir fikir ?
belgoros

32

İşte üç lezzet:

  1. sayısal . Basit artan sayısal değer, örneğin 1,2,3, ....
  2. GUID . bir RAWveri türü olarak global olarak tek yönlü tanımlayıcı .
  3. GUID (dize) . Yukarıdaki ile aynı, ancak bazı dillerde kullanımı daha kolay olabilecek bir dize olarak.

xkimlik sütunu. Değiştirin FOOörneklerin her birinde tablo adınızı.

-- 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;
/

Güncelleme:

Oracle 12c, tetikleyicilere bağlı olmayan bu iki değişkeni sunar:

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

Birincisi geleneksel şekilde bir dizi kullanır; ikincisi değeri dahili olarak yönetir.


7

SQL Server kimlik sütunu gibi bir sütun mu demek istiyorsunuz?

Oracle'da, aynı işlevselliği elde etmek için bir SEQUENCE kullanırsınız. İyi bir bağlantı bulup bulamayacağımı göreceğim.

Güncelleme: Görünüşe göre kendiniz buldunuz. Yine de bağlantı şu şekildedir: http://www.techonthenet.com/oracle/sequences.php


7

Oracle Database 12c, otomatik artan (sistem tarafından oluşturulan) bir sütun olan Identity'yi tanıttı. Önceki veritabanı sürümlerinde (11g'ye kadar), genellikle bir Dizi ve Tetikleyici oluşturarak bir Kimlik uygularsınız. 12c'den itibaren kendi tablonuzu oluşturabilir ve bir Kimlik olarak oluşturulması gereken sütunu tanımlayabilirsiniz.

Aşağıdaki makalede bunun nasıl kullanılacağı açıklanmaktadır:

Kimlik sütunları - Oracle Database 12c'de yeni bir girdi


5
Bu bağlantı soruyu cevaplayabilse de, cevabın önemli kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir.
Köprü

5

Triggerve Sequenceherkesin kolayca okuyabileceği / hatırlayabileceği / anlayabileceği seri numara istediğinizde kullanılabilir. Ancak ID Sütunu'nu (emp_id gibi) bu şekilde yönetmek istemiyorsanız ve bu sütunun değeri çok önemli değilse, SYS_GUID()Otomatik Artış'ı bu şekilde elde etmek için Tablo Oluşturma'da kullanabilirsiniz .

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

Artık emp_idsütununuz "global olarak benzersiz tanımlayıcı değeri" kabul edecek. emp_id sütununu bu şekilde yoksayarak tabloya değer ekleyebilirsiniz.

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

Böylece, emp_idSütununuza benzersiz bir değer katacaktır.


Bir satır silindiğinde ne olur? Will SYS_GUID()onun kimliği değerleri de?
kittu

5

Oracle 12c'den başlayarak, Kimlik sütunlarını iki yoldan biriyle destekleyin:

  1. Sıra + Tablo - Bu çözümde normalde yaptığınız gibi bir sıra oluşturmaya devam edersiniz, ardından aşağıdaki DDL'yi kullanırsınız:

    TABLO OLUŞTURMA OLUŞTUR (ID NUMBER VARSAYILAN MyTable_Seq.NEXTVAL , ...)

  2. Yalnızca Tablo - Bu çözümde hiçbir sıra açıkça belirtilmez. Aşağıdaki DDL'yi kullanırsınız:

    TABLO OLUŞTURMA ( KİMLİK OLARAK ÜRETİLEN KİMLİK NUMARASI , ...)

İlk yolu kullanırsanız, mevcut iş yapma yöntemiyle geriye dönük uyumludur. İkincisi biraz daha basittir ve diğer RDMS sistemleri ile daha fazla satır içi.


5

denir Identity Columnsve yalnızca Oracle Oracle 12c'den alınabilir

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

Identity Columnsaşağıdaki gibi içine ekleme örneği

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

1 satır oluşturuldu.

aşağıdaki gibi ekleyemezsiniz

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

Satır 1'deki HATA: ORA-32795: oluşturulan her zaman kimlik sütununa eklenemiyor

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

Satır 1'deki HATA: ORA-32795: oluşturulan her zaman kimlik sütununa eklenemiyor

faydalı link


1

İşte otomatik artış için istisna / hata işleme ile komple çözüm, bu çözüm geriye dönük olarak uyumludur ve özellikle uygulama üretimde ise 11g ve 12c'de çalışacaktır.

Lütfen 'TABLE_NAME' yerine uygun tablo adınızı yazın

--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

Varolan bir tablo ve sütun (id adlı) böyle yaptım:

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;

sadece tablo adını (AUDITLOGS) tablo adınızla ve new.id ile new.column_name değiştirmeliyim


-2

Belki de şu basit komut dosyasını deneyin:

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

Sonuç:

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
Bu eugnio'nun cevabından nasıl farklı? Artı: selectmodern Oracle sürümlerinde ihtiyacınız yok . Basitçe kullanabilirsiniz:new.pk := TABLE_PK_SEQ.NEXTVAL
a_horse_with_no_name
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.