尝试从游标中获取时出现 PLS-00103 错误
PLS-00103 error when trying to fetch from a cursor
我正在尝试编写游标。我尝试匹配示例的语法,但总是在 FETCH
语句上编译失败。
CREATE OR REPLACE PROCEDURE IFSAPP.CLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
-- cursor to get all the purchase orders's that have lines in released state that
CURSOR c1 IS
SELECT DISTINCT PO.ORDER_NO
FROM PURCHASE_ORDER PO, PURCHASE_ORDER_LINE_NOPART POLN
WHERE PO.ORDER_NO = POLN.ORDER_NO
AND POLN.STATE = 'Released'
AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY');
BEGIN
DECLARE corder_no varchar2(12);
OPEN c1;
LOOP
FETCH c1 INTO corder_no;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(corder_no);
END LOOP;
CLOSE c1;
END CLEAR_OLD_PURCHASE_ORDERS;
/
LINE/COL ERROR
-------- -----------------------------------------------------------------
17/9 PLS-00103: Encountered the symbol "FETCH" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table columns long
double ref char time timestamp interval date binary national
character nchar
21/5 PLS-00103: Encountered the symbol "CLOSE" when expecting one of the following:
end not pragma final instantiable order overriding static
member constructor map
谁能看出我错在哪里?
问题实际上出在您声明局部变量的位置,以及 DECLARE
关键字的使用。那是开始一个新的内部 PL/SQL 块,但是您随后拥有 OPEN
等,而无需使用新的 BEGIN
.
继续该模式
虽然你不需要子块,只需将局部变量声明向上移动到现有 BEGIN
之前,并丢失额外的 DECLARE
:
CREATE OR REPLACE PROCEDURE IFSAPP.CLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
-- cursor to get all the purchase orders's that have lines in released state that
CURSOR c1 IS
SELECT DISTINCT PO.ORDER_NO
FROM PURCHASE_ORDER PO, PURCHASE_ORDER_LINE_NOPART POLN
WHERE PO.ORDER_NO = POLN.ORDER_NO
AND POLN.STATE = 'Released'
AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY');
corder_no varchar2(12);
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO corder_no;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(corder_no);
END LOOP;
CLOSE c1;
END CLEAR_OLD_PURCHASE_ORDERS;
/
顺便说一下,您应该考虑使用 ANSI 连接语法,而不是古老的逗号分隔 FROM
子句语法。而且使用隐式游标循环会更简单:
CREATE OR REPLACE PROCEDURE IFSAPPCLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
BEGIN
FOR r1 IN (
SELECT DISTINCT PO.ORDER_NO
FROM PURCHASE_ORDER_LINE_NOPART POLN
JOIN PURCHASE_ORDER PO
ON PO.ORDER_NO = POLN.ORDER_NO
WHERE POLN.STATE = 'Released'
AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY')
) LOOP
DBMS_OUTPUT.PUT_LINE(r1.order_no);
END LOOP;
END CLEAR_OLD_PURCHASE_ORDERS;
/
我通常也更喜欢将过程参数声明为您需要的数据类型,即作为 DATE
,这样您就可以在查询中使用它而无需转换它;并使调用者的问题是传递正确的数据类型。
我正在尝试编写游标。我尝试匹配示例的语法,但总是在 FETCH
语句上编译失败。
CREATE OR REPLACE PROCEDURE IFSAPP.CLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
-- cursor to get all the purchase orders's that have lines in released state that
CURSOR c1 IS
SELECT DISTINCT PO.ORDER_NO
FROM PURCHASE_ORDER PO, PURCHASE_ORDER_LINE_NOPART POLN
WHERE PO.ORDER_NO = POLN.ORDER_NO
AND POLN.STATE = 'Released'
AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY');
BEGIN
DECLARE corder_no varchar2(12);
OPEN c1;
LOOP
FETCH c1 INTO corder_no;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(corder_no);
END LOOP;
CLOSE c1;
END CLEAR_OLD_PURCHASE_ORDERS;
/
LINE/COL ERROR
-------- -----------------------------------------------------------------
17/9 PLS-00103: Encountered the symbol "FETCH" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table columns long
double ref char time timestamp interval date binary national
character nchar
21/5 PLS-00103: Encountered the symbol "CLOSE" when expecting one of the following:
end not pragma final instantiable order overriding static
member constructor map
谁能看出我错在哪里?
问题实际上出在您声明局部变量的位置,以及 DECLARE
关键字的使用。那是开始一个新的内部 PL/SQL 块,但是您随后拥有 OPEN
等,而无需使用新的 BEGIN
.
虽然你不需要子块,只需将局部变量声明向上移动到现有 BEGIN
之前,并丢失额外的 DECLARE
:
CREATE OR REPLACE PROCEDURE IFSAPP.CLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
-- cursor to get all the purchase orders's that have lines in released state that
CURSOR c1 IS
SELECT DISTINCT PO.ORDER_NO
FROM PURCHASE_ORDER PO, PURCHASE_ORDER_LINE_NOPART POLN
WHERE PO.ORDER_NO = POLN.ORDER_NO
AND POLN.STATE = 'Released'
AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY');
corder_no varchar2(12);
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO corder_no;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(corder_no);
END LOOP;
CLOSE c1;
END CLEAR_OLD_PURCHASE_ORDERS;
/
顺便说一下,您应该考虑使用 ANSI 连接语法,而不是古老的逗号分隔 FROM
子句语法。而且使用隐式游标循环会更简单:
CREATE OR REPLACE PROCEDURE IFSAPPCLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
BEGIN
FOR r1 IN (
SELECT DISTINCT PO.ORDER_NO
FROM PURCHASE_ORDER_LINE_NOPART POLN
JOIN PURCHASE_ORDER PO
ON PO.ORDER_NO = POLN.ORDER_NO
WHERE POLN.STATE = 'Released'
AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY')
) LOOP
DBMS_OUTPUT.PUT_LINE(r1.order_no);
END LOOP;
END CLEAR_OLD_PURCHASE_ORDERS;
/
我通常也更喜欢将过程参数声明为您需要的数据类型,即作为 DATE
,这样您就可以在查询中使用它而无需转换它;并使调用者的问题是传递正确的数据类型。