16 ответов:
в Oracle нет таких столбцов, как" auto_increment "или" identity"по состоянию на Oracle 11g. Однако вы можете легко смоделировать его с помощью последовательности и триггера:
таблицы определения:
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) );
SYS_GUIDвозвращает идентификатор GUID-уникальный идентификатор. А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_GUIDCREATE TABLE table_name ( primary_key_column raw(16) default sys_guid() primary key, <<other columns>> )
в 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) );
и в Oracle (до 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; /
здесь представлены тремя вкусами:
- цифровой. Простое увеличение числового значения, например 1,2,3,....
- GUID. глобальный универсальный идентификатор, как
RAWтип данных.- GUID (строка). То же, что и выше, но в виде строки, которая может быть проще обрабатывать на некоторых языках.
x- это столбец идентификаторов. Заменить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);первый использует последовательность традиционным способом; второй управляет значением внутренне.
предполагая, что вы имеете в виду столбец, подобный столбцу идентификаторов SQL Server?
в Oracle вы используете последовательность для достижения той же функциональности. Я посмотрю, смогу ли я найти хорошую ссылку и опубликовать ее здесь.
обновление: похоже, вы нашли его сами. Здесь ссылка : http://www.techonthenet.com/oracle/sequences.php
Oracle Database 12c представила идентификатор, автоматически инкрементный (системный) столбец. В предыдущих версиях базы данных (до 11g) вы обычно реализуете идентификатор, создавая последовательность и триггер. Начиная с 12c, вы можете создать свою собственную таблицу и определить столбец, который должен быть сгенерирован как идентификатор.
в следующей статье объясняется, как его использовать:
столбцы идентификаторов-новая запись в базе данных Oracle 12c
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');таким образом, он будет вставлять уникальное значение для вашего
начиная с Oracle 12c существует поддержка столбцов идентификаторов одним из двух способов:
Последовательность + Стол - в этом решении вы все еще создаете последовательность, как обычно, а затем используете следующий DDL:
создать таблицу MyTable (ИДЕНТИФИКАЦИОННЫЙ НОМЕР по умолчанию MyTable_Seq.NEXTVAL, ...)
Таблица Только - в этом решении явно не указана последовательность. Вы бы использовали следующий DDL:
создать таблицу MyTable (ID NUMBER ГЕНЕРИРУЕТСЯ КАК IDENTITY, ...)
Если вы используете первый способ, он обратно совместим с существующим способом делать вещи. Второй немного более простой и более встроенный с остальными системами RDMS там.
это называется
Identity Columnsи он доступен только от oracle Oracle 12cCREATE 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: не удается вставить в всегда генерируется столбец идентификаторов
вот полное решение W.R. T исключение/обработка ошибок для автоматического увеличения, это решение обратно совместимо и будет работать на 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; /
oracle имеет последовательности и столбцы идентификаторов в 12c
http://www.oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1.php#identity-columns
Я нашел это, но не уверен, что такое rdb 7 http://www.oracle.com/technetwork/products/rdb/0307-identity-columns-128126.pdf
вот как я сделал это на существующей таблице и столбце (с именем 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;
create trigger t1_trigger before insert on AUDITLOGS for each row begin select t1_seq.nextval into :new.id from dual; end;только мне нужно просто изменить имя таблицы (AUDITLOGS) с вашим именем таблицы и new.id с новым.аргумент column_name
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;
может быть, просто попробуйте этот простой скрипт:
результат:
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;
Comments