核心要点
我们编写的许多代码都是为了执行某个操作。无论是数据库查询、文件操作、数据处理等等,所有这些都是为了使我们的脚本能够实现其既定目的。但是,您是否注意到有时您需要编写多少代码来验证之前的某个操作?我最近的一个项目涉及一个相当麻烦的问题,这导致我使用了无数的查询,只是为了确保在每次操作后所有数据在我的表中都保持同步。这远非优雅,本来应该是一个相当简单的脚本,却变成了一个复杂的查询页面。从维护的角度来看,这是不可行的,当我想要更新页面功能的一部分时,这简直是一场噩梦。正是这里,MySQL触发器进入了我的项目。通过让MySQL通过触发器做更多工作,我的项目的PHP端得到了极大的简化。因此,本文的目的是让您深入了解MySQL触发器的创建和使用,以便在阅读结束时,您可以在自己的项目中使用它们。
什么是MySQL触发器?
触发器在MySQL 5.0.2版本中引入,只是MySQL增加的功能之一,可以帮助我们作为开发人员简化工作。它们在表上执行操作(插入、更新、删除)之前或之后自动调用。您需要拥有相应的权限才能创建触发器。在MySQL 5.1.6之前,您需要SUPER权限,但在5.1.6中,这发生了变化,您需要TRIGGER权限。通常,共享主机计划不允许SUPER,因为它很容易被滥用,因此您可能只能在您拥有更多权限的服务器上使用它们,例如(虚拟)专用服务器或您的本地主机,具体取决于您使用的MySQL版本。以下是一些关于触发器的其他快速说明:
现在让我们通过将其分解为原始形式来仔细查看触发器的基本语法:
<code class="language-sql">CREATE TRIGGER TrigName [BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON tableName FOR EACH ROW BEGIN #action(s) to perform END</code>
创建触发器时,您可以选择它是在操作发生之前还是之后触发;您选择哪个将完全取决于您使用它们的情况。如果您要修改进入数据库的传入数据,则需要BEFORE。但是,如果您要执行某个操作是因为之前的操作,则应使用AFTER语句。将触发触发器的操作可以是INSERT、UPDATE或DELETE,因为这三个语句是唯一会导致修改表内数据的语句。
将触发器应用于实际情况
触发器在许多情况下都非常有用。一个众所周知的用法是通过在未使用外键时触发过时记录的删除来维护一组表的完整性。它们还可以用于在新的插入/删除时自动增加或减少统计表,记录对数据库内数据的更改,保持表与其他表同步等等。在本文中,我们将使用它们来预处理一些计算。这种情况是,我们有一家公司以每小时30英镑的价格出租其大厅。他们记录在该大厅举行的每个活动的名称、开始时间和结束时间,然后在收入表中计算时间和应付费用。事件的名称和开始时间最初被插入到事件表中以预订大厅,然后只有在活动结束后,才会在该行上更新租赁成本。需要计算事件的持续时间(以分钟为单位),其中开始时间将从结束时间中减去,然后租赁费用将通过将总时间乘以0.5(每小时30英镑,每分钟50便士)来计算。我们可以在更新事件信息时使用PHP执行事件持续时间和费用的计算(通过选择插入的数据,计算持续时间和租赁费用,然后插入或更新收入表),或者我们可以简单地使用触发器来自动化此过程并减少一些PHP代码。让我们设置两个基本表并将一些虚拟预订数据插入事件以开始操作。
<code class="language-sql">CREATE TABLE events ( id INTEGER NOT NULL AUTO_INCREMENT, event_name VARCHAR(50) NOT NULL, event_start TIMESTAMP NOT NULL DEFAULT 0, event_end TIMESTAMP NOT NULL DEFAULT 0, PRIMARY KEY (id) ) ENGINE=INNODB; CREATE TABLE revenue ( id INTEGER NOT NULL AUTO_INCREMENT, event_id INTEGER NOT NULL, hire_time INTEGER NOT NULL, hire_fees FLOAT NOT NULL, PRIMARY KEY (id), FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE, UNIQUE (event_id) )ENGINE=INNODB; INSERT INTO events VALUES (NULL, 'Birthday Party', '2012-11-08 14:30:00', 0), (NULL, 'Wedding', '2012-12-02 13:00:00', 0);</code>
设置好两个表后,我们可以继续创建名为CostCalc的触发器。触发器设置为在事件表上发生更新后触发,然后执行前面提到的计算。然后它插入或更新(如果预先存在的事件ID已设置)收入表。
<code class="language-sql">CREATE TRIGGER TrigName [BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON tableName FOR EACH ROW BEGIN #action(s) to perform END</code>
创建触发器时(与事件和存储例程类似),我们需要做的第一件事是指定一个新的分隔符,它表示触发器的结尾。这是使用DELIMITER关键字完成的,后面跟着一个自定义符号(或符号),并且需要将触发器作为一个整体执行,而不是MySQL只是单独执行内部的语句。然后,我们指定触发器的名称、其时间、事件以及它将被设置为在其上触发的表。在此示例中,我们将触发器的时间设置为在UPDATE语句发生后起作用,因为我们只想在成功更新后执行触发器;否则,我们将重复该事件的先前记录。接下来,我们使用BEGIN...END复合语句来容纳触发器的功能。触发器的正文首先声明两个变量:rows和time。我们从事件表中选择行数,其中ID引用刚刚修改的行,并且事件_start和event_end时间中的一个(或两个)已被修改,以及event_end时间不等于零。这是为了澄清是否需要对收入表进行任何操作,因为只有通过这些更改才能计算租赁费用。一旦我们知道我们可以计算时间和费用,我们将time变量设置为等于从事件的开始到结束列的分钟数。通过将这个数字乘以0.5,我们也可以得到租赁成本。由于event_id列是唯一的,我们只能有一个ID对应于事件表;因此,我们使用REPLACE来更新表中预先存在的行(如果有)或插入新行(如果没有)。在MySQL语句中,您可能还注意到在上面的SELECT和REPLACE语句中以及时间变量值的表达式中使用了关键字OLD和NEW。您使用这两个关键字将取决于您情况的事件以及触发器触发的时间。
将用于启动触发器的相应PHP脚本将包括一个类(称为EventHandler),以及我们的客户端调用代码。该类将通过PDO连接到我们的MySQL数据库,并将包含一个方法updateEvent(),该方法将在需要更新事件内容时调用。
<code class="language-sql">CREATE TRIGGER TrigName [BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON tableName FOR EACH ROW BEGIN #action(s) to perform END</code>
我们首先创建我们的EventHandler类,其中属性$db被定义为保存PDO类的实例,该实例通过构造方法设置。然后,我们继续制作我们的updateEvent()方法,其中定义了三个参数。第一个参数指定我们想要在事件表中更新的列,并且允许三个值之一:name、start、end。第二个参数保存要插入的值或更新列的当前值;而第三个参数保存要更新的元组的ID。确保列名有效后,我们通过参数化查询查询我们的表,最后检查是否有任何行被更新。创建类后,我们继续调用它。我们将PDO对象的实例作为参数传递给EventHandler类。然后,updateEvent()方法将使用不同的值调用四次,以显示我们的触发器将如何对在事件表上进行的更新做出反应。前两次更新不会导致我们的触发器插入或更新行,因为我们仍然没有计算事件持续时间和租赁费用所需的信息。我们所做的只是更新事件名称并将它的开始时间推迟两天。然而,接下来的两次更新将需要我们的触发器的功能,因为第一次更新定义了结束时间,第二次更新将结束时间重新定义为一个小时后,从而导致持续时间发生变化,因此租赁费用也发生变化。这就是我们需要REPLACE语句的地方,因为我们在创建表时对表施加了约束,我们每个事件ID只能有一条记录。
结束语
MySQL触发器如果使用得当,不仅可以对网站的性能产生积极影响,还可以避免编写大量的PHP代码来处理此类操作。我希望您在项目中发现它们像我在我的项目中一样有用,因此请随时大胆使用触发器!图片来自Fotolia
关于使用MySQL触发器进行操作自动化的常见问题解答
MySQL触发器是一个存储程序,它会自动响应表中发生的事件(例如插入、更新或删除)而被调用。触发器用于维护数据库中信息的完整性,并且在表上发生特定操作时会自动调用。它们可以在事件之前或之后执行。
创建MySQL触发器涉及CREATE TRIGGER语句,其中包括触发器的名称、触发事件以及事件发生时要执行的语句。这是一个基本示例:
<code class="language-sql">CREATE TABLE events ( id INTEGER NOT NULL AUTO_INCREMENT, event_name VARCHAR(50) NOT NULL, event_start TIMESTAMP NOT NULL DEFAULT 0, event_end TIMESTAMP NOT NULL DEFAULT 0, PRIMARY KEY (id) ) ENGINE=INNODB; CREATE TABLE revenue ( id INTEGER NOT NULL AUTO_INCREMENT, event_id INTEGER NOT NULL, hire_time INTEGER NOT NULL, hire_fees FLOAT NOT NULL, PRIMARY KEY (id), FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE, UNIQUE (event_id) )ENGINE=INNODB; INSERT INTO events VALUES (NULL, 'Birthday Party', '2012-11-08 14:30:00', 0), (NULL, 'Wedding', '2012-12-02 13:00:00', 0);</code>
不能直接调用。MySQL不支持从触发器调用PHP脚本。但是,您可以间接地通过使用UDF(用户定义函数)或使用外部系统来监视数据库中的更改,然后调用PHP脚本来实现这一点。
在MySQL中创建触发器的语法如下:
<code class="language-sql">CREATE TRIGGER TrigName [BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON tableName FOR EACH ROW BEGIN #action(s) to perform END</code>
MySQL中的自动化可以通过触发器、存储过程和事件来实现。触发器可用于自动化响应特定数据更改而应执行的任务。存储过程允许您将一系列命令封装到单个可调用例程中。事件是根据计划运行的任务。
MySQL触发器的一些局限性包括:它们只能与单个表关联,它们不能返回结果集,它们不能接受参数,并且不能像存储过程那样直接调用。
调试MySQL触发器可能具有挑战性,因为没有内置调试器。但是,您可以使用变通方法,例如将值插入单独的表以跟踪执行流程,或者使用MySQL Debugger之类的第三方工具。
可以。但是,您在执行此操作时应谨慎,因为它可能导致难以管理和调试的复杂事件链。
您可以使用DROP TRIGGER语句,后跟触发器的名称来删除MySQL触发器。例如:
<code class="language-sql">CREATE TABLE events ( id INTEGER NOT NULL AUTO_INCREMENT, event_name VARCHAR(50) NOT NULL, event_start TIMESTAMP NOT NULL DEFAULT 0, event_end TIMESTAMP NOT NULL DEFAULT 0, PRIMARY KEY (id) ) ENGINE=INNODB; CREATE TABLE revenue ( id INTEGER NOT NULL AUTO_INCREMENT, event_id INTEGER NOT NULL, hire_time INTEGER NOT NULL, hire_fees FLOAT NOT NULL, PRIMARY KEY (id), FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE, UNIQUE (event_id) )ENGINE=INNODB; INSERT INTO events VALUES (NULL, 'Birthday Party', '2012-11-08 14:30:00', 0), (NULL, 'Wedding', '2012-12-02 13:00:00', 0);</code>
可以。您可以创建一个触发器来检查数据是否在插入或更新到表中之前,并相应地采取措施。
以上是MySQL触发器的动作自动化的详细内容。更多信息请关注PHP中文网其他相关文章!