0

因此,我正在使用带有 MariaDB (10.1.36-MariaDB ) 数据库的 PHP (7.2.10) 上的大型 Laravel 项目 (5.7.26),现在我遇到了一些设置问题我的迁移。目前,我已经将 laravel 指向第二个测试数据库,并让它成功创建了我的测试所需的 4 个表——但不幸的是,我还需要测试一些用于填充其中一个测试表的触发器——我通常使用的触发器通过 phpmyadmin (4.8.3) 创建,没有问题。由于迁移回滚会在删除表时删除触发器(这是出于更广泛的原因我需要的),我希望在单独的迁移文件中使用 laravel 的 DB->uprepared() 表达式以编程方式重新插入它们(其中一个有问题的触发器复制如下):

CREATE TRIGGER `Update TitleDescFormatCoverage` AFTER UPDATE ON `omeka_element_texts`
 FOR EACH ROW IF (NEW.element_id = 50) THEN
    UPDATE mi_items as m
    SET m.title = IF(m.title=OLD.text,IF(NEW.text='',(
        SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
    ),NEW.text),m.title)
    WHERE m.id = NEW.record_id;
ELSEIF (NEW.element_id = 42) THEN
    UPDATE mi_items as m
    SET m.format = IF(m.format=OLD.text,IF(NEW.text='',(
        SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
    ),NEW.text),m.format)
    WHERE m.id = NEW.record_id;
ELSEIF (NEW.element_id = 41) THEN
    UPDATE mi_items as m
    SET m.description = IF(m.description=OLD.text,IF(NEW.text='',(
        SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
    ),NEW.text),m.description)
    WHERE m.id = NEW.record_id;
ELSEIF (NEW.element_id = 38) THEN
    UPDATE mi_items as m
    SET m.coverage = IF(m.coverage=OLD.text,IF(NEW.text='',(
        SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
    ),NEW.text),m.coverage)
    WHERE m.id = NEW.record_id;
END IF

上述触发器在迁移过程中会导致可预测的错误(我猜是因为遇到了分号语句分隔符)。我可以调整 SQL 并通过 phpmyadmin 成功运行查询,方法是在 SQL 的顶部添加 DELIMITER && 并将 && 添加到 SQL 的末尾,但这在 mySQL 客户端之外是无效的。

为了解决这个问题,我重建了上面的 SQL,如下所示:

        DB::connection('test')->unprepared("
            CREATE TRIGGER `Update Title` AFTER UPDATE ON `omeka_element_texts` FOR EACH ROW
                UPDATE mi_items as m
                SET m.title = IF(NEW.element_id = 50 && m.title=OLD.text,IF(NEW.text='',(
                    SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
                ),NEW.text),m.title)
                WHERE m.id = NEW.record_id;
        ");
        DB::connection('test')->unprepared("
        CREATE TRIGGER `Update Format` AFTER UPDATE ON `omeka_element_texts` FOR EACH ROW
            UPDATE mi_items as m
            SET m.format = IF(NEW.element_id = 42 && m.format=OLD.text,IF(NEW.text='',(
                SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
            ),NEW.text),m.format)
            WHERE m.id = NEW.record_id;
        ");
        DB::connection('test')->unprepared("
        CREATE TRIGGER `Update Description` AFTER UPDATE ON `omeka_element_texts` FOR EACH ROW
            UPDATE mi_items as m
            SET m.description = IF(NEW.element_id = 41 && m.description=OLD.text,IF(NEW.text='',(
                SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
            ),NEW.text),m.description)
            WHERE m.id = NEW.record_id;
        ");
        DB::connection('test')->unprepared("
        CREATE TRIGGER `Update Coverage` AFTER UPDATE ON `omeka_element_texts` FOR EACH ROW
            UPDATE mi_items as m
            SET m.coverage = IF(NEW.element_id = 50 && m.coverage=OLD.text,IF(NEW.text='',(
                SELECT text FROM omeka_element_texts WHERE text != '' ORDER BY id DESC LIMIT 1
            ),NEW.text),m.coverage)
            WHERE m.id = NEW.record_id;
        ");

但是,这也会产生错误,因为显然 MariaDB 不支持对同一操作(之前/之后,创建/更新/删除)的多个触发器。不幸的是,由于应用程序的需要,我需要为某些触发器有效地运行 4 条语句(如上所示)。所以,这给我们带来了我的问题:

问题:有没有办法使用 Laravel/Eloquent/一些额外的兼容库(与我现有的数据库)以编程方式在单个操作上构建多语句触发器(例如,更新后)?我的下一个想法是使用某种脚本并尝试运行 laravel 控制台命令以通过某种脚本直接调用 mySQL 进行迁移,但探索这是我最后的手段 atm。有人知道更好的方法吗?

编辑:我不认为雄辩的模型事件会起作用,因为我在这里使用的任何机制都需要在生产站点/数据库上工作,在该生产站点/数据库中,有问题的表将被写入/修改的单独应用程序(Omeka)不会使用雄辩。

4

0 回答 0