Dường như không có khái niệm về AUTO_INCREMENT trong Oracle, cho đến và bao gồm cả phiên bản 11g.
Làm cách nào tôi có thể tạo một cột hoạt động như tăng tự động trong Oracle 11g?
Dường như không có khái niệm về AUTO_INCREMENT trong Oracle, cho đến và bao gồm cả phiên bản 11g.
Làm cách nào tôi có thể tạo một cột hoạt động như tăng tự động trong Oracle 11g?
Câu trả lời:
Không có thứ gọi là cột "auto_increment" hay "nhận dạng" trong Oracle kể từ Oracle 11g . Tuy nhiên, bạn có thể mô hình hóa nó dễ dàng với trình tự và trình kích hoạt:
Bảng định nghĩa:
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;
Định nghĩa kích hoạt:
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
cột hiện có sẵn trên Oracle 12c:
create table t1 (
c1 NUMBER GENERATED by default on null as IDENTITY,
c2 VARCHAR2(10)
);
hoặc chỉ định các giá trị bắt đầu và gia tăng, cũng ngăn chặn mọi chèn vào cột định danh ( GENERATED ALWAYS
) (một lần nữa, chỉ Oracle 12c +)
create table t1 (
c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
c2 VARCHAR2(10)
);
Ngoài ra, Oracle 12 cũng cho phép sử dụng một chuỗi làm giá trị mặc định:
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));
dept_seq
đến từ đâu!
SELECT .. INTO
trong kích hoạt bạn có thể làm :new.id := dept_seq.NEXTVAL;
.
SYS_GUID
trả về một GUID-- một ID duy nhất trên toàn cầu. A SYS_GUID
là một RAW(16)
. Nó không tạo ra một giá trị số tăng dần.
Nếu bạn muốn tạo một khóa số tăng dần, bạn sẽ muốn tạo một chuỗi.
CREATE SEQUENCE name_of_sequence
START WITH 1
INCREMENT BY 1
CACHE 100;
Sau đó, bạn sẽ sử dụng trình tự đó trong INSERT
tuyên bố của mình
INSERT INTO name_of_table( primary_key_column, <<other columns>> )
VALUES( name_of_sequence.nextval, <<other values>> );
Hoặc bạn có thể xác định một trình kích hoạt tự động điền giá trị khóa chính bằng chuỗi
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;
Nếu bạn đang sử dụng Oracle 11.1 trở lên, bạn có thể đơn giản hóa trình kích hoạt một chút
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
:new.primary_key_column := name_of_sequence.nextval;
END;
Nếu bạn thực sự muốn sử dụng SYS_GUID
CREATE TABLE table_name (
primary_key_column raw(16) default sys_guid() primary key,
<<other columns>>
)
CACHE 100; in CREATE SEQUENCE name_of_sequence START WITH 1 INCREMENT BY 1 CACHE 100;
làm gì?
SYS_GUID()
là a RAW(16)
, không phải 32.
SYS_GUID
tài liệu tuyên bố raw(32)
làm tôi bối rối.
Trong Oracle 12c trở đi, bạn có thể làm một cái gì đó như,
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)
);
Và trong Oracle (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;
/
IDENTITY
ví dụ này rõ ràng hơn nhiều trong câu trả lời này.
WHEN (new.MAP_ID IS NULL)
có trong câu trả lời được chấp nhận. Nâng cao.
WHEN ( new.MAP_ID is null)
không phải là một mã tốt trong trường hợp này và đã được giải thích trong phần bình luận bởi @ABCade dưới câu trả lời được chấp nhận .. hãy đọc;)
CREATE OR REPLACE TRIGGER
đến END;
, tôi nhận được một cửa sổ "Enter Binds". Nếu tôi nhấp vào "Áp dụng" và không làm gì khác trong cửa sổ đó, rồi chạy ALTER TRIGGER
lệnh, tất cả đều tốt, nhưng ước gì có một cách lập trình để thoát khỏi cửa sổ bật lên đó và chạy mọi thứ cùng nhau. Nếu bạn thử nó hoàn toàn, bạn sẽ nhận được PLS-00103: Encountered the symbol 'ALTER'
và nó cũng không thích EXECUTE IMMEDIATE
(lỗi tương tự, chỉ nói Encountered the symbol 'EXECUTE'
thay thế).
[42000][907] ORA-00907: missing right parenthesis
khi chạy phiên bản cho Oracle 12c trở đi. Bất kỳ ý tưởng ?
Đây là ba hương vị:
RAW
kiểu dữ liệu.x
là cột danh tính. Thay thế FOO
với tên bảng của bạn trong mỗi ví dụ.
-- 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;
/
cập nhật:
Oracle 12c giới thiệu hai biến thể không phụ thuộc vào trình kích hoạt:
create table mytable(id number default mysequence.nextval);
create table mytable(id number generated as identity);
Cái đầu tiên sử dụng một chuỗi theo cách truyền thống; thứ hai quản lý giá trị trong nội bộ.
Giả sử bạn có nghĩa là một cột như cột nhận dạng SQL Server?
Trong Oracle, bạn sử dụng SEQUENCE để đạt được chức năng tương tự. Tôi sẽ xem nếu tôi có thể tìm thấy một liên kết tốt và đăng nó ở đây.
Cập nhật: có vẻ như bạn đã tìm thấy nó cho mình. Dù sao đây cũng là liên kết: http://www.techonthenet.com/oracle/ Hậuences.php
Cơ sở dữ liệu Oracle 12c đã giới thiệu Danh tính, một cột tự động gia tăng (do hệ thống tạo). Trong các phiên bản cơ sở dữ liệu trước đó (cho đến 11g), bạn thường triển khai Danh tính bằng cách tạo Trình tự và Kích hoạt. Từ 12c trở đi, bạn có thể tạo Bảng của riêng mình và xác định cột phải được tạo dưới dạng Danh tính.
Bài viết sau đây giải thích cách sử dụng nó:
Trigger
và Sequence
có thể được sử dụng khi bạn muốn số sê-ri mà bất kỳ ai cũng có thể dễ dàng đọc / ghi nhớ / hiểu. Nhưng nếu bạn không muốn quản lý Cột ID (như emp_id) bằng cách này và giá trị của cột này không đáng kể, bạn có thể sử dụng SYS_GUID()
tại Tạo bảng để nhận Tự động tăng như thế này.
CREATE TABLE <table_name>
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));
Bây giờ emp_id
cột của bạn sẽ chấp nhận "giá trị định danh duy nhất toàn cầu". bạn có thể chèn giá trị vào bảng bằng cách bỏ qua cột emp_id như thế này.
INSERT INTO <table_name> (name) VALUES ('name value');
Vì vậy, nó sẽ chèn giá trị duy nhất vào emp_id
Cột của bạn .
SYS_GUID()
giá trị id của nó không?
Bắt đầu với Oracle 12c, có hỗ trợ cho các cột Danh tính theo một trong hai cách:
Trình tự + Bảng - Trong giải pháp này, bạn vẫn tạo một chuỗi như bình thường, sau đó bạn sử dụng DDL sau:
TẠO BẢNG MyTable (ID SỐ DEFAULT MyTable_Seq.NEXTVAL , ...)
Chỉ bảng - Trong giải pháp này không có trình tự được chỉ định rõ ràng. Bạn sẽ sử dụng DDL sau:
TẠO BẢNG MyTable (SỐ ID TẠO NHƯ NHẬN , ...)
Nếu bạn sử dụng cách đầu tiên thì nó tương thích ngược với cách làm hiện tại. Thứ hai là đơn giản hơn một chút và trực tuyến hơn với các hệ thống RDMS còn lại ngoài kia.
nó được gọi là Identity Columns
và nó chỉ có sẵn từ oracle Oracle 12c
CREATE TABLE identity_test_tab
(
id NUMBER GENERATED ALWAYS AS IDENTITY,
description VARCHAR2 (30)
);
ví dụ về chèn vào Identity Columns
như dưới đây
INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');
Đã tạo 1 hàng.
bạn KHÔNG thể chèn như dưới đây
INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');
LRI ở dòng 1: ORA-32795: không thể chèn vào cột nhận dạng luôn được tạo
INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');
LRI ở dòng 1: ORA-32795: không thể chèn vào cột nhận dạng luôn được tạo
Dưới đây là giải pháp hoàn thành xử lý ngoại lệ / lỗi wrt để tăng tự động, giải pháp này tương thích ngược và sẽ hoạt động trên 11g & 12c, đặc biệt nếu ứng dụng đang được sản xuất.
Vui lòng thay thế 'TABLE_NAME' bằng tên bảng thích hợp của bạ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;
/
Đây là cách tôi đã làm điều này trên một bảng và cột hiện có (tên 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;
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;
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;
oracle có trình tự VÀ cột nhận dạng trong 12c
http://www.oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1.php#identity-columns
Tôi đã tìm thấy cái này nhưng không chắc rdb 7 là gì http://www.oracle.com/technetwork/products/rdb/0307-identity-columns-128126.pdf
create trigger t1_trigger
before insert on AUDITLOGS
for each row
begin
select t1_seq.nextval into :new.id from dual;
end;
chỉ tôi phải thay đổi tên bảng (AUDITLOGS) bằng tên bảng của bạn và new.id với new.column_name
Có lẽ chỉ cần thử kịch bản đơn giản này:
Kết quả là:
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;
select
phiên bản Oracle hiện đại. Bạn chỉ có thể sử dụng:new.pk := TABLE_PK_SEQ.NEXTVAL
BEFORE INSERT
kích hoạt trên bảng và kéo các giá trị ra khỏi chuỗi để tạo tăng tự động