我正在尝试创建一个将input_qty
的值添加到shelf_qty
的值的触发器,然后将input_qty
设置为0。
这是我的尝试:
DELIMITER $$
CREATE TRIGGER inventory_update
AFTER UPDATE ON `products`
FOR EACH ROW
IF OLD.`input_qty` > 0 THEN
BEGIN
DECLARE new_shelf_qty INT(11);
SET new_shelf_qty := OLD.`input_qty` + OLD.`shelf_qty`;
UPDATE `products` SET `input_qty` = 0, `shelf_qty` = new_shelf_qty;
END $$
DELIMITER;
通过修改戈登的答案,我设法使它“起作用”,但是触发器创建了一个无限循环,并且不更新任何内容。
DELIMITER $$
CREATE TRIGGER inventory_update
BEFORE UPDATE ON `products`
FOR EACH ROW
BEGIN
DECLARE new_shelf_qty INT(11);
IF OLD.`input_qty` > 0 THEN
SET new_shelf_qty = OLD.input_qty + OLD.shelf_qty;
SET new.input_qty = 0;
END IF;
END $$
更新资料
我会用这样的东西:
UPDATE product t
SET t.shelf_qty = t.shelf_qty + 1
WHERE t.id = 1 ;
但是问题是我的服务器上的汇编sql查询看起来像这样:
UPDATE `products`
SET `qty` = CASE
WHEN `sku` = 'foo' THEN `qty` + qty1
WHEN `sku` = 'bar' THEN `qty` + qty2
...
END;
更新2
查询数据是从如下形式收集的:
<input id="sku1" type="number">
<input id="sku2" type="number">
<input id="sku3" type="number">
...
<input type="submit" value="Save">
print(POST body) //[{sku1:qty1}, {sku2:qty2}, {sku3:qty3}...]
进行更改后,表单仅提交项目/数量对象列表。数量字段是增加库存量的数量,而不是实际数量。
据我所知,
THEN
之后的操作是不允许的,我想到的使用1个查询实现此操作的唯一方法是使用我尝试的触发器(这显然行不通)。任何建议将不胜感激:)接受的答案:
这为我工作:
UPDATE products t
SET t.qty = t.qty
+ CASE t.sku
WHEN 'foo' THEN 1
WHEN 'bar' THEN 2
ELSE 0
END
WHERE t.sku IN ('foo','bar')
最佳答案
TRIGGER无法对触发语句中引用的表执行DML操作。 MySQL参考手册中记录了此限制。
换句话说,UPDATE ON product
触发器的主体无法针对UPDATE
表发出product
语句。
这是触发器定义出错的原因之一。
除此之外,还有一些语法问题。 FOR EACH ROW
后面应带有BEGIN
关键字(该例外是作为单个语句的触发器。)IF
语句应使用END IF
关闭(而不仅仅是END
)
但是我们必须在这里重新考虑整个方法,而不仅仅是修复语法。
让我们通过示例来了解我们正在尝试实现的目标。
假设我们有表product
id mfr input_qty shelf_qty
-- --- --------- ---------
1 fee 3 39
2 fi 0 7
发出以下语句后,表的预期状态是什么:
UPDATE product SET mfr = 'fo' WHERE id = 1 ;
UPDATE product SET input_qty = 4 WHERE id = 2 ;
也就是说,如果不触发任何触发器,我们可以预测这些语句的结果。但是触发器应该如何影响行为,修改这些语句的结果?我们需要触发器来完成什么?
UPDATE product SET input_qty = 5 , shelf_quantity = 11 WHERE id = 1;
如果没有规范,我们将无法编写代码来执行某些操作。我们需要进行一些测试,以验证我们编写的代码正在执行应做的工作。否则,我们只是抛出SQL语法,希望事情能以某种方式解决。
我们要完成什么?
如果我们想通过某些提供的值“递增”
shelf_qty
,那么规范模式将是这样的(没有任何触发器): UPDATE product t
SET t.shelf_qty = t.shelf_qty + 1
WHERE t.id = 1 ;
我们引用
shelf_qty
列的当前值,并将其添加1,然后将该新值分配回shelf_qty
列。更新1
可以在
THEN
表达式中的CASE
关键字之后使用表达式。允许在表达式中进行加法运算。为“汇编的sql查询”显示的语法(有效;我们希望在
END
之前有一个ELSE数量,因为执行UPDATE
而没有WHERE
子句(更新表中的每一行)。该语法看起来有效,但我无法验证其语义,例如
sku
和qty
是否为有效的列引用,等等。)就个人而言,我将执行UPDATE操作(添加到问题中),如下所示:
UPDATE product t
SET t.qty = t.qty
+ CASE t.sku
WHEN 'fee' THEN 1
WHEN 'fi' THEN 2
ELSE 0
END
但是我不确定当未列出
qty
时应该分配给sku
的内容。我的假设是我们将那些行上的qty
值保持不变。我只是不了解此用例的触发器的好处,更新2
“据我所知,不允许在THEN之后进行操作”(在CASE表达式中)
这取决于操作的含义。 CASE表达式的语法为:
CASE WHEN expr1 THEN expr2 WHEN expr3 THEN expr4 ... ELSE expr5 END
要么:
CASE expr1 WHEN expr2 THEN expr3 WHEN expr4 THEN expr5 ... ELSE expr6 END
其中
exprN
是表达式。可以在表达式中使用加法运算。我们可以这样编写更新:
UPDATE products t
SET t.qty = CASE
WHEN t.sku = 'foo' THEN t.qty + 1
WHEN t.sku = 'bar' THEN t.qty + 2
ELSE t.qty
END
WHERE t.sku IN ('foo','bar')
但是我们可以通过这样表达来使将来的读者更容易辨别我们的意图
UPDATE products t
SET t.qty = t.qty
+ CASE t.sku
WHEN 'foo' THEN 1
WHEN 'bar' THEN 2
ELSE 0
END
WHERE t.sku IN ('foo','bar')
概括起来很简单。应用程序使用命名占位符生成的SQL文本如下所示:
UPDATE products t
SET t.qty = t.qty
+ CASE t.sku
WHEN :sku1 THEN :qty1
WHEN :sku2 THEN :qty2
WHEN :sku3 THEN :qty3
ELSE 0
END
WHERE t.sku IN ( :wsku1 , :wsku2 , :wsku3 )
或使用位置占位符,如下所示:
UPDATE products t
SET t.qty = t.qty
+ CASE t.sku
WHEN ? THEN ?
WHEN ? THEN ?
WHEN ? THEN ?
ELSE 0
END
WHERE t.sku IN ( ? , ? , ? )
我们可以看到如何针对可变数量的
{sku:qty}
组合动态扩展该语句跟进
所有这些都不建议使用TRIGGER。这不是处理需求的最佳方法。但是,要回答所提出的问题...
如果我们必须使用触发器,则给出:
product
id sku input_qty shelf_qty
-- --- --------- ---------
3 fo 0 41
4 fum 0 11
和
UPDATE product t
SET t.input_qty = CASE t.sku
WHEN 'fo' THEN 1
WHEN 'fum' THEN 2
ELSE 0
END
WHERE t.sku IN ('fo','fum')
然后定义此触发器:
DELIMITER $$
CREATE TRIGGER product_bu
BEFORE UPDATE ON product
FOR EACH ROW
BEGIN
IF NEW.input_qty > 0 THEN
-- add provided value of input_qty to shelf_qty
SET NEW.shelf_qty = HEW.shelf_qty + NEW.input_qty;
-- set input_qty to zero
SET NEW.input_qty = 0;
END IF;
END$$
预期结果将是:
product
id sku input_qty shelf_qty
-- --- --------- ---------
3 fo 0 42
4 fum 0 13
但是,使用触发器来执行此操作对我来说没有任何意义。我没有看到好处。它似乎不必要地且令人困惑地修改了
UPDATE
的正常行为。
关于mysql - 创建MYSQL触发器语句时错误代码:1064,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54674654/