【问题标题】:MariaDB : Trigger keeps getting syntax error after insertMariaDB:插入后触发器不断出现语法错误
【发布时间】:2021-02-22 10:01:07
【问题描述】:

我有两张桌子。表 vitamin 包含列 vitamin_nameprice。表 vitamin_variety 包含列 price_varietyprice_variety_extreme。我想创建一个 AFTER INSERT 触发器,如果​​ vitamin_name 的值包含 extremeprice_variety_extreme 并且不包含 extremeprice_variety 中,它将插入 pricevitamin

这就是我的意思,如果我将它插入vitamin,价格将输入到vitamin_variety

table = vitamin
+----------------+-------+
|  vitamin_name  | price |
+----------------+-------+
| extreme pill 1 |    10 |
| pill 1         |     5 |
| extreme pill 2 |    20 |
| pill 2         |    10 |
+----------------+-------+
 table = vitamin_variety
+---------------+-----------------------+
| price_variety | price_variety_extreme |
+---------------+-----------------------+
|             5 |                    10 |
|            10 |                    20 |
+---------------+-----------------------+

我的查询不断出现语法错误。它一直在说

#1064 - 您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,以了解要使用的正确语法 在第 5 行的 '' 附近

怎么了?

create trigger vitamin_ain after insert on vitamin
for each ROW
if vitamin.vitamin_name like 'extreme%' then 
    update vitamin_variety 
    set price_variety_extreme = new.price_variety_extreme;
else if vitamin.vitamin_name not like 'extreme%' then 
    update vitamin_variety
    set price_variety = new.price_variety;
end if;

【问题讨论】:

    标签: mariadb


    【解决方案1】:

    存在一些语法问题和其他情况,但触发器内部的条件可能类似于以下代码:

    首先,(不是对或错)else if可以简化为else。如果第一个条件发现极端,则无需反向检查 not like 极端。 (除非一些奇怪的要求需要处理)

    当然,如果对您更有意义,请随时保持else if 检查原样,但我使用了以下代码:

    if new.vitamin_name like 'extreme%' then 
        update vitamin_variety 
        set price_variety_extreme = new.price;
    else  
        update vitamin_variety
        set price_variety = new.price;
    end if
    

    “语法问题”:

    1. 在if条件下,将vitamin.vitamin_name改为new.vitamin。来自触发器插入操作的列引用自 new,而不是表名。
    2. 如果保留您原来的else if,需要更改第1 项中提到的相同vitamin.vitamin_name 引用。
    3. 维生素插入中不存在引用 new.price_variety_extremenew.price_variety(这些列不在维生素中),但 new.price 存在,而其他 vitamin 列。

    “其他情况”:

    • 如果vitamin_variety 表中没有任何行,则不会发生更新,因为没有要更新的行。这种情况会使它看起来好像触发器不工作,但触发器没有什么可以更新的。
    • 使用当前信息无法实现对vitamin_variety 的期望输出。更新会将一个或另一个的所有列设置为最后插入的价格,因为没有唯一的行引用。 (没有 WHERE 子句来限制更新哪些行)

    以下是一些交互示例:

    正如提到的第一种情况,vitamin_variety 表中没有行,所以我添加了一个:

    MariaDB [test]> insert into vitamin_variety (price_variety, price_variety_extreme) values (0, 0);
    Query OK, 1 row affected (0.08 sec)
    
    MariaDB [test]> select * from vitamin_variety;
    +----+---------------+-----------------------+
    | id | price_variety | price_variety_extreme |
    +----+---------------+-----------------------+
    |  1 |             0 |                     0 |
    +----+---------------+-----------------------+
    1 row in set (0.00 sec)
    

    然后,将触发器添加到vitamin,插入几行:

    MariaDB [test]> insert into vitamin( vitamin_name, price ) values ('pilly 5', 7);
    Query OK, 1 row affected (0.10 sec)
    
    MariaDB [test]> insert into vitamin( vitamin_name, price ) values ('extreme pill 5', 3);
    Query OK, 1 row affected (0.12 sec)
    

    显示那些插入:

    MariaDB [test]> select * from vitamin;
    +----+----------------+-------+
    | id | vitamin_name   | price |
    +----+----------------+-------+
    |  8 | pilly 5        |     7 |
    |  9 | extreme pill 5 |     3 |
    +----+----------------+-------+
    2 rows in set (0.00 sec)
    

    vitamin_variety 表中显示触发的价格更新:

    MariaDB [test]> select * from vitamin_variety;
    +----+---------------+-----------------------+
    | id | price_variety | price_variety_extreme |
    +----+---------------+-----------------------+
    |  1 |             7 |                     3 |
    +----+---------------+-----------------------+
    1 row in set (0.00 sec)
    

    =====

    编辑:

    鉴于此vitamin_variety 表结构,实现目标的一种可能方法:

    CREATE TABLE `vitamin_variety` (
     `pill_name` varchar(25) NOT NULL,
     `price_variety` int(11) NOT NULL DEFAULT '0',
     `price_variety_extreme` int(11) NOT NULL DEFAULT '0',
     UNIQUE KEY `pill_name` (`pill_name`)
    );
    

    然后将vitamin表触发条件改为:

    if new.vitamin_name like 'extreme%' then 
        insert into vitamin_variety (pill_name, price_variety_extreme)
        values (replace(new.vitamin_name, 'extreme ', ''), new.price) 
        on duplicate key update price_variety_extreme = new.price;
    else  
        insert into vitamin_variety (pill_name, price_variety)
        values (new.vitamin_name, new.price)
        on duplicate key update price_variety = new.price;
    end if
    

    然后根据您原来的vitamin 表详细信息运行插入 SQL:

    MariaDB [test]> insert into vitamin (vitamin_name, price) values ('extreme pill 1', 10);
    Query OK, 1 row affected (0.09 sec)
    
    MariaDB [test]> insert into vitamin (vitamin_name, price) values ('pill 1', 5);
    Query OK, 1 row affected (0.16 sec)
    
    MariaDB [test]> insert into vitamin (vitamin_name, price) values ('extreme pill 2', 20);
    Query OK, 1 row affected (0.10 sec)
    
    MariaDB [test]> insert into vitamin (vitamin_name, price) values ('pill 2', 10);
    Query OK, 1 row affected (0.10 sec)
    

    给予:

    MariaDB [test]> select * from vitamin_variety;
    +-----------+---------------+-----------------------+
    | pill_name | price_variety | price_variety_extreme |
    +-----------+---------------+-----------------------+
    | pill 1    |             5 |                    10 |
    | pill 2    |            10 |                    20 |
    +-----------+---------------+-----------------------+
    2 rows in set (0.00 sec)
    

    【讨论】:

    • 啊,我明白了,非常感谢 Paul 的详细解释,这对我很有帮助。我非常感谢你的回答。你有什么建议我该怎么做才能得到我想要的结果?我没有更多的想法来实现我想要的输出。谢谢保罗
    • 目前还不确定,但我明白了。一行涵盖pill 1 价格,另一行涵盖pill 2 价格。在这些触发器更新之前,vitamin_variety 表中是否已经存在行?可能是明天晚些时候,在我回来之前,我的 TZ 已经快午夜了。
    • 不,没有,我只需要根据它们的极端情况将它们插入到vitamin_variety。好的,保罗,非常感谢你帮助我。我真的很感激:)
    • 编辑了答案以展示实现预期目标的一种可能方式。
    猜你喜欢
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 2018-07-29
    • 2021-08-27
    • 2022-12-05
    • 2013-01-21
    • 1970-01-01
    • 2012-07-27
    相关资源
    最近更新 更多