PL/SQL 根据用户输入值输出值的存储过程

PL/SQL stored procedure which outputs values depending on user input value

我有一个 Oracle table(示例):

+----------------------------+----------------+-----------------------+
|     DEPT                   |   BUILDINGID   |      GEOMETRY         |
+----------------------------+----------------------------------------+
| Emergency Services AMB     |      516       |  [MDSYS.SDO_GEOMETRY] |
| Emergency Services AMB     |      287       |  [MDSYS.SDO_GEOMETRY] |
| Emergency Services FIRE    |      283       |  [MDSYS.SDO_GEOMETRY] |
| Emergency Services FIRE    |      460       |  [MDSYS.SDO_GEOMETRY] |
| Emergency Services POLICE  |      515       |  [MDSYS.SDO_GEOMETRY] |
+----------------------------+----------------------------------------+

我正在制作一个 PL/SQL 存储过程,要求用户插入他们想要的部门。然后部门名称将被 link 编辑为其 ID (BUILDINGID) 以及 LONGITUDE 和 LATITUDE。

输出需要如下:

Type of Building:

BUILDINGID      LONGITUDE      LATITUDE
----------      ---------      --------

我已经启动了以下代码,但我坚持尝试 link BUILDINGID 与用户输入的部门。另外,如何分别显示经度和纬度? (因为它们位于 [MDSYS.SDO_GEOMETRY] )?

CREATE OR REPLACE PROCEDURE outputBuilding              --create procedure
  (i_building_type IN VARCHAR2 (20),
   i_BuildingID IN OTTAWABUILDINGS.BUILDINGID%TYPE,
   i_longitude IN OTTAWABUILDINGS.GEOMETRY%Type,
   i_latitude IN OTTAWABUILDINGS.GEOMETRY%Type) IS


CURSOR c_building IS
SELECT DEPT, BUILDINGID
FROM OTTAWABUILDINGS;
r_building c_building%ROWTYPE;

BEGIN
v_type := '&TypeOfBuilding';   --user inserts type of building

DBMS_OUTPUT.PUT_LINE('Type of Building: ' ||v_type);
DBMS_OUTPUT.PUT_LINE ('BUILDINGID   ' || 'LONGITUDE   ' ||'LATITUDE    ' );
DBMS_OUTPUT.PUT_LINE ('----------   ' || '----------   ' ||'----------    ' );

    FOR r_building IN c_building
    LOOP 
        SELECT DEPT INTO v_type FROM OTTAWABUILDINGS WHERE DEPT = v_type;
        IF v_type = 'Emergency Services POLICE' OR
        v_type = 'Emergency Services AMB' OR
        v_type = 'Emergency Services FIRE' THEN
        DBMS_OUTPUT.PUT_LINE (i_BuildingID || '   ' || i_longitude || '   ' || i_latitude);
        END IF;
    END LOOP;
COMMIT;
END outputBuilding;

-----------TESTING STORED PROCEDURE---------------
BEGIN
  outputBuilding (i_BuildingID, i_longitude, i_latitude);
END;

设计程序需要一些计划和思考。您需要了解需求并在代码中实现它们。

所以第一个要求是:

the user is asked to insert a department they wish

这意味着您的过程应该采用单个参数:

CREATE OR REPLACE PROCEDURE outputBuilding             
  (i_building_type IN VARCHAR2 )
IS

请注意,参数不受长度限制(同样,'Emergency Services POLICE' 超过二十个字符)。

下一个要求:

the department name will be linked to

这意味着您需要使用参数来过滤您的查询。为了清楚起见,我们将坚持使用您的显式光标。

CURSOR c_building IS
    SELECT DEPT, BUILDINGID
    FROM OTTAWABUILDINGS
    where dept = i_building_type;

下一个要求是:

the department name will be linked to its ID (BUILDINGID) and the LONGITUDE and LATITUDE

嗯,我们最好在查询中包括几何列。

CURSOR c_building IS
    SELECT DEPT, BUILDINGID, geometry
    FROM OTTAWABUILDINGS
    where dept = i_building_type;
r_building c_building%ROWTYPE;

最终且最棘手的要求

show the longitude and latitude separately

这取决于经度和纬度的存储方式。我们应该希望它们存储为点。所以你需要这样的东西:

v_long := r_building.geometry.SDO_POINT.X;
v_lat := r_building.geometry.SDO_POINT.Y;

警告:我现在无法访问具有空间的数据库,因此不能保证这一点。

代码中的冗余:

  • 不要将 SQL*Plus 语法与 PL/SQL 混合使用。用户通过参数传递建筑类型,因此删除此:v_type := '&TypeOfBuilding';
  • 同样,您不需要在循环中进行查询,因为光标会选择您需要的信息。
  • 您只是在选择数据,因此不需要 commit

所以修改后的存储过程看起来像这样:

CREATE OR REPLACE PROCEDURE outputBuilding             
  (i_building_type IN VARCHAR2) 
IS

    CURSOR c_building IS
        SELECT DEPT, BUILDINGID, geometry
        FROM OTTAWABUILDINGS
        where dept = i_building_type;
    r_building c_building%ROWTYPE;

    v_long varchar2(28);
    v_lat varchar2(28);

BEGIN

    DBMS_OUTPUT.PUT_LINE('Type of Building: ' ||v_type);
    DBMS_OUTPUT.PUT_LINE ('BUILDINGID   ' || 'LONGITUDE    ' ||'LATITUDE    ' );
    DBMS_OUTPUT.PUT_LINE ('----------   ' || '----------   ' ||'----------    ' );

    FOR r_building IN c_building
    LOOP 
        v_long := r_building.geometry.SDO_POINT.X;
        v_lat := r_building.geometry.SDO_POINT.Y;
        DBMS_OUTPUT.PUT_LINE (r_building.BuildingID || '   ' || v_long || '   ' || v_lat);
    END LOOP;
END outputBuilding;

我将重复我关于没有 Spatial 的声明,所以我无法编译它。因此,它可能包含语法错误,这些错误留作 reader.

的练习。

调用它:

begin
    outputBuilding('Emergency Services POLICE');
end;