无法通过存储过程更新表

时间:2018-03-17 05:49:33

标签: sql oracle oracle-sqldeveloper

我正在尝试通过存储过程更新Products表的数量。

我在SQL Developer中使用Oracle数据库。

create or replace procedure alter_products 
(
  pid in number :=''
  ,qty in number :=''
) 
as 
begin
    UPDATE PRODUCTS
    SET P_QUANTITY = (select P_QUANTITY from PRODUCTS where PID = pid) - qty
    WHERE PID = pid;
end alter_products;

存储过程已成功编译,但在尝试运行它时,我收到此错误:

  

ORA-01427:单行子查询返回多行   ORA-06512:在" DB_NAME.ALTER_PRODUCTS",第7行   ORA-06512:第8行

2 个答案:

答案 0 :(得分:2)

您的更新声明应该是这样的:

UPDATE PRODUCTS p
   SET p.P_QUANTITY = p.P_QUANTITY - qty
   WHERE p.PID = p_pid; --argument should have a different name than the column
-- to keep it clean.

编辑:有关详细解释,请参阅@william Robertson的回答。

答案 1 :(得分:1)

参数pid与表中的列具有相同的名称(Oracle标识符名称不区分大小写,因此以大写形式写入其中一个对您没有帮助),所以您有条件的地方

where pid = pid

对于表中的每一行都是如此,因为pid总是等于它自己(除非它是null,并且你在注释中提到它是PK,所以它不能为null)。因此,您需要重命名参数或以前缀:

create or replace procedure alter_products
    ( pid in number
    , qty in number )
as
begin
    update products p
    set    p_quantity =
           ( select p_quantity
             from   products p1
             where  p1.pid = alter_products.pid ) - qty
    where  p.pid = alter_products.pid;
end alter_products;

但是如果products.pidproducts的PK,那么您尝试在子查询中查找的行就是您已有的行,因此子查询是多余的。为什么不呢:

create or replace procedure alter_products
    ( in_pid in products.pid%type
    , in_qty in products.p_quantity%type )
as
begin
    update products p
    set    p_quantity = p_quantity - in_qty
    where  p.pid = in_pid;
end alter_products;

参数的通常命名约定是p_,例如p_pid,但是您的表容易混淆地有一个名为p_quantity的列,因此我使用了in_作为前缀

我还将参数设置为强制参数,因为它们似乎没有任何意义,因为它们在原始版本中是可选的,并将它们锚定到相应的列类型。