MySQL 触发器中的“INSTEAD OF”,从 SQL Server 转换而来

Posted

技术标签:

【中文标题】MySQL 触发器中的“INSTEAD OF”,从 SQL Server 转换而来【英文标题】:"INSTEAD OF" in MySQL trigger, converted from SQL Server 【发布时间】:2021-07-01 20:27:59 【问题描述】:

我正在将一些 SQL Server 触发器转换为 mysql,并且遇到了一些语法问题。当我将 SQL Server 数据库迁移到 Aurora RDS MySQL 时,使用 AWS Schema Conversion Tool 转换了其余的数据库架构和对象。这是我在转换时遇到问题的触发器示例:

-- Create the UpdateAUD trigger on the new table.
CREATE TRIGGER [dbo].[UpdateAUD] ON [dbo].[AUD]
INSTEAD OF UPDATE
AS
BEGIN
  IF @@ROWCOUNT > 0
  BEGIN
    RAISERROR( 'Audit rows for AUD cannot be updated!', -1, 0 );
    ROLLBACK;
  END
END;

我尝试过的代码如下:

DELIMITER $$
-- Create the UpdateAUD trigger on the new table.
CREATE TRIGGER dbo.UpdateAUD 
AFTER UPDATE
ON dbo.AUD FOR EACH ROW
BEGIN
    set msg = ('Audit rows for AUD cannot be updated!');
    signal sqlstate '45000' set message_text = msg;
    ROLLBACK;
END$$

首先,AFTER 可以替代INSTEAD OF 吗?其次,MySQL 工作台遇到了 RAISERROR 问题,我已经查找了解决方法。但是我得到的错误是在 msg 变量附近,它说的是 Unknown system variable 'msg'

有什么想法吗?

【问题讨论】:

我建议阅读每个产品的文档以确定部分语法的工作方式。并且不要在寻找具有 MySQL 专业知识的人时标记 SQL Server。 通过拒绝选定用户的 UPDATE 权限可以更好地处理这种情况,这是一个比触发器更好的选择。在 SQL Server 和 MySQL 中。 我也在其中标记了 SQL,因为原始语法来自 SQL Server 数据库,其功能需要在 MySQL 中复制 请使用sql 标记用于SQL 语言,独立于任何实现,而sql-server 用于Microsoft SQL Server。 不要标记 SQL Server,因为 SQL Server 专家不一定是 MySQL 专家。与其说我需要在 SQL Server 中实现的这个功能,不如解释一下您的实际需求,而不依赖于 RBDMS。 【参考方案1】:

它必须是 BEFORE UPDATE TRIGGER,这样 UPDATE 才会被中断

你也可以

REVOKE UPDATE ON AUD FROM '*'@'localhost';

所以没有人可以更新表了

CREATE TABLE AUD (id int)
INSERT INTO AUD VALUES(1)
CREATE TRIGGER UpdateAUD 
BEFORE UPDATE
ON AUD FOR EACH ROW
BEGIN
    set @msg := 'Audit rows for AUD cannot be updated!';
    signal sqlstate '45000' set message_text = @msg;
END
UPDATE AUD SET  id = 1 WHERE id = 1
无法更新 AUD 的审计行!

db小提琴here

【讨论】:

【参考方案2】:

我最终修改为

DELIMITER $$
-- Create the UpdateAUD trigger on the new table.
CREATE TRIGGER dbo.UpdateAUD  
BEFORE UPDATE
ON dbo.AUD FOR EACH ROW
BEGIN
    signal sqlstate '45000' set message_text = 'Audit rows for AUD cannot be updated!';
END$$

根据文档,不需要ROWCOUNT,因为FOR EACH ROW 应该处理它。至于ROLLBACK,我检查了https://dev.mysql.com/doc/refman/5.6/en/trigger-syntax.html,发现它也应该被处理。

这看起来是从顶部发布的原始 MS-SQL 的良好转换吗?

【讨论】:

它是我的副本,你可以看到它有效 是的,我将你的答案标记为答案并投票赞成

以上是关于MySQL 触发器中的“INSTEAD OF”,从 SQL Server 转换而来的主要内容,如果未能解决你的问题,请参考以下文章

INSTEAD OF与AFTER触发器

SQL Server INSTEAD OF INSERT 触发器失败

为啥 INSTEAD OF UPDATE 触发器的 INSERTED 表为空?

如何使用 INSTEAD OF 触发器在视图中插入数据?

INSTEAD OF INSERT 触发器未触发视图 - SQL Server

数据库触发器for,instead of和after的使用