PL/SQL 游标 - 从多个表中检索数据
PL/SQL Cursors - Retrieving data from multiple tables
我需要输入产品代码作为参数来检索所述产品和其他信息。我需要比我提供的更多的信息,我已经开始小规模尝试尽早调试任何错误,但我不明白为什么下面的代码不起作用。我正在使用 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;
/
当我们获取一个变量时,它的结构必须与我们正在获取的查询的投影相匹配。或者,如果我们要获取多个变量,我们需要在投影中每一列有一个变量。您的代码也没有。
最简单的解决方案是使用光标定义变量,如下所示:
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 之间没有连接,因此您的结果集将是一个产品(交叉连接)或两个表中的所有记录。几乎可以肯定你不想要那个。
此外,不在异常处理程序中重新引发异常是不好的做法(除了某些边缘情况)。像这样的玩具代码没关系,但不要养成坏习惯。
我需要输入产品代码作为参数来检索所述产品和其他信息。我需要比我提供的更多的信息,我已经开始小规模尝试尽早调试任何错误,但我不明白为什么下面的代码不起作用。我正在使用 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;
/
当我们获取一个变量时,它的结构必须与我们正在获取的查询的投影相匹配。或者,如果我们要获取多个变量,我们需要在投影中每一列有一个变量。您的代码也没有。
最简单的解决方案是使用光标定义变量,如下所示:
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 之间没有连接,因此您的结果集将是一个产品(交叉连接)或两个表中的所有记录。几乎可以肯定你不想要那个。
此外,不在异常处理程序中重新引发异常是不好的做法(除了某些边缘情况)。像这样的玩具代码没关系,但不要养成坏习惯。