2013-06-19 2 views
0

Я делаю операцию вставки и удаления в таблице в одной транзакции. У меня есть триггер в этой таблице, который обновляет журнал. В журнале есть первичный ключ как sequenceId, который всегда получает увеличивается при вставке. Сначала я удаляю, а затем вставляю в транзакцию.Разная временная метка для разных запросов DML в одной транзакции в оракуле

У меня есть два вопроса:

  • Отметка времени в журнале для вставки и удаления в настоящее время то же самое. Могу ли я заставить его быть другим.
  • Порядок работы (вставка/удаление) в журнале меняется на обратный. Он показывает операцию удаления после операции вставки (в соответствии с sequenceId). Как я могу гарантировать, что порядок согласован в журнале (вставить после удаления).

Пример:

create table address (ID number, COUNTRY char(2)); 

create table address_log(SEQ_ID number, ID number, COUNTRY char(2), DML_TYPE char(1), CHANGE_DATE timestamp(6)); 

create sequence seq_id start with 1 increment by 100 nominvalue nomaxvalue cache 20 noorder; 

create or replace trigger trg_add 
before insert or delete on address 
FOR EACH ROW 
BEGIN 
if inserting then 
    insert into address_log values(SEQ_ID.nextval, :new.ID, :new.COUNTRY, 'I', sysdate); 
else 
    insert into address_log values(SEQ_ID.nextval, :old.ID, :old.COUNTRY, 'D', sysdate); 
end if; 
end; 

insert into address values(1,'US'); 
insert into address values(2,'CA'); 
delete from address where id = 1; 
insert into address values(3,'UK'); 
delete from address where id = 3; 

, если я совершить последние DML запросов в одной транзакции, то я должен видеть тот же порядок в address_log.

+0

@ wolφi Я использую первичный ключ sequenceId журнала, чтобы определить его. Он всегда получает incremented.Also обновленный вопрос. – rajsekhar

+0

Спасибо за примеры кода. Итак, оба вопроса были решены с помощью ответа Винсента, не так ли? (Подсказка: если вы его примете, то и Винсент, и вы получите несколько очков ...) –

ответ

3

Каков тип данных вашей временной метки?

Если вы используете TIMESTAMP с достаточной точностью, заказ должен быть сохранен.

Например TIMESTAMP(6) (точность в микро-секунду) - что точность по умолчанию:

SQL> CREATE TABLE t_data (ID NUMBER, d VARCHAR2(30)); 

Table created 

SQL> CREATE TABLE t_log (ts TIMESTAMP (6), ID NUMBER, action VARCHAR2(1)); 

Table created 

SQL> CREATE OR REPLACE TRIGGER trg 
    2  BEFORE INSERT ON t_data 
    3  FOR EACH ROW 
    4 BEGIN 
    5  INSERT INTO t_log VALUES (systimestamp, :NEW.id, 'I'); 
    6 END; 
    7/

Trigger created 

SQL> INSERT INTO t_data (SELECT ROWNUM, 'x' FROM dual CONNECT BY LEVEL <= 10); 

10 rows inserted 

SQL> SELECT * FROM t_log ORDER BY ts; 

TS         ID ACTION 
----------------------------- ---------- ------ 
19/06/13 15:47:51,686192    1 I 
19/06/13 15:47:51,686481    2 I 
19/06/13 15:47:51,686595    3 I 
19/06/13 15:47:51,686699    4 I 
19/06/13 15:47:51,686800    5 I 
19/06/13 15:47:51,686901    6 I 
... 

В любом случае, если вы действительно хотите, чтобы различать одновременные события (параллельные вставки, например), вы всегда можете использовать последовательность в дополнении, с ORDER ключевым словом, чтобы гарантировать, что строки будут упорядочены:

CREATE SEQUENCE log_sequence ORDER 

Это будет позволяют иметь надежный порядок сортировки, даже если события происходили одновременно.

+0

Тип метки времени - TIMESTAMP (6). Вставка и удаление происходит в одном и том же коммитах, и оба имеют одну и ту же метку времени. – rajsekhar

+0

@rajsekhar Как вы можете видеть в моем примере, 'SYSTIMESTAMP' не определяется в момент фиксации, но во время вставки. Маловероятно, что триггер всегда будет выполняться с той же точностью, что и микросекунда. Измените свой вопрос на примере, воспроизводящем описанное поведение. С помощью операторов создания, кода запуска, инструкции insert и оператора select. –

+1

Я предполагаю, что использование SYSDATE вместо SYSTIMESTAMP делает разницу – rajsekhar