如何通过PL-Sql获取数字范围内的数字。?

时间:2013-11-21 09:17:23

标签: sql oracle plsql

这是我的串行表。它有超过1000条记录。具有起始编号和结束编号。但数字之间不存在。 我需要添加所有数字[开始/介于&之间结束号码]另一个临时表中记录按号码编号 如下所示

EXIST TABLE

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来实现这一点。 请帮我解决这个问题

我在dual的帮助下尝试了以下查询。 但它非常缓慢但尚未得到结果:-)运行超过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&amp; Dba.i尝试了你的问题,并且发生了以下错误。

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.

4 个答案:

答案 0 :(得分:4)

一种方法,无需借助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 演示

答案 1 :(得分:1)

试试这个,

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;     

答案 2 :(得分:1)

只需编写一些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;

答案 3 :(得分:0)

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;

上面的代码帮助我解决了我的问题 谢谢大家: - )