不知道我的存储过程写的好不好?

该存储过程用于根据输入的开始和结束日期以及工作日数量范围,计算并返回相应的颜色标记,黄色表示工作日在指定范围内,红色表示超过范围。同时,定义了一个功能函数用于工单通告预警,依据业务单位和当前日期计算预警级别、数量等信息。
不知道这样写存储过程,是不是不够优化?
  1. create or replace function F_GET_WORK_DAYS_COLOR   
  2. (   
  3.   in_begin_date  DATE,   
  4.   in_end_date    DATE,   
  5.   in_first_days  number,   
  6.   in_second_days number   
  7.  )   
  8. return varchar2 is  
  9.   
  10. /*=========================================================   
  11. 功能:去掉休息日,去工作日,   
  12. 说明:传入日期 和 工作日天数,返回到期时间   
  13. 创建:   
  14. 修改:   
  15. 时间:2006-12-12   
  16. =========================================================*/   
  17.   
  18. v_color        varchar(20);   
  19. v_days         number(6);   
  20. --v_exception Exception;   
  21.   
  22.   
  23.   
  24. begin  
  25.   
  26.   
  27.  select count(1)    
  28.    into v_days    
  29.    from ZX_CALENDAR_AND_REST z   
  30.   where z.calendar_day >= trunc(in_begin_date)   
  31.     and z.calendar_day <= trunc(in_end_date)   
  32.     and z.rest_flag = 'N';   
  33.   
  34.   if v_days  > in_first_days and v_days  <= in_second_days then  
  35.      v_color := 'yellow';   
  36.   elsif v_days  > in_second_days  then  
  37.      v_color :=  'red';   
  38.   else  
  39.      v_color := 'white';   
  40.   end if;   
  41.   
  42.   return v_color;   
  43.   
  44. exception   
  45.   when others then  
  46.     rollback;   
  47.    -- p_pub_error_log(v_result, sqlcode, sqlerrm, 'sf_f_note_issue_confirm');   
  48.     return sysdate;   
  49. end;   
  1. create or replace function F_ZX_WORK_SHEET_VERIFY_NOTICES(   
  2.   begin_day   date,   
  3.   end_day     date,   
  4.   v_operator  varchar2,   
  5.   stat_bureau varchar2)   
  6. return integer is  
  7.  ------------------------------------------------------------------------------------------   
  8.  -- 功能:工单通告预警   
  9.  -- 参数:当前日期   
  10.  -- 创建: 2007-1-24   
  11.  -- 修改:   
  12.  ------------------------------------------------------------------------------------------   
  13.   
  14.  v_day     date;   
  15.  v_end_day date;   
  16.  v_busi    varchar2(8);   
  17.  v_result  integer;   
  18. begin  
  19.   v_day := sysdate ;   
  20.   v_busi := stat_bureau;   
  21.   v_end_day := end_day;   
  22.   --初使化v_busi   
  23.     if v_busi = '%' then  
  24.        v_busi := 'TT';   
  25.     end if;   
  26.      --清除已经发布的内容   
  27.   v_result := -10;   
  28.   delete from ZX_WORK_SHEET_VERIFY_NOTICES h   
  29.   where h.start_day   = begin_day and  
  30.         h.end_day     = v_end_day and  
  31.         (h.STAT_BUREAU = v_busi or h.bureau_code = v_busi);    --新加的列,统计单位   
  32.    dbms_output.put_line('liuhui');   
  33.    --插入数据   
  34.    v_result := -20;   
  35. if v_busi = 'TT' then    
  36.   insert into ZX_WORK_SHEET_VERIFY_NOTICES   
  37.   (   
  38.     NOTICE_LEVEL ,   
  39.     NOTICE_DAY   ,   
  40.     SHEET_NUM   ,   
  41.     SHEET_RATE   ,   
  42.     RATE_NUM     ,   
  43.     REMARK      ,   
  44.     BUREAU_CODE ,   
  45.     OPERATOR    ,   
  46.     DATA_TIME   ,   
  47.     START_DAY   ,   
  48.     END_DAY     ,   
  49.     STAT_BUREAU )   
  50.    SELECT DECODE(W.COLOR,'red',1,'yellow',2,3),   
  51.           v_day,   
  52.           W.NUM,   
  53.           0,   
  54.           0,   
  55.           DECODE(W.COLOR,'red','非常严重','yellow','严重',''),   
  56.           W.BUREAU_CODE,   
  57.           v_operator ,   
  58.           v_day,   
  59.           begin_day ,   
  60.           v_end_day ,   
  61.           v_busi   
  62.     FROM  
  63.    (select count(1)  NUM,   
  64.            z.bureau_code   BUREAU_CODE,   
  65.    max(F_GET_WORK_DAYS_COLOR(z.confirm_date,decode(z.back_verify_date,'',sysdate,z.back_verify_date),3,13))  COLOR   
  66.      from ZX_WORK_SHEET_VERIFY z   
  67.      where F_GET_WORK_DAYS_COLOR(z.confirm_date,decode(z.back_verify_date,'',sysdate,z.back_verify_date),3,13) <> 'white'   
  68.      and z.confirm_sign = 'Y' and z.app_date between begin_day and v_end_day  and (z.error_type <> '0' or z.error_type is not null)   
  69.      group by z.bureau_code,F_GET_WORK_DAYS_COLOR(z.confirm_date,decode(z.back_verify_date,'',sysdate,z.back_verify_date),3,13)   
  70.      ORDER BY COLOR,NUM ) W;   
  71. ELSE  
  72.      
  73.   insert into ZX_WORK_SHEET_VERIFY_NOTICES   
  74.   (   
  75.     NOTICE_LEVEL ,   
  76.     NOTICE_DAY   ,   
  77.     SHEET_NUM   ,   
  78.     SHEET_RATE   ,   
  79.     RATE_NUM     ,   
  80.     REMARK      ,   
  81.     BUREAU_CODE ,   
  82.     OPERATOR    ,   
  83.     DATA_TIME   ,   
  84.     START_DAY   ,   
  85.     END_DAY     ,   
  86.     STAT_BUREAU )   
  87.    SELECT DECODE(W.COLOR,'red',1,'yellow',2,3),   
  88.           v_day,   
  89.           W.NUM,   
  90.           0,   
  91.           0,   
  92.           DECODE(W.COLOR,'red','非常严重','yellow','严重',''),   
  93.           W.BUREAU_CODE,   
  94.           v_operator ,   
  95.           v_day,   
  96.           begin_day ,   
  97.           v_end_day ,   
  98.           v_busi   
  99.     FROM  
  100.    (select count(1)  NUM,   
  101.            z.bureau_code   BUREAU_CODE,   
  102.    max(F_GET_WORK_DAYS_COLOR(z.confirm_date,decode(z.back_verify_date,'',sysdate,z.back_verify_date),3,13))  COLOR   
  103.      from ZX_WORK_SHEET_VERIFY z   
  104.      where F_GET_WORK_DAYS_COLOR(z.confirm_date,decode(z.back_verify_date,'',sysdate,z.back_verify_date),3,13) <> 'white'   
  105.      and z.confirm_sign = 'Y' and z.app_date between begin_day and v_end_day  and (z.error_type <> '0' or z.error_type is not null)   
  106.      group by z.bureau_code,F_GET_WORK_DAYS_COLOR(z.confirm_date,decode(z.back_verify_date,'',sysdate,z.back_verify_date),3,13)   
  107.      ORDER BY COLOR,NUM ) W    
  108.      WHERE W.BUREAU_CODE = v_busi;   
  109.   end if;   
  110.   ------合计   
  111.   v_result := -30;   
  112. IF v_busi = 'TT' then  
  113.   insert into ZX_WORK_SHEET_VERIFY_NOTICES   
  114.   (   
  115.     NOTICE_LEVEL ,   
  116.     NOTICE_DAY   ,   
  117.     SHEET_NUM   ,   
  118.     SHEET_RATE   ,   
  119.     RATE_NUM     ,   
  120.     REMARK      ,   
  121.     BUREAU_CODE ,   
  122.     OPERATOR    ,   
  123.     DATA_TIME   ,   
  124.     START_DAY   ,   
  125.     END_DAY     ,   
  126.     STAT_BUREAU )   
  127.    SELECT DECODE(t.notice_level,'',3,t.notice_level),   
  128.           v_day,   
  129.           sum(nvl(t.sheet_num,0)),   
  130.           '',   
  131.           max(0),   
  132.           max(t.remark),   
  133.           'TT'  ,   
  134.           v_operator ,   
  135.           v_day,   
  136.           begin_day ,   
  137.           v_end_day ,   
  138.           v_busi   
  139.     from  ZX_WORK_SHEET_VERIFY_NOTICES t   
  140.    where t.start_day = begin_day   
  141.      and t.end_day   = v_end_day   
  142.      and t.bureau_code <> v_busi    
  143.      and t.stat_bureau = v_busi    
  144.    group by rollup(t.notice_level);   
  145.   
  146. end if;   
  147.   
  148.   ----工单超期率 不包括天津的   
  149.     v_result := -40;   
  150. if v_busi = 'TT' then    
  151.     update ZX_WORK_SHEET_VERIFY_NOTICES  B   
  152.        set (B.SHEET_RATE) = (select round(decode((select count(*) from ZX_WORK_SHEET_VERIFY z    
  153.                               where z.app_date between begin_day and v_end_day   
  154.                                 and z.bureau_code = a.bureau_code    
  155.                                 and (z.confirm_date <> date'1900-1-1' or z.confirm_date is not null)),0,0,   
  156.                             (select sum(c.SHEET_NUM) from ZX_WORK_SHEET_VERIFY_NOTICES c   
  157.                               where c.bureau_code  = a.bureau_code    
  158.                                 and a.notice_level = c.notice_level   
  159.                                 and b.start_day    = c.start_day    
  160.                                 and c.end_day      = b.end_day and c.bureau_code <> v_busi and    
  161.                                 c.stat_bureau = v_busi )   
  162.                                 /   
  163.                              (select count(*) from ZX_WORK_SHEET_VERIFY z   
  164.                                where z.app_date between begin_day and v_end_day   
  165.                                  and z.bureau_code  = a.bureau_code    
  166.                                  and (z.confirm_date <> date'1900-1-1' or z.confirm_date is not null))),4)*100   
  167.                                 from ZX_WORK_SHEET_VERIFY_NOTICES a    
  168.                                WHERE A.BUREAU_CODE  = B.BUREAU_CODE    
  169.                                  AND A.NOTICE_LEVEL = B.NOTICE_LEVEL   
  170.                                  and b.start_day    = a.start_day    
  171.                                  and a.end_day      = b.end_day    
  172.                                  and a.bureau_code <> v_busi AND A.STAT_BUREAU = B.STAT_BUREAU);    
  173.                                    
  174. else    
  175.     update ZX_WORK_SHEET_VERIFY_NOTICES  B   
  176.        set (B.SHEET_RATE) = (select round(decode((select count(*) from ZX_WORK_SHEET_VERIFY z    
  177.                               where z.app_date between begin_day and v_end_day   
  178.                                 and z.bureau_code = a.bureau_code    
  179.                                 and (z.confirm_date <> date'1900-1-1' or z.confirm_date is not null)),0,0,   
  180.                             (select sum(nvl(c.SHEET_NUM,0)) from ZX_WORK_SHEET_VERIFY_NOTICES c   
  181.                               where c.bureau_code  = a.bureau_code    
  182.                                 and a.notice_level = c.notice_level   
  183.                                 and b.start_day    = c.start_day    
  184.                                 and c.end_day      = b.end_day    
  185.                                 )   
  186.                                 /   
  187.                              (select count(*) from ZX_WORK_SHEET_VERIFY z   
  188.                                where z.app_date between begin_day and v_end_day   
  189.                                  and z.bureau_code  = a.bureau_code    
  190.                                  and (z.confirm_date <> date'1900-1-1' or z.confirm_date is not null))),4)*100   
  191.                                 from ZX_WORK_SHEET_VERIFY_NOTICES a    
  192.                                WHERE A.BUREAU_CODE  = B.BUREAU_CODE    
  193.                                  AND A.NOTICE_LEVEL = B.NOTICE_LEVEL   
  194.                                  and b.start_day    = a.start_day    
  195.                                  and a.end_day      = b.end_day    
  196.                                  and a.bureau_code = v_busi AND A.STAT_BUREAU = B.STAT_BUREAU);    
  197. end if;   
  198.   -----排名   
  199.     v_result := -50;   
  200. if v_busi = 'TT' then    
  201.      update ZX_WORK_SHEET_VERIFY_NOTICES  B   
  202.         set (B.RATE_NUM) = (select r.row_num   
  203.                            FROM (   
  204.                            SELECT row_number () over (PARTITION by z.NOTICE_LEVEL order by z.SHEET_RATE asc) row_num,   
  205.                                   Z.BUREAU_CODE , Z.NOTICE_LEVEL   
  206.                            FROM ZX_WORK_SHEET_VERIFY_NOTICES Z where  
  207.                              begin_day = z.start_day and v_end_day = z.end_day and z.notice_level <> 3 AND Z.BUREAU_CODE <> v_busi   
  208.                              AND Z.STAT_BUREAU = v_busi    
  209.                            ) r   
  210.                             WHERE r.BUREAU_CODE = B.BUREAU_CODE AND r.NOTICE_LEVEL = B.NOTICE_LEVEL  );    
  211.  else update ZX_WORK_SHEET_VERIFY_NOTICES  B   
  212.         set (B.RATE_NUM) = '';   
  213. end if;   
  214.      commit;   
  215.      return 0;   
  216.    exception   
  217.      when others then  
  218.      begin  
  219.        rollback ;   
  220.      P_PUB_ERROR_LOG(v_result,sqlcode,sqlerrm,'F_ZX_WORK_SHEET_VERIFY_NOTICES');   
  221.      return v_result;   
  222.      end;   
  223. END;   
