我第二天遇到了以下问题。 我有一个包,想要从另一个中调用一个函数。 我有一张带坐标的地方表。所以第一个函数返回 两个城市之间的距离。第二个必须返回一个数字表,表示从一个城市到其他城市的距离。 所以我不知道我在做错了什么: 因此函数Entfernung不起作用,但函数abstand工作正常。
我遇到以下编译错误: Fehler(11,20):PLS-00103:遇到符号"("当期待下列之一时:。 Fehler(12,7):PLS-00103:遇到符号" EXIT"当期待以下之一时:。 (,%来自
set serveroutput on
set echo on
CREATE OR REPLACE PACKAGE Geo AS
TYPE entfernungTab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
FUNCTION Abstand(Stadt1 IN Rheinland_Staedte.Stadtname%TYPE, Stadt2 IN Rheinland_Staedte.Stadtname%TYPE) RETURN NUMBER;
FUNCTION Entfernung(Stadt IN Rheinland_Staedte.Stadtname%TYPE) RETURN entfernungTab;
END Geo;
/
CREATE OR REPLACE PACKAGE BODY Geo AS
FUNCTION Entfernung(Stadt IN Rheinland_Staedte.Stadtname%TYPE)
RETURN entfernungTab
IS
TYPE entfernungTab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
CURSOR cur_ent IS SELECT * FROM Rheinland_Staedte;
BEGIN
OPEN cur_ent;
LOOP
FETCH Abstand(Stadt, cur_ent.Stadtname) INTO entfernungTab
EXIT WHEN cur_ent%NOTFOUND;
END LOOP;
RETURN (entfernungTab);
END;
FUNCTION Abstand (Stadt1 IN Rheinland_Staedte.Stadtname%TYPE, Stadt2 IN Rheinland_Staedte.Stadtname%TYPE)
RETURN NUMBER
IS
v_dis NUMBER;
v_s1 Rheinland_Staedte%ROWTYPE;
v_s2 Rheinland_Staedte%ROWTYPE;
v_yAbstandMin NUMBER;
v_xAbstandMin NUMBER;
BEGIN
SELECT * INTO v_s1 FROM Rheinland_Staedte WHERE Stadtname = Stadt1;
SELECT * INTO v_s2 FROM Rheinland_Staedte WHERE Stadtname = Stadt2;
v_yAbstandMin := ((v_s1.GradNB * 60) + v_s1.MinNB)
- ((v_s2.GradNB * 60) + v_s2.MinNB);
v_xAbstandMin := ((v_s1.GradOL * 60) + v_s1.MinOL)
- ((v_s2.GradOL * 60) + v_s2.MinOL);
v_dis := SQRT((v_yAbstandMin * v_yAbstandMin)) + ((v_xAbstandMin * v_xAbstandMin));
RETURN (v_dis);
END;
END Geo;
希望你能给我一些建议。
答案 0 :(得分:2)
FETCH Abstand(Stadt, cur_ent.Stadtname) INTO entfernungTab
之后缺少分号。
您必须实际声明类型为entfernungTab
的变量并将其返回。你不能将记录分配给一个类型并返回 - 它没有任何意义。
从包体(entfernungTab
)中删除TYPE entfernungTab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
的类型定义 - 您已经在包声明中定义了类型。
从光标获取时无法应用函数。而是将该函数集成到游标定义中。
以下代码调整问题:
FUNCTION Entfernung(Stadt IN Rheinland_Staedte.Stadtname%TYPE)
RETURN entfernungTab
IS
CURSOR cur_ent IS SELECT Abstand(Stadt, Stadtname) FROM Rheinland_Staedte;
distanzen entfernungTab;
BEGIN
OPEN cur_ent;
LOOP
FETCH cur_ent INTO distanzen ( distanzen.COUNT + 1 );
EXIT WHEN cur_ent%NOTFOUND;
END LOOP;
RETURN distanzen;
END Entfernung;
答案 1 :(得分:2)
你有一些问题。即时错误是您尝试将某个函数作为fetch
的一部分进行调用,这是不允许的。
这编译;我在评论中写了一些笔记。
FUNCTION Entfernung(Stadt IN Rheinland_Staedte.Stadtname%TYPE)
RETURN entfernungTab
IS
-- do not redelare the type in the function (or the package body)
-- TYPE entfernungTab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
CURSOR cur_ent IS SELECT * FROM Rheinland_Staedte;
-- you need a record to fetch into
cur_row cur_ent%ROWTYPE;
-- you need a variable of the return type, and to initialise it
returnTab entfernungTab;
-- you need an index variable for the table;
indx pls_integer := 0;
BEGIN
OPEN cur_ent;
LOOP
-- fetch into a record, and you can't call the function at this point
-- FETCH Abstand(Stadt, cur_ent.Stadtname) INTO entfernungTab
FETCH cur_ent INTO cur_row;
-- check this condition straight after fetching
EXIT WHEN cur_ent%NOTFOUND;
-- add the function result to the table, based on the record field value
indx := indx + 1;
returnTab(indx) := Abstand(Stadt, cur_row.Stadtname);
END LOOP;
-- close the cursor
CLOSE cur_ent;
-- return the variable, not the type
-- RETURN (entfernungTab);
RETURN returnTab;
END;
您也可以将该函数作为游标查询的一部分来调用,如果这是游标查询中唯一的表达式/列,您可以直接选择您的集合而无需循环:
FUNCTION Entfernung(Stadt IN Rheinland_Staedte.Stadtname%TYPE)
RETURN entfernungTab
IS
-- call the function in the cursor query
CURSOR cur_ent IS SELECT Abstand(Entfernung.Stadt, Rheinland_Staedte.Stadtname)
FROM Rheinland_Staedte;
returnTab entfernungTab;
BEGIN
OPEN cur_ent;
-- bulk collect straight into your collection
FETCH cur_ent BULK COLLECT INTO returnTab;
CLOSE cur_ent;
RETURN returnTab;
END;
或者,如果您有大量记录,则可以添加限制:
FUNCTION Entfernung(Stadt IN Rheinland_Staedte.Stadtname%TYPE)
RETURN entfernungTab
IS
-- call the function in the cursor query
CURSOR cur_ent IS SELECT Abstand(Entfernung.Stadt, Rheinland_Staedte.Stadtname)
FROM Rheinland_Staedte;
returnTab entfernungTab;
BEGIN
OPEN cur_ent;
LOOP
-- bulk collect straight into your collection with limit
FETCH cur_ent BULK COLLECT INTO returnTab LIMIT 10;
EXIT WHEN cur_ent%NOTFOUND;
END LOOP;
CLOSE cur_ent;
RETURN returnTab;
END;