我有一种情况,我必须在共享主机提供商上更新网站。该站点具有CMS。使用FTP上传CMS的文件非常简单。
我还必须导入一个大的数据库文件(相对于PHP脚本而言)(大约2-3 MB未压缩)。Mysql已关闭,无法从外部访问,因此我必须使用FTP上传文件,然后启动PHP脚本将其导入。可悲的是,我无权访问mysql命令行功能,因此必须使用本地PHP进行解析和查询。我也不能使用LOAD DATA INFILE。我也不能使用任何类型的交互式前端(例如phpMyAdmin),它需要以自动化方式运行。我也不能使用mysqli_multi_query()。
mysql
mysqli_multi_query()
是否有人知道或拥有已经编码的简单解决方案,该解决方案可以 可靠地 将此类文件拆分为单个查询(可能有多行语句)并运行查询。由于可能遇到很多陷阱,我想避免自己开始摆弄它(如何检测字段分隔符是否是数据的一部分;如何处理备注字段中的换行符;等等上)。有 必须 是这个现成的解决方案。
这是一个内存友好的函数,该函数应该能够 在单个查询中拆分大文件,而无需一次打开整个文件 :
function SplitSQL($file, $delimiter = ';') { set_time_limit(0); if (is_file($file) === true) { $file = fopen($file, 'r'); if (is_resource($file) === true) { $query = array(); while (feof($file) === false) { $query[] = fgets($file); if (preg_match('~' . preg_quote($delimiter, '~') . '\s*$~iS', end($query)) === 1) { $query = trim(implode('', $query)); if (mysql_query($query) === false) { echo '<h3>ERROR: ' . $query . '</h3>' . "\n"; } else { echo '<h3>SUCCESS: ' . $query . '</h3>' . "\n"; } while (ob_get_level() > 0) { ob_end_flush(); } flush(); } if (is_string($query) === true) { $query = array(); } } return fclose($file); } } return false; }
我在一个大型phpMyAdmin SQL转储上对其进行了测试,它工作得很好。
一些测试数据:
CREATE TABLE IF NOT EXISTS "test" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "description" TEXT ); BEGIN; INSERT INTO "test" ("name", "description") VALUES (";;;", "something for you mind; body; soul"); COMMIT; UPDATE "test" SET "name" = "; " WHERE "id" = 1;
并分别输出:
SUCCESS: CREATE TABLE IF NOT EXISTS "test" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "description" TEXT ); SUCCESS: BEGIN; SUCCESS: INSERT INTO "test" ("name", "description") VALUES (";;;", "something for you mind; body; soul"); SUCCESS: COMMIT; SUCCESS: UPDATE "test" SET "name" = "; " WHERE "id" = 1;