即使更改ID后,更新查询也会添加旧数据

时间:2019-02-07 17:26:23

标签: oracle stored-procedures plsql

创建一个过程,该过程接受2个代表inv_id的参数以及价格上涨的百分比。伪函数应首先使用新价格更新数据库,然后返回新价格和现有数量。 创建另一个名为L4Q3的过程,该过程接受inv_id和价格上涨的百分比。该过程将使用旧过程来显示新的库存价值(提示:价值=价格X现有数量)

CREATE OR REPLACE PROCEDURE ex3 (p_inv_id IN NUMBER, p_change IN NUMBER, 
p_new_price OUT NUMBER, p_qoh OUT NUMBER)
AS
v_new_price NUMBER(6,2);
v_qoh NUMBER(6,2);
BEGIN
UPDATE inventory 
SET inv_price = (SELECT inv_price + (inv_price*(p_change/100))
FROM inventory
WHERE inv_id = p_inv_id);
COMMIT;
SELECT inv_price, inv_qoh
INTO p_new_price, p_qoh
FROM inventory
WHERE inv_id = p_inv_id;
COMMIT;
v_qoh := p_qoh;
v_new_price := p_new_price;
DBMS_OUTPUT.PUT_LINE('hello'||v_new_price);
END;
/ 


CREATE OR REPLACE PROCEDURE use_ex3 ( p_inv_id NUMBER, p_change NUMBER)
AS
v_new_price NUMBER(6,2);
v_qoh NUMBER(6,2);
v_value NUMBER(10,2);
BEGIN
ex3(p_inv_id, p_change, v_new_price, v_qoh);
v_value := v_new_price*v_qoh;
DBMS_OUTPUT.PUT_LINE('value is:'||v_value);
END; 
/

1 个答案:

答案 0 :(得分:1)

考虑如下转换程序:

SQL> set serveroutput on;
SQL> CREATE OR REPLACE PROCEDURE ex3(p_inv_id    IN  inventory.inv_id%type,
                                     p_change    IN  NUMBER,
                                     p_new_price OUT inventory.inv_price%type,
                                     p_qoh       OUT inventory.inv_qoh%type) AS
BEGIN
  UPDATE inventory
     SET inv_price = inv_price * ( 1 + (p_change / 100) )
   WHERE inv_id = p_inv_id
   RETURNING inv_price, inv_qoh 
        INTO p_new_price, p_qoh;

  DBMS_OUTPUT.PUT_LINE('hello '|| p_new_price);
END;
/
SQL> CREATE OR REPLACE PROCEDURE use_ex3(p_inv_id inventory.inv_id%type, p_change NUMBER) AS
        v_new_price inventory.inv_price%type;
        v_qoh       inventory.inv_qoh%type;
        v_value     NUMBER(10, 2);
BEGIN
   ex3(p_inv_id, p_change, v_new_price, v_qoh);
   v_value := v_new_price * v_qoh;
   DBMS_OUTPUT.PUT_LINE('value is: '|| v_value);
END;

核心问题是

WHERE inv_id = p_inv_id语句中缺少过滤器UPDATE。    即不只限于一个inv_id

此外考虑以下事项将使您的代码更好:

  • 不需要SET子句的子查询,只需分配一个inv_price = inv_price * ( 1 + (p_change / 100) )
  • 最好将列的变量类型定义为 inventory.<column_name>%type
  • 不需要额外的局部变量,例如v_new_priceout 诸如p_new_price之类的过程的参数可以用作 分配目标
  • 不需要在SELECT之后的
  • UPDATE语句,使用RETURNING INTO就足够了
  • 不要忘记使用set serveroutput on打印出结果

  • 我认为在单个程序中排除commit是一个好习惯 提供交易完整性以确保数据一致性的单元 DML的表格。建议在呼叫者内只保留一个commit 所有语句和程序单元末尾的应用程序。