首页 > 解决方案 > 过程中的光标并调用过程

问题描述

需要帮助了解如何在过程中使用游标变量。并使用匿名块调用过程 6 次来运行一组查询。试图弄清楚这一点让我很头疼,在此先感谢您的帮助。

    CREATE OR REPLACE PROCEDURE City_Jail_SP
     (lv_query IN NUMBER,
      lv_out out VARCHAR2)
     AS
     cursor qry_lvl IS
BEGIN
   OPEN qry_lvl;
   LOOP
   FETCH INTO
    IF chioce = 1 THEN SELECT AVG(COUNT(*))
    FROM crime_officers
    GROUP BY officer_id;
    
    ELSIF chioce = 2 THEN SELECT MIN(Fine_amount)
    FROM Crime_charges;  
    
    ELSIF chioce = 3 THEN COLUMN (hearing_date-date_charged) HEADING DAYS
    SELECT crime_id, Classification, date_charged, hearing_date,
    ( hearing_date-date_charged)
    FROM crimes
    WHERE hearing_date-date_charged >14;
    
    ELSIF choice = 4 THEN select cl.criminal_id, cl.last, cl.first, cc.Crime_code, cc.Fine_amount
    FROM criminals cl
    JOIN crimes cr
    ON cr.criminal_id = cl.criminal_id
    JOIN crime_charges cc
    ON cc.crime_id = cr.crime_id;
   
    ELSIF chioce = 5 THEN SELECT LAST, FIRST
    FROM officers JOIN crime_officers USING (officer_id)
    JOIN crimes USING (crime_id)
    GROUP BY (LAST, FIRST)
    HAVING COUNT(crime_id)>(SELECT AVG(COUNT(crime_id))
    FROM crimes JOIN crime_officers using (crime_id)
    GROUP BY officer_id);
    
    ELSIF choice = 6 THEN SELECT DISTINCT FIRST, LAST
    FROM criminals JOIN crimes USING (criminal_id)
    JOIN crime_charges USING (crime_id)
    GROUP BY (FIRST, LAST)
    HAVING COUNT(Criminal_ID)<(SELECT AVG(COUNT(Criminal_ID))
    FROM crimes JOIN criminals USING (Criminal_ID)
    GROUP BY Criminal_ID)
    ORDER BY FIRST, LAST;
END IF;
close qry_lvl;
END;    
/ 

标签: oracleif-statementstored-proceduresplsqlcursor

解决方案


看起来您编写的代码应该被删除,以便您可以重新开始。

  • 你开始声明一个游标,但从未完成它
  • 您没有声明任何游标变量来将游标的值存储到其中
    • 无论如何,您宁愿切换到游标 FOR 循环,因为它更易于使用
  • 你正在进入......什么?
  • 没有end loop
  • 您声明INOUT参数,但从未使用过它们中的任何一个
  • 中有一堆select语句IF,几乎所有语句都返回不同的数据集。此外,其中任何一个都没有into条款。PL/SQL 需要它,所以你必须声明很多局部变量
  • 错别字,错别字,错别字……是它chioce还是choice
  • column ... heading days件事应该怎么做?听起来像是与 SQL*Plus 相关的东西

也许您实际上想要使用 refcursors。这是一个基于 Scott 模式的简单示例。根据部门编号,我返回不同的数据集。

样本数据:

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

程序(有点模拟您尝试做的事情):

SQL> CREATE OR REPLACE PROCEDURE p_test (par_deptno  IN     NUMBER,
  2                                      par_rc         OUT SYS_REFCURSOR)
  3  IS
  4     l_dname  dept.dname%TYPE;
  5  BEGIN
  6     SELECT dname
  7       INTO l_dname
  8       FROM dept
  9      WHERE deptno = par_deptno;
 10
 11     IF l_dname = 'ACCOUNTING'
 12     THEN
 13        OPEN par_rc FOR SELECT d.dname, e.ename, e.job
 14                          FROM dept d
 15                               JOIN emp e
 16                                  ON     e.deptno = d.deptno
 17                                     AND d.deptno = par_deptno;
 18     ELSIF l_dname = 'SALES'
 19     THEN
 20        OPEN par_rc FOR SELECT e.ename, e.job, e.sal
 21                          FROM emp e
 22                         WHERE e.job = 'SALESMAN';
 23     END IF;
 24  END;
 25  /

Procedure created.

测试:

SQL> var l_rc refcursor
SQL> exec p_test(10, :l_rc);

PL/SQL procedure successfully completed.

SQL> print :l_rc

DNAME          ENAME      JOB
-------------- ---------- ---------
ACCOUNTING     CLARK      MANAGER
ACCOUNTING     KING       PRESIDENT
ACCOUNTING     MILLER     CLERK

SQL> exec p_test(30, :l_rc);

PL/SQL procedure successfully completed.

SQL> print :l_rc

ENAME      JOB              SAL
---------- --------- ----------
ALLEN      SALESMAN        1600
WARD       SALESMAN        1250
MARTIN     SALESMAN        1250
TURNER     SALESMAN        1500

SQL>

请阅读一些基本的 PL/SQL 文档,你不能开始编码和编写自己的语法。这是Oracle 12c PL/SQL 语言参考。你会花一些时间来阅读它,但是 - 至少 - 你会知道你在做什么(我希望如此)。


推荐阅读