2013-11-22 4 views
2

Я относительно новичок в Oracle и последние несколько часов просматриваю веб-страницы и до сих пор не могу найти окончательного ответа на вопрос, который меня прослушивал.Auto increment alternatives in oracle DB

Я нахожусь на фоне программного обеспечения, и количество повторений кода, которое я делаю, создавая последовательности ИИ для каждой таблицы, расстраивает меня. Есть ли в любом случае я могу определить функцию ИИ, которая принимает имя последовательности и таблицы, чтобы я мог просто вызвать функцию в моем триггере или мне нужно жестко кодировать каждую последовательность?

Я в настоящее время есть последовательность, как это для каждого из 12 таблиц, у меня есть

CREATE OR REPLACE TRIGGER trg_site_addr 
BEFORE INSERT OR UPDATE ON site_addr FOR EACH ROW 
BEGIN 
IF INSERTING THEN 
    IF :NEW.site_addr_id IS NULL THEN 
     SELECT seq_site_addr_id.nextval 
     INTO :NEW.site_addr_id 
     FROM sys.dual; 
    END IF; 
END IF; 
END; 

В идеале я хотел бы быть в состоянии сделать следующее

CREATE OR REPLACE TRIGGER trg_site_addr 
BEFORE INSERT OR UPDATE ON site_addr FOR EACH ROW 
BEGIN 
IF INSERTING THEN 
    IF :NEW.site_addr_id IS NULL THEN 
     -- Param 1 = sequence name, Parm 2 = table name 
     auto_increment(seq_site_addr_id, site_addr); 
    END IF; 
END IF; 
END; 

Как бы я идти о выполнении это, любой указатель будет очень признателен.

Alex.

* EDIT * Чтобы прояснить путаницу, я хотел бы создать функцию, но я не знаю, если это возможно, чтобы встроить последовательность внутри функции и затем использовать параметры, т.е.

CREATE FUNCTION auto_increment(seq_name, table_col_id) 
     SELECT seq_name.nextval 
     INTO :NEW.table_col_id 
     FROM sys.dual; 
END; 

Таким образом, он будет динамически создавать последовательности инкремента в триггере для каждой таблицы без необходимости жесткого кодирования триггера AI на каждой таблице.

Если это невозможно, то жесткое кодирование не имеет большого значения, это был просто запрос, который у меня был.

+1

Вы пробовали настоящую «ПОСЛЕДОВАТЕЛЬНОСТЬ»? См. Http://stackoverflow.com/questions/7681122/oracle-modify-an-existing-table-to-auto-increment-a-column и http://docs.oracle.com/cd/B28359_01/server.111. /b28286/statements_6015.htm#SQLRF01314 – admdrew

+0

Итак, вы хотите создать что-то вроде цикла for? –

+0

обновление вопрос реальный быстрый. – Alex

ответ

1

Альтернативный подход будет иметь таблицу для хранения других идентификаторов таблиц.
Как:
identification holder

Для любой таблицы приложения (например, таблицы клиентов) нам нужно будет сделать некоторые вещи, как это:

insert into ID_Table (table_name, current_id) values ('CUSTOMER', 0); 

Функция для извлечения нового идентификатора будет:

CREATE OR REPLACE FUNCTION fetch_new_id(p_table_name Varchar2) return number 
IS 
    result_value number; 
BEGIN  
     SELECT ID_Tbale.current_id + 1 
     INTO result_value 
     FROM ID_Table where trim(upper(ID_Table.table_name)) = trim(upper(p_table_name)) 
     for update; 

     UPDATE ID_Tbale set current_id = current_id + 1 
     where trim(upper(ID_Table.table_name)) = trim(upper(p_table_name)); 

     COMMIT; 

     RETURN result_value ; 
     -- exception handling, etc 
END; 
+0

Если вы идете по этому маршруту, я думаю, что использовать одно обновление с помощью 'RETURNING': 'update id_table set current_id = current_id + 1, где table_name = p_table_name возвращает current_id в result_value' – gpeche

+0

@gpeche Я использовал' для обновления', намеренно поддерживать параллелизм и предотвращать потерянные обновления. –

+0

@Moshen Yedari Я знаю, я считаю, что это чище, если вы делаете все это в одном «UPDATE ... RETURNING ...», который также поддерживает параллелизм и предотвращает потерянные обновления благодаря единственному запросу SQL. – gpeche

1

Я не рекомендую его, но что-то, как это должно сделать более или менее то, что вы хотите:

CREATE FUNCTION auto_increment(seq_name in varchar2) RETURN NUMBER IS 
    next_seq number; 
BEGIN 
    -- WARNING: use with care, possible SQL injections? 
    execute immediate 'select ' || seq_name || '.nextval from dual' into next_seq; 
    return next_seq 
END auto_increment; 

-- In trigger code 
... 
if inserting then 
    if :new.id is null then 
    :new.id := auto_increment('myseq'); 
    end if; 
end if; 
... 

Лучший способ будет просто встроить вызов последовательности в INSERT заявлении. Я бы использовал триггеры, если операторы INSERT не могут быть изменены (возможно, они являются частью некоторого стороннего программного обеспечения, предполагающего, что каждая БД в мире поддерживает колонки автоинкремента).