我有一个varchar(50)行,它有一个唯一约束,我想得到一个新插入的下一个唯一编号但是有一个给定的前缀.
我的行看起来像这样:
ID (varchar)
00010001
00010002
00010003
00080001
Run Code Online (Sandbox Code Playgroud)
因此,如果我想从前缀"0001"获得下一个unqiue号码,那么它将是"00010004",但如果我希望它为前缀"0008",那么它将是"00080002".
此表中将有超过1百万个条目.有没有办法让Oracle 11执行相当快的这种操作?
我知道这个设置完全是疯了但这是我必须要处理的.我不能创建任何新表等.
您可以搜索指定前缀的最大值并将其递增:
SQL> WITH DATA AS (
2 SELECT '00010001' id FROM DUAL UNION ALL
3 SELECT '00010002' id FROM DUAL UNION ALL
4 SELECT '00010003' id FROM DUAL UNION ALL
5 SELECT '00080001' id FROM DUAL
6 )
7 SELECT :prefix || to_char(MAX(to_number(substr(id, 5)))+1, 'fm0000') nextval
8 FROM DATA
9 WHERE ID LIKE :prefix || '%';
NEXTVAL
---------
00010004
Run Code Online (Sandbox Code Playgroud)
我相信你知道这是一种生成主键的低效方法.此外,它不会在多用户环境中很好地发挥作用,因此不会扩展.并发插入将等待然后失败,因为列上有UNIQUE约束.
如果前缀总是相同的长度,您可以稍微减少工作量:您可以创建一个专门的索引,以最少的步骤找到最大值:
CREATE INDEX ix_fetch_max ON your_table (substr(id, 1, 4),
substr(id, 5) DESC);
Run Code Online (Sandbox Code Playgroud)
然后,以下查询可以使用索引,并将在检索到的第一行停止:
SELECT id
FROM (SELECT substr(id, 1, 4) || substr(id, 5) id
FROM your_table
WHERE substr(id, 1, 4) = :prefix
ORDER BY substr(id, 5) DESC)
WHERE rownum = 1
Run Code Online (Sandbox Code Playgroud)
如果您需要使用相同的前缀进行同时插入,我建议您使用DBMS_LOCK请求对指定的锁定newID.如果由于某人已插入此值而导致调用失败,请尝试使用newID+1.虽然这涉及比传统序列更多的工作,但至少您的插入不会彼此等待(可能导致死锁).
| 归档时间: |
|
| 查看次数: |
631 次 |
| 最近记录: |