程序中的PLSQL Oracle Cursor

时间:2017-07-27 09:20:24

标签: oracle plsql cursor procedure

目前我正在使用Oracle学习PLSQL。我正在尝试获取比另一个表中的PARAM天更旧的数据。我希望程序获取所有数据,检查某些记录是否比param_value中的参数更旧(recv_date),如果是,则触发我的警报程序。我在声明CURSOR和ln_pallets_container时遇到问题。我知道我可以以某种方式进入ln_pallets数据只有recv_date我已经过滤但在这里我都不知道如何正确地做到这一点。也许我应该在程序之前声明游标而不是在其中?

  procedure CHECK_STOCK_DATE(warehouse_id_in IN warehouse.warehouse_id%TYPE)
IS
ln_pallet_count NUMBER;
ln_days_till_expiration param_value.param_value%TYPE;

CURSOR ln_pallets IS
       SELECT container_id, recv_date
       FROM wms_stock ws

ln_pallets_container%ROWTYPE;


BEGIN

       OPEN ln_pallets;
            LOOP
                FETCH ln_pallets INTO ln_pallets_container;
                EXIT WHEN ln_pallets%NOTFOUND;

                SELECT param_value.param_value
                INTO ln_days_till_expiration
                FROM param_value
                WHERE param_value.parameter_id = 266;

                   IF(ln_pallets_container.recv_date >= trunc(sysdate - ln_days_till_expiration)

                      ALARM.ALARM(WAREHOUSE_ID =>MY_COMMONS.GET_WHRS_ID,
SOURCE_TEXT => ln_pallets_container.container_id,
MESSAGE_CODE => 'Cannot find this container on warehouse. Check container code.');
                  END IF;
            END LOOP;
        CLOSE ln_pallets;
END;

3 个答案:

答案 0 :(得分:1)

修复了代码中的一些问题。

procedure check_stock_date(warehouse_id_in in warehouse.warehouse_id%type) is

       ln_pallet_count         number;
       ln_days_till_expiration param_value.param_value%type;

       l_container_id wms_stock.container_id%type;
       l_recv_date    wms_stock.recv_date%type;

       cursor ln_pallets is
          select container_id
                ,recv_date
            from wms_stock ws;

    begin

       open ln_pallets;

       loop
          fetch ln_pallets
             into l_container_id
                 ,l_recv_date;

          exit when ln_pallets%notfound;

          select param_value.param_value
            into ln_days_till_expiration
            from param_value
           where param_value.parameter_id = 266;

          if l_recv_date >= trunc(sysdate - ln_days_till_expiration)
          then
             alarm.alarm(warehouse_id => my_commons.get_whrs_id
                        ,source_text  => l_container_id
                        ,message_code => 'Cannot find this container on warehouse. Check container code.');
          end if;
       end loop;
       close ln_pallets;
    end;

答案 1 :(得分:1)

您的代码存在一些问题,我已修复并突出显示以下内容:

PROCEDURE check_stock_date(warehouse_id_in IN warehouse.warehouse_id%TYPE) IS
  ln_pallet_count         NUMBER;
  ln_days_till_expiration param_value.param_value%TYPE;

  CURSOR ln_pallets IS
    SELECT container_id,
           recv_date
    FROM   wms_stock ws; -- added semicolon

  ln_pallets_container ln_pallets%ROWTYPE; -- amended to set the datatype of the variable to be the cursor rowtype

BEGIN

  OPEN ln_pallets;
  LOOP
    FETCH ln_pallets
      INTO ln_pallets_container;
    EXIT WHEN ln_pallets%NOTFOUND;

    SELECT param_value.param_value
    INTO   ln_days_till_expiration
    FROM   param_value
    WHERE  param_value.parameter_id = 266;

    IF /*removed bracket*/ ln_pallets_container.recv_date >= trunc(SYSDATE - ln_days_till_expiration)
    THEN --added

      alarm.alarm(warehouse_id => my_commons.get_whrs_id,
                  source_text  => ln_pallets_container.container_id,
                  message_code => 'Cannot find this container on warehouse. Check container code.');
    END IF;
  END LOOP;
  CLOSE ln_pallets;
END check_stock_date;

然而,这可以更有效地完成。目前,您正在遍历wms_stock中的所有行,另外您自己明确地打开,获取和关闭光标。

这意味着对于wms_stock中的每一行,您都会找到parameter_id 266的值(我假设您在循环结果时不会改变!),以及检查是否可以运行你的警报程序。

为什么不将检查移动到光标中,而不是获取所有行 - 这样,您只需获取参数266值一次并过滤掉不需要运行警报程序的任何行。

同时,为什么不切换到使用游标换环?这样,您就不必担心打开/关闭游标,因为Oracle会为您处理所有这些。

这样做会导致代码少得多,这样更有效,更易于阅读和维护,如下所示:

PROCEDURE check_stock_date(warehouse_id_in IN warehouse.warehouse_id%TYPE) IS 
BEGIN
  FOR ln_pallets_rec IN (SELECT container_id,
                                recv_date
                         FROM   wms_stock ws
                         WHERE  recv_date >= (SELECT trunc(SYSDATE - param_value.param_value
                                              FROM   param_value
                                              WHERE  param_value.parameter_id = 266))
  LOOP
    alarm.alarm(warehouse_id => my_commons.get_whrs_id,
                source_text  => ln_pallets_rec.container_id,
                message_code => 'Cannot find this container on warehouse. Check container code.');
  END LOOP;

END check_stock_date;

答案 2 :(得分:0)

您好,您没有为ln_pallets_container变量指定表名,也缺少&#39 ;;'在游标声明后修复此问题并尝试