【问题标题】:How I can improve my plsql code for working correctly?如何改进我的 plsql 代码以使其正常工作?
【发布时间】:2021-03-19 03:55:22
【问题描述】:

我想创建一个程序,该程序将为训练计划表生成从指定开始日期起 4 周(或一个月)的记录,每周 3 次(周一、周三、周五或周二、周四、周六) )。如果该用户的某个日期已经存在培训,则无需插入记录。时间表是:

  1. 培训编号

  2. 用户名 VARCHAR

  3. 培训日期 这是我的代码:

    CREATE OR REPLACE PROCEDURE schedule_training
         (p_training_id IN OUT trainings.trainingid%TYPE,
          p_username trainings.username%TYPE,
          p_training_date IN OUT trainings.trainingdate%TYPE) IS
         v_date DATE := TO_DATE(TO_CHAR(ADD_MONTHS(p_training_date,1),'DD-MON-YYYY'));
         v_date1 trainings.trainingdate%TYPE;
         v_username trainings.username%TYPE;
     BEGIN
         WHILE(p_training_date < v_date)
         LOOP
         SELECT trainingdate, username INTO v_date1, v_username
         FROM trainings;
             IF(TO_CHAR(p_training_date,'d') = 1) THEN
                 IF p_username != v_username AND p_training_date != v_date1
                 THEN INSERT INTO trainings VALUES
                         (p_training_id, p_username, p_training_date);
                         p_training_id := p_training_id + 1;
                 END IF;
             ELSIF(TO_CHAR(p_training_date,'d') = 3) THEN
                 IF p_username != v_username AND p_training_date != v_date1
                 THEN INSERT INTO trainings VALUES
                         (p_training_id, p_username, p_training_date);
                         p_training_id := p_training_id + 1;
                 END IF;   
             ELSIF(TO_CHAR(p_training_date,'d') = 5) THEN
                 IF p_username != v_username AND p_training_date != v_date1
                 THEN INSERT INTO trainings VALUES
                         (p_training_id, p_username,p_training_date);
                         p_training_id := p_training_id + 1;
                 END IF;
             END IF;
    
    
             p_training_date := TO_DATE(TO_DATE(v_date,'dd.mm.yyyy')+ 1, 'dd.mm.yyyy');
    
         END LOOP;
     END schedule_training;
    

    我这样调用这个过程:

     schedule_training(1,'user1',TO_DATE('21-03-2021','DD-MM-YYYY'));
    

当我调用它时,会发生未知错误: 从行开始的错误:命令中的 41 - schedule_training(1,'user1',TO_DATE('21-03-2021','DD-MM-YYYY')) 错误报告 - 未知命令

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    在已经是 DATE 的值上运行 TO_DATE() 没有任何意义。

    所以使用简单

    v_date DATE := ADD_MONTHS(p_training_date,1);
    
    p_training_date := v_date + 1;
    

    TO_CHAR(..., 'd') 的结果取决于当前用户会话NLS_TERRITORY 设置,它可能随时更改。更好地使用TO_CHAR(p_training_date, 'DY', 'nls_date_language = american') IN ('MON', 'WED', 'FRI')

    查询SELECT trainingdate, username INTO v_date1, v_username FROM trainings; 是个问题SELECT ... INTO ... 要求查询准确返回一行。

    最后你不需要任何循环。可以使用行生成器,应该类似这样:

    v_date DATE := ADD_MONTHS(p_training_date,1);
    INSERT INTO trainings (better, list, column, names, here) 
    SELECT p_training_id + ROWNUM, p_username, training_date
    FROM (
         SELECT p_training_date + LEVEL as training_date 
         FROM dual 
         CONNECT BY p_training_date + LEVEL <= v_date)
    WHERE to_char(training_date , 'DY', 'nls_date_language = american') in ('MON', 'WED', 'FRI')
       AND NOT EXISTS (
          SELECT 1 
          FROM trainings 
          WHERE username = v_username AND trainingdate = training_date)
    
    p_training_id  := p_training_id + SQL%ROWCOUNT;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2017-05-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多