如何在包PL / SQL中返回数字表

时间:2016-05-20 16:25:28

标签: sql oracle plsql

我第二天遇到了以下问题。 我有一个包,想要从另一个中调用一个函数。 我有一张带坐标的地方表。所以第一个函数返回 两个城市之间的距离。第二个必须返回一个数字表,表示从一个城市到其他城市的距离。 所以我不知道我在做错了什么: 因此函数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;
希望你能给我一些建议。

2 个答案:

答案 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;