Oracle:生成一个数字序列,其值以某个数字开头
Posted
技术标签:
【中文标题】Oracle:生成一个数字序列,其值以某个数字开头【英文标题】:Oracle: generate a numeric sequence whose values start with a certain digit 【发布时间】:2020-08-28 10:52:56 【问题描述】:我需要在 Oracle 中为我的表的列定义一个数字序列。 我得到的唯一约束要求所有值都以 9 开头。 因此,自动生成的值列表应如下所示:
9、90、91、92...99、900、901...999、9000、9001...9999、90000、...
您知道如何通过 SQL(通过适时创建和按顺序编辑)和/或 Java 代码来解决这个问题吗? 在我在网上阅读的一些帖子中,人们建议以这种方式修改序列:
ALTER SEQUENCE gokhan.sample_seq INCREMENT BY -500;
SELECT gokhan.sample_seq.NEXTVAL FROM dual;
ALTER SEQUENCE gokhan.sample_seq INCREMENT BY 1;
这需要每次都计算新的增量。如果可能的话,我想写一段 SQL 代码来自动化这个过程。
感谢支持。
【问题讨论】:
这听起来像是一个家庭作业。还有哪些额外的限制? 你不能只使用一个序列并添加一个 9 作为第一个数字吗?像 CONCAT('9',sequence.nextval)? 遗憾的是,这不是一个练习,但幸运的是没有其他限制。关于您的提示,是否可以将字符串与数值连接并将结果保存到数值列中? 【参考方案1】:如果你想在 java 中实现它,我看到的唯一困难是计算给定数字的下一个值。但幸运的是,您的边界是十的幂(10、100、1000 ...),否则您会增加一。像下面这样的东西应该给你一个初步的方法
public class Test
//A method to check if a given number is a power of ten :
public static boolean powerOf10(int n)
int max_power10 = 1_000_000_000;
if (n > max_power10 ) return false;
int i = 1;
while (i < n) i *= 10;
return i == n;
//Then you can calculate the next value by either adding one or
//adding one and multipling by 9 if last value plus one is a power of ten
public static int nextVal(int lastVal)
if(!powerOf10(lastVal + 1))
return lastVal + 1;
return 9 * (lastVal + 1);
//Note: for the sake of readability i omitted the check if the last value is a valid value (a number starting with 9)
//Demo
public static void main(String[] args)
int MIN_VALUE = 9;
for(int i = MIN_VALUE; i < 10000; i = nextVal(i))
System.out.println(i);
【讨论】:
感谢您的回答,这或多或少是我在 Java 方面的想法。您将如何处理数据库序列?【参考方案2】:使用普通序列 0,1,2,3,... 并且对于从此序列中检索到的任何 x,直接计算您的花哨序列的映射元素。
当序列的初始值为0时,元素1-10映射到90-99,元素11-110映射到900-999,元素111-1110映射到9000-9999等等。因此对于每个x输入序列(例如 500)的 em> 找到区间的下限(111),计算下限的对等点(900)并计算对等点的偏移量(9389)。
代码:
with sequence (x) as (
select level - 1 from dual connect by level < 1001
), o (x,ones) as (
select x, case x when 0 then 0 else to_number(rpad('1',to_char(1 + trunc(log(10,x))),'1')) end as ones
from sequence
), m (x,ones,min) as (
select x, ones, case when x >= ones then ones else (ones - 1) / 10 end as min
from o
)
select x, case x when 0 then 9 else x - min + 9 * power(10, 1 + trunc(log(10,min))) end as result from m;
翻译成 PLSQL 由您决定。请注意,将9
连接到正常序列的数字的建议不会产生所需的结果,因为这样的序列会增长 10/9 倍(在 9,90,900,... 元素之后,数字的数量会增加 1,而在你的序列中在 10,100,1000,... 个元素之后,位数增加 1)。不过会简单很多。尽管您没有描述这种逻辑的原因,但我还是会考虑用更简单的逻辑替换。
【讨论】:
以上是关于Oracle:生成一个数字序列,其值以某个数字开头的主要内容,如果未能解决你的问题,请参考以下文章