在提交插入之前,如何编写更新同一表中的行的触发器?

时间:2013-11-19 18:53:45

标签: mysql sql triggers

我的数据库中有一个名为stockpricehistory的表,它跟踪库存物品的价格变化,并包含以下数据:

  • 股票编号
  • 价格
  • DateStart(介绍特定价格时)
  • DateEnd(当特定价格停止使用时)。

DateStart默认为CURRENT_TIMESTAMP,而DateEnd默认为空,好像没有DateEnd值,那么该行中的价格就是当前库存中的价格。

现在,我怎么能(我通过触发器推测它)使得每当我为特定库存物品插入新行时,它会更新该库存物品的最后一行(即匹配的行)那个库存项,其中DateEnd设置为NULL)以匹配刚刚为要插入的新行的DateStart值,如下所示:

这是表格的初始状态:

  1. 1,2.99,2013-11-19 18:49:24,NULL
  2. 然后,当为该库存项目(ID 1)插入新行时,结果如下:

    1. 1,4.99,2013-11-20 12:00:00,NULL

    2. 1,2.99,2013-11-19 18:49:24,2013-11-20 12:00:00

    3. 理论上,它应该只需要更新一行,因为每个股票ID只有一行没有结束日期,即具有当前价格的行。

      我认为它将通过BEFORE INSERT触发器完成,但我很可能错了。

2 个答案:

答案 0 :(得分:0)

根据documentation

  

在存储的函数或触发器中,不允许修改a   已经被使用(用于读或写)的表   调用函数或触发器的语句。

从插入位置插入后,您始终可以进行更新。

要更新它,你可以这样做:

UPDATE stockpricehistory s
INNER JOIN (
  SELECT stockID,
    MAX(dateStart) AS maxDate
  FROM stockpricehistory
  WHERE StockID = 1
    AND DateEnd IS NULL
  ) a ON s.StockID = a.StockID    
SET s.dateEnd = a.maxDate
WHERE s.DateEnd IS NULL
  AND s.dateStart != a.maxDate

这是为了让你更新其中一个有dateEnd NULL的行,而不是那个有max(dateStart)的行。

希望它有所帮助。

答案 1 :(得分:0)

正如@Filipe Silva所说,你无法修改在该表上调用的触发器中的表。

您可以通过为股票和股票价格历史记录提供单独的表来解决这个问题,这在任何情况下都可能是一个好主意。 stock表每个库存项目保留一行及其当前价格,并且当stockpricehistory中的行插入或更新时,该表上的触发器会保留stock中的记录。

http://sqlfiddle.com/#!2/55c626/1

create table stock (
  stockId int primary key,
  price numeric(5, 2));

create table stockpricehistory (
  stockId int,
  price numeric(5,2),
  dateStart datetime,
  dateEnd datetime);

create trigger t_si before insert on stock
for each row
  insert into stockpricehistory values (new.stockId, new.price, current_timestamp, null);

create trigger t_su before update on stock
for each row begin
  update 
    stockpricehistory 
  set
    dateEnd = current_timestamp
  where
    stockId = new.stockId and
    dateEnd is null;
  insert into stockpricehistory values (new.stockId, new.price, current_timestamp, null);
end;