1

我需要以 yyyyMMddxxxxxx 格式生成订单号,其中 xxxxxx 是自午夜以来的订单数。

例如,20120821000004 是 2012 年 8 月 21 日的第四个订单。每秒最多可以创建 5 个订单,因此这是一个性能考虑。

一个明显的解决方案是执行以下操作来查找要增加的最新订单:

SELECT MAX (id) FROM table_name WHERE id LIKE '2012-08-21%'

但这很可能会遇到性能问题。

我探索的另一个选项是创建一个用于驱动数字组件并使用插入触发器的序列。这种方法的问题在于,您需要某种安全的方法在一天开始时将序列翻转为零,如果序列未在午夜完全重置,这可能会导致冲突/竞争条件。

我可以在这里与 Oracle 一起使用一些技巧来使其密封且高效吗?

4

5 回答 5

1

您可以为每一天生成一个新序列。给他们一个有意义的名字,比如“order_seq_20120821”。

  • 检查今天的序列是否存在
  • 如果不创建它(在这里处理并发,另一个线程可能已经创建它)
  • 然后使用它

这里不是真正的java问题,客户端无法处理数据库并发

于 2012-08-21T01:18:55.147 回答
1

如果您只打算在没有任何外部实用程序的 SQL 中执行此操作,我可能会保留两个表:

  • 绝对订单编号
  • 日期/订单偏移

第一个表将用于生成单调递增的唯一 ID 值。第二个表将用于跟踪从第一个表到每日 ID 的每日偏移量。将在当天的第一个订单上插入一行,该行将是第一个表中的日期和最高 ID。然后可以通过从第一个表中提取的新 ID 中减去第二个表中的 ID 偏移量来计算订单 ID。

您可以考虑使用整数绝对订单 ID 在内部跟踪数据库中的订单,并仅使用日期/偏移数据来动态生成日期和每日订单号的人性化信息或作为交叉引用。

于 2012-08-21T01:34:08.203 回答
0

Create an Oracle sequence for each day of the week i.e.

CREATE SEQUENCE SEQ_MON
START WITH 1
INCREMENT BY 1
ORDER;

CREATE SEQUENCE SEQ_TUE
START WITH 1
INCREMENT BY 1
ORDER;

ETC up to SEQ_SUN

Create an Oracle Stored Procedure that returns:
1. a datetime
2. a sequence number for the day of the week corresponding to above datetime

Logic as per below:
- Store current date and time in a variable
- Get day of week corresponding to date in variable.
Note: Use a formula that is independent of NLS_TERRITORY setting. You could use: 1 + TRUNC (DT) - TRUNC (DT, 'IW') to get 1 for Mon.
- Get next sequence from sequence corresponding to above day of the week
- Return the datetime in the variable and the new sequence number obtained above.

Schedule Job:
Create a scheduled job that runs at 1 a.m. (not midnight) every day to reset seq of previous day.

With the above approach, you are safe with 24X7 operations.

IMPORTANT:
The datetime returned should be used to timestamp your incoming request so that the timestamp of your request shall match the sequence number allotted to it. This is important for requests hitting just before midnight.

于 2013-04-29T15:32:11.327 回答
0

您可以创建一个从下一个订单 ID 开始的序列

CREATE SEQUENCE orders_seq
 START WITH     201208210000001
 INCREMENT BY   1
 NOCACHE
 ;

并通过作业将午夜的序列增加到第二天的第一个 id:

 declare
  v_curr_id NUMBER;
  v_inc     NUMBER;
  v_next_val NUMBER;
 begin 
  select orders_seq.nextval into v_curr_id from dual;
  v_next_val := to_number(to_char(SYSDATE+1, 'yyyymmdd') || '000000');
  v_inc := v_next_val - v_curr_id;
  execute immediate ' alter sequence orders_seq increment by ' || v_inc ;
  select orders_seq.nextval into v_curr_id from dual;
  execute immediate ' alter sequence orders_seq increment by 1';
 end;
 /
于 2012-08-21T05:47:11.033 回答
0

这不是一个专门的 Oracle 解决方案,但我正在考虑使用一个包含三列的订单号表:日期、xxxxxx(作为 int)和订单号。

保持索引(日期,xxxxxxx)。现在,查询如下:

select max(id) from OrderNumbers where date = <date>

这将使用索引并且应该加速操作。

另一个想法是保留一个类似的表格,但仅限于当前日期。在这个版本中,您将有一个序列/自动增量列自动生成 xxxxxx。然后,您可以使用触发器来计算订单号并取回插入的最后一个值以创建新的订单号。这可能是最快的方法,尤其是当您考虑锁定数据的问题时。

于 2012-08-21T01:01:46.493 回答