在 MySQL 中触发以防止插入

Gam*_*der 8 mysql trigger

我想创建一个触发器,以防止在numflights不存在的航班 ( )的预订表中插入。

Tables
----------------------------------------------
flights(numflight, origine, destination, dep, arr)
airports(code, city, country)
reservation(people, numflight, date_travel)
Run Code Online (Sandbox Code Playgroud)

originedestination包含机场代码。

Rol*_*DBA 4

以下示例基于MySQL 存储过程编程一书第 11 章第 254-256 页中“使用触发器验证数据”副标题下的触发器中偷工减料的错误捕获方法:

DELIMITER $$

CREATE TRIGGER reservation_bi BEFORE INSERT ON reservation FOR EACH ROW
BEGIN

DECLARE found_count,dummy INT;

SELECT COUNT(1) INTO found_count FROM flights WHERE numflight=new.numflight;
IF found_count = 0 THEN
    SELECT 'Cannot Insert This Reservation Because Flight Number is Invalid'
    INTO dummy FROM reservation WHERE numflight=new.numflight;
END IF;

END; $$

DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

如果需要进行其他验证,请遵循相同的错误捕获方法!

更新

书中建议以这种方式抢占触发器的原因源于MySQL存储过程语言没有将SIGNAL实现到该语言中(当然,SIGNAL是ANSI标准)。

本书的作者通过调用语法正确但在运行时失败的 SQL 语句创建了解决方法。本书第 144-145 页(第 6 章:错误处理)给出了直接抢占存储过程(示例 6-18)或通过信号仿真(示例 6-19 和 6-20)的示例。

# Example 6-18. Using a nonexistent column name to force an error to the calling program

    CREATE PROCEDURE sp_update_employee_dob2
        (p_employee_id INT, p_dob DATE)
    BEGIN
        IF datediff(curdate(),p_dob)<(16*365) THEN
            UPDATE `Error: employee is too young; Employee must be 16 years or older`
                SET x=1;
        ELSE
            UPDATE employees
               SET date_of_birth=dob
            WHERE employee_id=p_dob;
       END IF;
    END;

# Example 6-19. Standard procedure to emulate SIGNAL

    CREATE PROCEDURE `my_signal`(in_errortext VARCHAR(255))
    BEGIN
        SET @sql=CONCAT('UPDATE `',in_errortext,'` SET x=1');
        PREPARE my_signal_stmt FROM @sql;
        EXECUTE my_signal_stmt;
        DEALLOCATE PREPARE my_signal_stmt;
    END;

# Example 6-20. Using our SIGNAL emulation procedure to raise an error

    CREATE PROCEDURE sp_update_employee_dob2
        (p_employee_id INT, p_dob DATE)
    BEGIN
        IF datediff(curdate(),p_dob)<(16*365) THEN
            CALL my_signal('Error: employee is too young; Employee must be 16 years or older')
        ELSE
            UPDATE employees
               SET date_of_birth=dob
            WHERE employee_id=p_dob;
       END IF;
    END;
Run Code Online (Sandbox Code Playgroud)

不幸的是,示例 6-19 和 6-20 中的信号仿真无法在触发器中完成。本书的作者在第 254-256 页上使用了示例 6-18 中的技术来抢占触发器。这就是为什么这本书的建议必须成为可行的方法。