mysql - 创建MYSQL触发器语句时错误代码:1064

标签 mysql sql triggers

我正在尝试创建一个将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子句(更新表中的每一行)。

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

就个人而言,我将执行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/

相关文章:

mysql - 如何更改数据库中的日期

c# - 使用方法 'mysql_native_password' 对主机或用户进行身份验证失败

mysql - 有没有办法将 JSON 字段中的数组与 MySQL 中的 JSON_ARRAY 进行比较?

mysql - 创建触发器将旧数据插入新表

mysql - 在每次更新时触发触发,而不仅仅是一列

mysql - 定义 MYSQL 触发器的语法错误

php - 将选择保存到数据库中

mysql - 先有鸡还是先有蛋的电子邮件

PHP 如何在结果的每 10 行回显不同的图像

sql - Postgres 在连接时无法识别 CAST 的问题