过程中的 PLSQL Oracle 游标
PLSQL Oracle Cursor in procedure
目前我正在学习PLSQL,使用Oracle。我正在尝试获取比在另一个 table 中贴标的 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;
您好,您没有为 ln_pallets_container 变量指定 table 名称,它还缺少一个“;”游标声明后修复此问题并尝试
修复了代码中的一些问题。
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;
您的代码有几处错误,我已修复并在下面突出显示:
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 值并过滤掉不需要警报过程的任何行运行.
同时,为什么不改用游标循环呢?这样,您就不必担心 opening/fetching from/closing 游标,因为 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;
目前我正在学习PLSQL,使用Oracle。我正在尝试获取比在另一个 table 中贴标的 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;
您好,您没有为 ln_pallets_container 变量指定 table 名称,它还缺少一个“;”游标声明后修复此问题并尝试
修复了代码中的一些问题。
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;
您的代码有几处错误,我已修复并在下面突出显示:
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 值并过滤掉不需要警报过程的任何行运行.
同时,为什么不改用游标循环呢?这样,您就不必担心 opening/fetching from/closing 游标,因为 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;