因此,我正在使用带有 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)不会使用雄辩。