创建MYSQL触发器语句时出错代码:1064

创建MYSQL触发器语句时出错代码:1064,mysql,sql,triggers,Mysql,Sql,Triggers,我正在尝试创建一个触发器,将input\u qty的值与shelf\u qty的值相加,然后将input\u 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 :=

我正在尝试创建一个触发器,将
input\u qty
的值与
shelf\u qty
的值相加,然后将
input\u 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;
通过修改Gordon的答案,我成功地使它“起作用”,但触发器创建了一个无限循环,并且不会更新任何内容

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 ;
UPDATE `products`
SET `qty` = CASE
    WHEN `sku` = 'foo' THEN `qty` + qty1
    WHEN `sku` = 'bar' THEN `qty` + qty2
    ...
END;
<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}...]
UPDATE product t
   SET t.qty = t.qty 
             + CASE t.sku 
                 WHEN 'fee' THEN 1 
                 WHEN 'fi' THEN 2 
                 ELSE 0
               END
 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 ( ? , ? , ? )
但问题是,我的服务器上组装的sql查询如下所示:

UPDATE product t
SET t.shelf_qty = t.shelf_qty + 1 
WHERE t.id = 1 ;
UPDATE `products`
SET `qty` = CASE
    WHEN `sku` = 'foo' THEN `qty` + qty1
    WHEN `sku` = 'bar' THEN `qty` + qty2
    ...
END;
<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}...]
UPDATE product t
   SET t.qty = t.qty 
             + CASE t.sku 
                 WHEN 'fee' THEN 1 
                 WHEN 'fi' THEN 2 
                 ELSE 0
               END
 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 ( ? , ? , ? )
更新2 查询的数据从如下表单中收集:

UPDATE product t
SET t.shelf_qty = t.shelf_qty + 1 
WHERE t.id = 1 ;
UPDATE `products`
SET `qty` = CASE
    WHEN `sku` = 'foo' THEN `qty` + qty1
    WHEN `sku` = 'bar' THEN `qty` + qty2
    ...
END;
<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}...]
UPDATE product t
   SET t.qty = t.qty 
             + CASE t.sku 
                 WHEN 'fee' THEN 1 
                 WHEN 'fi' THEN 2 
                 ELSE 0
               END
 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 ( ? , ? , ? )
这听起来真的很奇怪——你有一个列总是0?。但是,如果希望将当前行中的值设置为
0
,则在更新之前使用
触发器:

DELIMITER $$
CREATE TRIGGER inventory_update
BEFORE UPDATE ON `products`
FOR EACH ROW
BEGIN
    IF OLD.`input_qty` > 0 THEN
        DECLARE new_shelf_qty INT(11);
        SET new_shelf_qty = OLD.input_qty + OLD.shelf_qty;
        SET new.input_qty = 0;
    END IF;
END $$
DELIMITER;
这听起来真的很奇怪——你有一个列总是0?。但是,如果希望将当前行中的值设置为
0
,则在更新之前使用
触发器:

DELIMITER $$
CREATE TRIGGER inventory_update
BEFORE UPDATE ON `products`
FOR EACH ROW
BEGIN
    IF OLD.`input_qty` > 0 THEN
        DECLARE new_shelf_qty INT(11);
        SET new_shelf_qty = OLD.input_qty + OLD.shelf_qty;
        SET new.input_qty = 0;
    END IF;
END $$
DELIMITER;

触发器无法对触发器语句中引用的表执行DML操作。MySQL参考手册中记录了此限制

换句话说:
updateonproduct
触发器的主体不能针对
product
表发出
UPDATE
语句

这是触发器定义的错误之一

除此之外,还有一些语法问题。每行的
后面应该跟有
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语法,希望事情能以某种方式解决

我们想要实现什么

 UPDATE product SET input_qty = 5 , shelf_quantity = 11 WHERE id = 1;

如果我们想通过提供的某个值“增加”
货架数量
,那么标准模式应该是这样的(没有任何触发):

我们引用
货架数量
列的当前值,并向其中添加1,然后将该新值分配回
货架数量


更新1


表达式可以在
大小写
表达式中的
然后
关键字后面使用。允许在表达式中进行加法运算

为“组合sql查询”(assembled sql query)显示的语法是有效的;我们希望在
结束
之前有一个ELSE数量,因为在没有
WHERE
子句(更新表中的每一行)的情况下执行
更新
有点奇怪(不是非法的,只是不寻常)

语法看起来有效,但我无法验证语义,例如
sku
qty
是否是有效的列引用,等等。)

就我个人而言,我会这样做更新操作(添加到问题中):

UPDATE product t
SET t.shelf_qty = t.shelf_qty + 1 
WHERE t.id = 1 ;
UPDATE `products`
SET `qty` = CASE
    WHEN `sku` = 'foo' THEN `qty` + qty1
    WHEN `sku` = 'bar' THEN `qty` + qty2
    ...
END;
<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}...]
UPDATE product t
   SET t.qty = t.qty 
             + CASE t.sku 
                 WHEN 'fee' THEN 1 
                 WHEN 'fi' THEN 2 
                 ELSE 0
               END
 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
什么。我的假设是,我们将保持这些行上的
qty
值不变。我只是不理解这个用例中触发器的好处


更新2

“据我所知,之后的操作是不允许的”[在CASE表达式中]

这取决于操作的含义。CASE表达式的语法为:

 CASE WHEN expr1 THEN expr2 WHEN expr3 THEN expr4 ... ELSE expr5 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 product t
SET t.shelf_qty = t.shelf_qty + 1 
WHERE t.id = 1 ;
UPDATE `products`
SET `qty` = CASE
    WHEN `sku` = 'foo' THEN `qty` + qty1
    WHEN `sku` = 'bar' THEN `qty` + qty2
    ...
END;
<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}...]
UPDATE product t
   SET t.qty = t.qty 
             + CASE t.sku 
                 WHEN 'fee' THEN 1 
                 WHEN 'fi' THEN 2 
                 ELSE 0
               END
 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 ( ? , ? , ? )
或者使用位置占位符,如下所示:

UPDATE product t
SET t.shelf_qty = t.shelf_qty + 1 
WHERE t.id = 1 ;
UPDATE `products`
SET `qty` = CASE
    WHEN `sku` = 'foo' THEN `qty` + qty1
    WHEN `sku` = 'bar' THEN `qty` + qty2
    ...
END;
<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}...]
UPDATE product t
   SET t.qty = t.qty 
             + CASE t.sku 
                 WHEN 'fee' THEN 1 
                 WHEN 'fi' THEN 2 
                 ELSE 0
               END
 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}
组合动态扩展


跟进

这一切都是使用触发器解除提示的。这不是处理需求的最佳方式。但是,为了回答被问到的问题

如果我们必须使用触发器,给定:

 product 
 id  sku  input_qty   shelf_qty
 --  ---  ---------   ---------
  3  fo           0          41
  4  fum          0          11

然后定义此触发器:

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

但我觉得用扳机做这件事没有意义。我没有看到好处。它似乎不必要地、令人困惑地修改了
更新的正常行为

触发器无法对触发器语句中引用的表执行DML操作。MySQL参考手册中记录了此限制

换句话说:
updateonproduct
触发器的主体不能针对
product
表发出
UPDATE
语句

这是触发器定义的错误之一

除此之外,还有一些语法问题。每行的
后面应该跟有
BEGIN
关键字(例外情况是触发器是一条语句)

IF
语句应以
END IF
结束(不仅仅是
END

但我们必须重新思考整个方法,而不仅仅是修改语法


我们走吧