0

我正在运行 Oracle 11g RAC。

我的桌子上有一个FOR EACH ROW BEFORE INSERT触发器,用于填充CREATED_DATE (DATE)using sysdate

数据类型有什么粒度DATE?当通过这样的触发器填充时,RAC 中的两行是否有可能具有完全相同的INSERT日期/时间?

4

3 回答 3

4

即使没有 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
于 2013-09-18T09:37:49.810 回答
1

从手册

对于每个 DATE 值,Oracle 存储以下信息:年、月、日、小时、分钟和秒

因此,如果两个插入发生在同一秒内,那么是的,这些列可以具有相同的值。

如果您需要更细粒度的时间信息,您应该使用一TIMESTAMP列,该列还可以存储最多 9 位的小数秒。但是在高流量系统上,我认为仍然可能发生两个插入在同一毫秒内发生

于 2013-09-18T09:36:45.257 回答
1

在 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 列来提供唯一性。这是应该通过序列生成值来实现的。

于 2013-09-18T11:15:52.193 回答