<think>好的,我现在需要帮助用户用Oracle存储过程一个随机大乐透的程序。首先,我得理解大乐透的规则。大乐透通常是前区1-35选5个重复的数字,后区1-12选2个重复的数字,所以整个程序需要生成两组数字。 接下来,我得考虑如何在Oracle中实现随机选择。可能需要用到DBMS_RANDOM包来生成随机数。过要注意的是,生成的数字能重复,所以需要处理重复的情况。比如前区5个数字,每次生成一个数字后检查是否已经存在,如果存在就重新生成,直到得到5个重复的。 然后,存储过程的结构应该是什么样的呢?可能需要创建一个存储过程,里面定义变量来存储前区和后区的数字。前区可以用一个数组或者集合来保存,确保重复。后区同理,但范围同。 接着,排序的问题。生成完数字后,前区和后区都需要按升序排列,这样符合一般的显示习惯。可以用Oracle的排序功能,比如使用ORDER BY或者自己排序逻辑。 还要考虑输出结果。存储过程可能需要使用DBMS_OUTPUT.PUT_LINE来显示结果。或者返回给调用者,比如用OUT参数。这里用户可能只需要简单的输出,所以用DBMS_OUTPUT应该可以。 然后,需要处理可能出现的死循环吗?比如在生成数字时,如果运气好一直重复,但实际情况下概率很低,可能需要特别处理,但还是要确保循环有终止条件。 测试的时候,可能需要多次执行存储过程,检查生成的数字是否符合规则,是否有重复,排序是否正确。 可能的步骤分解: 1. 创建存储过程结构。 2. 定义前区和后区的变量,比如使用集合类型。 3. 循环生成前区5个数字,检查重复。 4. 同样处理后区的2个数字。 5. 对结果进行排序。 6. 输出结果。 现在,具体实现时,可能需要用到PL/SQL的集合,比如VARRAY或者TABLE类型。例如,前区可以声明为一个数字数组,每次生成一个随机数,检查是否在数组中已存在,存在则加入,直到有5个。 关于随机数的生成,DBMS_RANDOM.VALUE(1,35)生成的是包括1,但包括35的数值,所以可能需要使用TRUNC或者CEIL来调整,例如使用TRUNC(DBMS_RANDOM.VALUE(1,36))来得到1-35的整数。 后区同理,用1-12的范围。 排序部分,可以使用SELECT ... FROM TABLE(...) ORDER BY COLUMN_VALUE的方式来排序集合中的元素。 最后,将前区和后区的结果拼接成字符串输出。 可能需要处理集合类型和字符串之间的转换,比如用循环遍历数组中的元素,拼成字符串,或者用XMLAGG等函数。 检查语法是否正确,比如变量声明、循环结构、异常处理等。 例如,代码结构大致如下: CREATE OR REPLACE PROCEDURE generate_daletou IS 前区数组类型定义; 后区数组类型定义; BEGIN 初始化前区数组; WHILE 数组长度小于5 LOOP 生成随机数; 检查是否存在,存在则加入; END LOOP; 同样处理后区; 排序; 输出结果; END; 具体实现时,需要注意数据类型的正确使用,以及循环逻辑的正确性。</think>以下是用Oracle存储过程实现随机大乐透号码生成的详细步骤: ```sql CREATE OR REPLACE PROCEDURE Generate_DaLeTou IS TYPE num_array IS VARRAY(5) OF NUMBER; -- 前区数组类型 TYPE spec_array IS VARRAY(2) OF NUMBER; -- 后区数组类型 front_num num_array := num_array(); -- 前区号码 back_num spec_array := spec_array(); -- 后区号码 temp_num NUMBER; BEGIN -- 生成前区号码(1-35选5个) WHILE front_num.COUNT < 5 LOOP temp_num := TRUNC(DBMS_RANDOM.VALUE(1, 36)); -- 生成1-35的随机整数 IF NOT temp_num MEMBER OF front_num THEN front_num.EXTEND; front_num(front_num.COUNT) := temp_num; END IF; END LOOP; -- 生成后区号码(1-12选2个) WHILE back_num.COUNT < 2 LOOP temp_num := TRUNC(DBMS_RANDOM.VALUE(1, 13)); -- 生成1-12的随机整数 IF NOT temp_num MEMBER OF back_num THEN back_num.EXTEND; back_num(back_num.COUNT) := temp_num; END IF; END LOOP; -- 对结果进行排序(使用嵌套表实现排序) SELECT COLUMN_VALUE BULK COLLECT INTO front_num FROM TABLE(front_num) ORDER BY 1; SELECT COLUMN_VALUE BULK COLLECT INTO back_num FROM TABLE(back_num) ORDER BY 1; -- 输出结果 DBMS_OUTPUT.PUT_LINE('大乐透号码:'); DBMS_OUTPUT.PUT('前区: '); FOR i IN 1..front_num.COUNT LOOP DBMS_OUTPUT.PUT(LPAD(front_num(i), 2, '0') || ' '); END LOOP; DBMS_OUTPUT.NEW_LINE; DBMS_OUTPUT.PUT('后区: '); FOR i IN 1..back_num.COUNT LOOP DBMS_OUTPUT.PUT(LPAD(back_num(i), 2, '0') || ' '); END LOOP; DBMS_OUTPUT.NEW_LINE; END; / ``` 执行方法: ```sql -- 启用输出 SET SERVEROUTPUT ON; -- 调用存储过程 EXEC Generate_DaLeTou; ``` 代码说明: 1. **变量定义** - 使用`VARRAY`定义固定长度的数组类型 - 前区数组容量5,数值范围1-35 - 后区数组容量2,数值范围1-12 2. **随机数生成** - `DBMS_RANDOM.VALUE`生成指定范围的随机数 - `TRUNC`保证生成整数 - `MEMBER OF`检查数值是否已存在 3. **排序实现** - 通过`TABLE()`函数将VARRAY转换为可查询的表 - 使用`ORDER BY`进行排序后重新填充数组 4. **结果输出** - `LPAD`保证两位数格式显示 - 使用`DBMS_OUTPUT`包进行格式化输出 典型输出示例: ``` 大乐透号码: 前区: 05 12 18 27 33 后区: 03 11 ``` 注意事项: 1. 需要Oracle 10g及以上版本支持`MEMBER OF`语法 2. 保证`DBMS_OUTPUT`缓冲区足够大(可使用`SET SERVEROUTPUT ON SIZE UNLIMITED`) 3. 重复执行会生成同的随机组合 4. 可通过修改数值范围适配其他彩票规则 这个实现方式保证了: - 数值的绝对随机性 - 无重复号码 - 符合官方排序规则 - 标准的输出格式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值