简体   繁体   English

PL / SQL更新触发器更新所有行

[英]PL/SQL Update Trigger Updates All Rows

New to working with PL/SQL and trying to create a statement level trigger that will change the 'Reorder' value to 'Yes' when the product quantity (p_qoh) is either less than 10 or less than two times the product minimum (p_min). 使用PL / SQL并尝试创建语句级别触发器的新手,当产品数量(p_qoh)小于产品最小值(p_min)的10或两倍时,该触发器将把'Reorder'值更改为'Yes' 。 And if that's not the case, then to change the 'Reorder' value to 'No'. 如果不是这种情况,则将“重新排序”值更改为“否”。 My problem is that when I perform an update for a specific product, it changes the reorder value of all rows instead of the one I'm specifying. 我的问题是,当我为特定产品执行更新时,它将更改所有行的重新排序值,而不是我指定的行。 Can't seem to figure out where I'm going wrong, think I've been staring at it too long, any help is greatly appreciated. 似乎无法弄清楚我要去哪里,以为我盯着它看了太久了,对您的帮助将不胜感激。

CREATE OR REPLACE TRIGGER TRG_AlterProd
AFTER INSERT OR UPDATE OF p_qoh, p_min ON product
DECLARE
  v_p_min  product.p_min%type;
  v_p_qoh  product.p_qoh%type;
CURSOR v_cursor IS SELECT p_min, p_qoh FROM product;
BEGIN
  OPEN v_cursor;
LOOP
  FETCH v_cursor INTO v_p_min, v_p_qoh;
  EXIT WHEN v_cursor%NOTFOUND;
IF v_p_qoh < (v_p_min * 2) OR v_p_qoh < 10 THEN
 UPDATE product SET p_reorder = 'Yes';
ELSE
  UPDATE product SET p_reorder = 'No';
END IF;
END LOOP;
END;
/

The update command : 更新命令:

UPDATE product SET p_reorder = 'Yes';

updates all of your rows because you are not specifying a WHERE clause. 更新所有行,因为您没有指定WHERE子句。 What you can do is to retrieve the product's id ( product_id ) using your cursor and save it so that you would use it this way: 您可以做的是使用游标检索产品的ID( product_id )并将其保存,以便以这种方式使用它:

UPDATE product SET p_reorder = 'Yes' WHERE id = product_id;

Whoaa, this is not how you do triggers. 哇,这不是您触发的方式。

1 - Read the Oracle Trigger Documentation 1-阅读Oracle触发器文档

2 - (almost) Never do a commit in a trigger. 2-(几乎)永远不要在触发器中进行提交。 That is the domain of the calling application. 那是调用应用程序的域。

3 - There is no need to select anything related to product. 3-无需选择与产品相关的任何内容。 You already have the product record at hand with the :new and :old pseudo records. 您已经有了带有:new和:old伪记录的产品记录。 Just update the column value in :new as needed. 只需根据需要更新:new中的列值。 Example below (not checked for syntax errors, etc.); 下面的示例(未检查语法错误等);

CREATE OR REPLACE TRIGGER TRG_AlterProd
BEFORE INSERT OR UPDATE OF p_qoh, p_min ON product
FOR EACH ROW
BEGIN

IF :new.p_qoh < (:new.p_min * 2) OR :new.p_qoh < 10 THEN
  :new.p_reorder = 'Yes';
ELSE
  :new p_reorder = 'No';
END IF;
END;

@StevieP, If you need to commit inside a trigger, you may want to consider doing it as Autonomous Transaction . @StevieP,如果需要在触发器内提交,则可能要考虑将其作为“ 自主事务”来进行

Also, sorry if my understanding of your problem statement is wrong, but your it sounded to me like a row level trigger - are you only updating the current row or are you scanning the entire table to change status on several rows? 另外,如果我对您的问题说明的理解是错误的,对不起,但是您的声音听起来像行级触发器-您是仅更新当前行还是要扫描整个表以更改几行的状态? If it's on current row, @OldProgrammer's solution seems right. 如果在当前行上,@ OldProgrammer的解决方案似乎正确。

And I am just curious, if you do an UPDATE statement inside the trigger on the same table, wouldn't it generate (recursive) trigger(s)? 我只是很好奇,如果您在同一张表的触发器内执行UPDATE语句,它不会生成(递归)触发器吗? I haven't done statement triggers like this, so sorry if this is not the expected trigger behavior. 我还没有完成像这样的语句触发器,所以很抱歉,如果这不是预期的触发器行为。

To me a statement trigger would make more sense, if the trigger was on say, sales table, when a product is sold (inserted into sales table), it will trigger the corresponding product id records to be updated (to REORDER) in Product table. 对我来说,语句触发器会更有意义,如果该触发器位于销售表上,则当产品售出(插入到销售表中)时,它将触发要更新的产品ID记录(到REORDER)。 。 That will prevent recursion danger also. 那也将防止递归危险。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM