为什么Laravel中执行SOURCE命令报MySQL 1064错误但命令行运行正常?
问题原因
SOURCE 不是MySQL服务端支持的SQL语法,它是MySQL官方命令行客户端专属的内置命令,仅在你直接使用mysql命令行交互/导入时才会被识别。通过Laravel DB门面、PDO这类直接向MySQL服务端发送SQL语句的接口执行SOURCE,服务端完全无法解析,自然会抛出1064语法错误。
另外你代码里还有两个非核心问题:
- 定义
$snapshot变量时末尾多带了多余的分号 - DROP、CREATE DATABASE属于DDL语句,会自动触发隐式提交,外层包裹的事务完全不会生效,无法起到回滚作用
解决方案
以下两种方案都可以在Artisan命令中直接实现需求:
方案1:调用Shell执行MySQL导入(最稳妥,和命令行执行效果完全一致)
直接在PHP中执行你原本命令行的导入逻辑即可,Homestead环境下cli运行的Artisan命令默认有对应权限:
$dbUser = 'homestead'; $dbPass = 'secret'; $dbName = 'homestead'; $snapshotPath = '/home/vagrant/Data/local-db-snapshot.sql'; // 先删库建库,再直接导入快照文件 exec("mysql -h localhost -u {$dbUser} -p{$dbPass} -e 'DROP DATABASE IF EXISTS {$dbName}; CREATE DATABASE {$dbName};' && mysql -h localhost -u {$dbUser} -p{$dbPass} {$dbName} < {$snapshotPath}", $output, $returnVar); // 判断执行结果 if ($returnVar !== 0) { $this->error('数据库恢复失败:' . implode("\n", $output)); return; } $this->info('数据库恢复成功');
方案2:读取SQL文件内容直接执行(不依赖Shell调用)
如果你的场景不允许执行Shell命令,可以读取快照文件的SQL内容,用Laravel的多语句执行接口运行:
$db = 'homestead'; $snapshotPath = '/home/vagrant/Data/local-db-snapshot.sql'; // 删库建库切换库 DB::statement('DROP DATABASE IF EXISTS ' . $db); DB::statement('CREATE DATABASE ' . $db); DB::statement('USE ' . $db); // 读取SQL文件内容直接执行 $sql = file_get_contents($snapshotPath); DB::unprepared($sql);
注意如果你的SQL文件包含存储过程、触发器、特殊注释等复杂语法,优先使用方案1,避免语法解析边界问题。
内容的提问来源于stack exchange,提问作者fronzee
相关产品推荐
相关产品推荐

