【问题标题】:MySQL trigger working on one table but not the otherMySQL 触发器在一张表上工作,但在另一张表上不工作
【发布时间】:2014-02-23 09:57:51
【问题描述】:

我创建了一个 mysql 触发器来更新从另一个表中插入值:

DROP TRIGGER IF EXISTS `CourseCode`//
CREATE TRIGGER `CourseCode` BEFORE INSERT ON `race`
FOR EACH ROW  BEGIN
SET NEW.Course_Code = (
    SELECT 
        course_code 
    from 
        tb_course 
    where 
        tb_course.course_name = NEW.course_name
)
END
//

这非常有效。它根据 tb_course 表返回 course_name 的 4 字符代码。

我正在尝试做的是在另一个表中完全相同的事情,我复制并粘贴触发器并重命名触发器和表(字段名称和类型也相同)但它不起作用:

DROP TRIGGER IF EXISTS `CourseCode2`//
CREATE TRIGGER `CourseCode2` BEFORE INSERT ON `fields`
FOR EACH ROW 
BEGIN 
SET NEW.Course_Code = (
    SELECT 
        course_code 
    from 
        tb_course 
    where 
        tb_course.course_name = NEW.course_name
)
END    
//

但是这会导致空值。我尝试用字符串(即 tb_course.course_name="String")替换 New.Course_name 并更新该静态值,因此触发器似乎正在工作,但它与此表中的 select 语句不匹配,或者它没有设置 Course_Code 字段...

您可以建议进行任何调试来解决这个问题吗?这让我发疯了,我不知道该怎么做才能诊断出问题。

干杯

【问题讨论】:

  • 为什么你要这样做?如果course_name 足以识别tb_course 中的唯一记录(这些触发器必须是这种情况),那么只需将其用作其他表中的外键即可。另外存储course_code 违反3NF
  • 嗨,老实说,因为我不知道外键是什么...我草率地自学了我的 mysql 知识以使某些东西正常工作。我将阅读一些有关外键的内容,看看这是否对我有帮助。谢谢
  • 好的,我明白你现在在说什么了。我还在输入到我的字段表中的数据中发现了一个错误,导致触发器失败(开头的空白我没有注意到),这解释了我原来的问题。感谢您的回复,我会做一些调整并最终开始使用一些外键而不是我的触发器。
  • 实际上,许多应用程序使用代理键,例如course_code,而不是自然的,例如course_name(一方面,它可以在不更新子表的情况下更改键值):也就是说,要遵守 3NF,您将仅在子表中存储 course_code 而不是 course_name。这是怎么做到的?通常应用程序在插入数据时就知道相关的course_code——因此直接在INSERT语句中将其提供给数据库;如果不知道,可以使用INSERT ... SELECT获取。

标签: mysql


【解决方案1】:

我不知道第二个触发器出了什么问题。

但是,“调试”部分我也许可以提供帮助。

搜索“网络”将返回各种允许单步调试的软件(付费)。我想要的不是花钱买东西,而是从存储函数过程和触发器内部“打印”语句。

快速搜索将我带到已经完成所有工作的人。

Debugging Stored Procedures in MySql

我刚刚在MySql中设置了一下,试了一下,效果很好。

这是一些示例代码,基于您的触发器和我得到的输出。

DELIMITER $$

USE `testmysql`$$

DROP TRIGGER /*!50032 IF EXISTS */ `CourseCode`$$
CREATE
    /*!50017 DEFINER = 'test'@'localhost' */
    TRIGGER `CourseCode` BEFORE INSERT ON `race` 
    FOR EACH ROW BEGIN
        DECLARE v_course_code INT; 
        DECLARE v_course_title VARCHAR(255);

    CALL procLog("line 12: Entering CourseCode");
    SELECT 
        course_code, course_title
        INTO
        v_course_code, v_course_title
    FROM 
        tb_course 
    WHERE 
        tb_course.course_name = NEW.course_name;

    SET NEW.course_code = v_course_code;

        CALL procLog(CONCAT("line_22: ", v_course_title, " code: ", NEW.course_code));
        CALL procLog("line 24: Exiting CourseCode");
    END;
$$

DELIMITER ;

查询:

CALL setupProcLog();

INSERT INTO `race` (course_name, race_info)
VALUES ('learn_it_02', 'this is another test');

CALL cleanup('query end');

procLog 输出:

entrytime connection_id 消息


2014-02-23 12:32:21 5 line 12: 输入 CourseCode
2014-02-23 12:32:21 5 line_22:Learn It Course 02 代码:2
2014-02-23 12:32:21 5 line 24: Exiting CourseCode
2014-02-23 12:32:21 5 cleanup() 查询结束

好的,可能有点笨拙,但它有助于调试“存储”的程序。

从现在开始我会使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多