我正在运行 Oracle 11g RAC。
我的桌子上有一个FOR EACH ROW BEFORE INSERT
触发器,用于填充CREATED_DATE (DATE)
using sysdate
。
数据类型有什么粒度DATE
?当通过这样的触发器填充时,RAC 中的两行是否有可能具有完全相同的INSERT
日期/时间?
即使没有 RAC,也很容易实现。
17:25:47 (455)SYSTEM@dwal> create table t (k int primary key, d date);
Table created.
Elapsed: 00:00:00.35
17:32:00 (455)SYSTEM@dwal> ed
Wrote file S:\spool\dwal\BUF_SYSTEM_455.sql
1 create trigger t_bi before insert on t for each row
2 begin
3 :new.d := sysdate;
4* end;
17:32:04 (455)SYSTEM@dwal> /
Trigger created.
Elapsed: 00:00:00.10
17:32:04 (455)SYSTEM@dwal> insert into t(k) select rownum from dual connect by rownum <= 1e3;
1000 rows created.
Elapsed: 00:00:00.02
17:32:30 (455)SYSTEM@dwal> select d, count(*) from t group by d;
D COUNT(*)
------------------- ----------
18.09.2013 17:32:37 1000
Elapsed: 00:00:00.01
DATE 类型的粒度为秒,如果您想要更粒度的内容,您可能需要使用 TIMESTAMP:
17:34:51 (455)SYSTEM@dwal> alter table t add (ts timestamp);
Table altered.
Elapsed: 00:00:00.17
17:36:01 (455)SYSTEM@dwal> ed
Wrote file S:\spool\dwal\BUF_SYSTEM_455.sql
1 create or replace trigger t_bi before insert on t for each row
2 begin
3 :new.d := sysdate;
4 :new.ts := systimestamp;
5* end;
17:36:05 (455)SYSTEM@dwal> /
Trigger created.
Elapsed: 00:00:00.13
17:36:05 (455)SYSTEM@dwal> insert into t(k) select rownum from dual connect by rownum <= 1e3;
1000 rows created.
Elapsed: 00:00:00.12
17:36:47 (455)SYSTEM@dwal> select d, min(ts) mn, max(ts) mx, count(*) from t group by d;
D MN MX COUNT(*)
------------------- ------------------------------ ------------------------------ ----------
18.09.2013 17:36:19 18-SEP-13 05.36.19.481071 PM 18-SEP-13 05.36.19.593846 PM 1000
Elapsed: 00:00:00.02
从手册:
对于每个 DATE 值,Oracle 存储以下信息:年、月、日、小时、分钟和秒
因此,如果两个插入发生在同一秒内,那么是的,这些列可以具有相同的值。
如果您需要更细粒度的时间信息,您应该使用一TIMESTAMP
列,该列还可以存储最多 9 位的小数秒。但是在高流量系统上,我认为仍然可能发生两个插入在同一毫秒内发生
在 SQL 语句中引用 sysdate 时,仅使用一个 sysdate 值。
因此,如果您执行了 1,000,000 条记录的插入,其中包括将 sysdate 分配给 CREATED_AT 列,并且插入花费了 15 分钟,那么所有 1,000,000 条记录将具有相同的 CREATED_AT 值。
但是,当 CREATED_AT 的值由触发器填充时,我相信每次触发器执行都会重新评估其值。AskTom 对此进行了讨论。其中一个结论是,当您需要在从 SQL 调用的函数中使用 SYSDATE 时,如果时间很关键,可能需要从 SQL 语句中传入 SYSDATE 的值,因为长时间运行的语句或过程可能是引用 SYSDATE 的多个值。
我相信这同样适用于 TIMESTAMP 值。
因此,您不能依赖 created_at 列来提供唯一性。这是应该通过序列生成值来实现的。