【问题标题】:PL/SQL Cursors - Retrieving data from multiple tablesPL/SQL 游标 - 从多个表中检索数据
【发布时间】:2018-10-01 04:38:40
【问题描述】:

我需要输入产品代码作为参数,以检索所述产品和其他信息。我需要比我提供的更多的信息,我已经开始小规模尝试及早调试任何错误,但我不明白为什么下面的代码不起作用。我正在使用 SQLPlus,任何帮助将不胜感激。

CREATE OR REPLACE PROCEDURE product_info(PRODUCT_NO IN CHAR)
AS
    v_product PRODUCTS%ROWTYPE;
    v_suborders  SUBORDERS.ORDER_NO%TYPE;

    CURSOR cur_products IS
    SELECT p.name, p.prod_id, p.description, p.unit_price, s.order_no
    FROM PRODUCTS P, SUBORDERS S
    WHERE p.prod_id = product_no;

BEGIN
OPEN cur_products;
LOOP
FETCH cur_products INTO v_product, v_suborders;

  DBMS_OUTPUT.PUT_LINE('Product Code: ' || v_product.prod_id 
  || ' Name: ' || v_product.name 
  || ' Description: ' || v_product.description
  || ' Price: ' || v_product.unit_price
  || ' Order: ' || v_suborders);
END LOOP;
EXCEPTION
WHEN no_data_found THEN 
DBMS_OUTPUT.PUT_LINE ('Product number does not exist'); 
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('Operation failed  ' || 'SQLCODE: ' || SQLCODE); 
ROLLBACK;
END; 
/

【问题讨论】:

    标签: sql plsql oracle11g sqlplus database-cursor


    【解决方案1】:

    当我们获取一个变量时,它的结构必须与我们正在获取的查询的投影相匹配。或者,如果我们要获取多个变量,我们需要投影中的每列一个变量。你的代码也不行。

    最简单的解决方案是使用光标定义变量,如下所示:

        CURSOR cur_products IS
            SELECT p.name, p.prod_id, p.description, p.unit_price, s.order_no
            FROM PRODUCTS P, SUBORDERS S
            WHERE p.prod_id = product_no;
        v_rec  cur_products%ROWTYPE;
    
    BEGIN
        OPEN cur_products;
        LOOP
        FETCH cur_products INTO v_rec;
        ...
    

    另一种解决方案是使用隐式游标。你可以像这样重写你的代码:

    CREATE OR REPLACE PROCEDURE product_info(PRODUCT_NO IN CHAR)
    AS
    BEGIN
        for v_rec in (SELECT p.name, p.prod_id, p.description, p.unit_price, s.order_no
                      FROM PRODUCTS P, SUBORDERS S
                      WHERE p.prod_id = product_no )
        LOOP
          DBMS_OUTPUT.PUT_LINE('Product Code: ' || v_rec.prod_id 
          || ' Name: ' || v_rec.name 
          || ' Description: ' || v_rec.description
          || ' Price: ' || v_rec.unit_price
          || ' Order: ' || v_rec.odrer_no);
        END LOOP;
    EXCEPTION
        WHEN no_data_found THEN 
        DBMS_OUTPUT.PUT_LINE ('Product number does not exist'); 
       WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('Operation failed  ' || 'SQLCODE: ' || SQLCODE); 
        ROLLBACK;
    END; 
    /
    

    顺便说一句,您的查询在 PRODUCTS 和 SUBORDERS 之间没有连接,因此您的结果集将是一个产品(交叉连接)或两个表中的所有记录。几乎可以肯定你不想那样。

    此外,不要在异常处理程序中重新引发异常是不好的做法(除了一些边缘情况)。像这样的一段玩具代码没关系,但不要落入坏习惯。

    【讨论】:

    • 感谢您的解决方案,但请更新它以在第一个解决方案中使用 %ROWTYPE 而不是 %TYPE。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多