目前我正在使用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;
答案 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 ;;'在游标声明后修复此问题并尝试