如何通过 PL-Sql 获取数字范围内的数字。?
Posted
技术标签:
【中文标题】如何通过 PL-Sql 获取数字范围内的数字。?【英文标题】:How to get Numbers in number range by PL-Sql .? 【发布时间】:2013-11-21 09:17:23 【问题描述】:这是我的序列表。它有超过 1000 条记录。它有开始号和结束号。但数字之间不存在。 我需要在另一个临时表中添加所有数字 [开始/之间和结束数字] 记录 按数字编号 如下所示
存在表
select concat(CARD_BULK_CODE,start_serial) startserial,concat(CARD_BULK_CODE,end_serial) endserial
from TSR_BULK_CARD_SERIALS
--------------------------
STARTSERIAL ENDSERIAL |
--------------------------
18126944 18126946 |
18141101 18141122 |
15150722 15150729 |
19069303 19069317 |
--------------------------
必填表
------------ SERIAL_NO | ------------ 18126944 18126945 18141101 18141102 …… ------------似乎它需要 pl-sql 来实现这一点。 请帮我解决这个问题
我在双重的帮助下尝试了以下查询。 但它很慢而且还没有得到结果:-) 运行超过 1 小时
select distinct concat(t.CARD_BULK_CODE,t.START_SERIAL)+level-1 SERIAL
from TSR_BULK_CARD_SERIALS t, dual
connect by level-1<=(concat(t.CARD_BULK_CODE,t.END_SERIAL ))-concat(t.CARD_BULK_CODE,t.START_SERIAL)
order by 1
编辑:
亲爱的 Alen 和 Dba。我尝试了你的,但发生了以下错误。
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (select concat(card_bulk_code, start_serial) startserial,concat(card_bulk_code, end_serial) endserial from tsr_bulk_card_serials)
LOOP
l_st := rec.startserial;
l_en := rec.endserial;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO temp(serial_no) values(rec1);
END LOOP;
END LOOP;
COMMIT;
END;
Error at line 1
ORA-01426: numeric overflow
ORA-06512: at line 9
Script Terminated on line 1.
【问题讨论】:
Oracle get numbers with range 的可能重复项 发布临时表结构解决数字溢出错误 亲爱的 psaraj12,它带有 serial_no 列 |型号 亲爱的朋友 Nicholas,我从那个帖子中得到了双 sql。但它不符合我的要求。 【参考方案1】:一种不使用 plsql 的方法
WITH ranges AS
(
SELECT CONCAT(CARD_BULK_CODE, start_serial) startserial,
CONCAT(CARD_BULK_CODE, end_serial) endserial
FROM TSR_BULK_CARD_SERIALS
),
numbers(n) AS (
SELECT 0 n
FROM dual
UNION ALL
SELECT n + 1
FROM numbers
WHERE n <=
(
SELECT MAX(endserial - startserial)
FROM ranges
)
)
SELECT t.startserial + n.n SERIAL_NO
FROM ranges t JOIN numbers n
ON n.n <= t.endserial - t.startserial
ORDER BY SERIAL_NO
这里是SQLFiddle演示
【讨论】:
感谢亲爱的 peterm。我曾用 dual 尝试过一次。但它有更多时间来执行。这就是为什么我要 plsql :-)【参考方案2】:只需编写一些 PL/SQL - 遍历您的表并在临时表中插入行。
declare
l_start number;
l_end number;
begin
for r_rec in (select to_number(concat(card_bulk_code, start_serial)) startserial
, to_number(concat(card_bulk_code, end_serial)) endserial
from tsr_bulk_card_serials )
loop
l_start := r_rec.startserial;
l_end := r_rec.endserial;
for l_i in l_start..l_end loop
insert into your_temp_table;
end loop;
end loop;
end;
【讨论】:
只需添加 to_number( ... ) 以使数据类型为数字。您示例中的 Concat 函数可能返回 varchar2 类型。更新了答案。 你的数字有多大?最大起始序列号和最终序列号是多少? 喜欢这个'121100246016920' OK,然后添加 to_number() 就可以了。【参考方案3】:这样试试,
WITH t(ST, EN) AS
(
SELECT 18126944, 18126946 FROM dual
UNION
SELECT 18141101, 18141122 FROM dual
UNION
SELECT 15150722, 15150729 FROM dual
UNION
SELECT 19069303 , 19069317 FROM dual
)
SELECT DISTINCT st + LEVEL -1
FROM t
CONNECT BY LEVEL <= (SELECT en - st + 1 FROM DUAL)
ORDER BY 1;
/
为 PL/SQL 尝试类似的方法,
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (SELECT * FROM t)
LOOP
l_st := rec.st;
l_en := rec.en;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO <your_tab>;
END LOOP;
END LOOP;
COMMIT;
END;
【讨论】:
亲爱的 Dba,这里使用的 pl-sql 怎么样?因为存在表中的行数更多 这会产生大量的行并且会很慢。 只需编写一些 PL/SQL - 遍历您的表并在临时表中插入行。 是的,亲爱的 Przemyslaw.thatswhy 我想插入临时表。 @PrzemyslawKruglej,你说得对,如果我们使用 sql 会非常慢。感谢您指出。【参考方案4】:DECLARE
l_st NUMBER (20);
l_en NUMBER (20);
testnum NUMBER (4);
BEGIN
FOR rec IN (SELECT CONCAT (card_bulk_code, start_serial) startserial,CONCAT (card_bulk_code, end_serial) endserial FROM tsr_bulk_card_serials)
LOOP
l_st := TO_NUMBER (rec.startserial);
l_en := TO_NUMBER (rec.endserial);
testnum := l_en - l_st;
DBMS_OUTPUT.put_line (l_st);
DBMS_OUTPUT.put_line (l_en);
IF l_st < l_en
THEN
FOR rec1 IN 0 .. testnum
LOOP
l_st := l_st + 1;
INSERT INTO temp(serial_no) VALUES (l_st);
END LOOP;
END IF;
END LOOP;
COMMIT;
END;
上面的代码帮助我解决了我的问题 谢谢大家:-)
【讨论】:
以上是关于如何通过 PL-Sql 获取数字范围内的数字。?的主要内容,如果未能解决你的问题,请参考以下文章
如何创建一个 NSPredicate 过滤给定范围内的所有字符,包括数字/数字?