使用php解析sql文件
Posted
技术标签:
【中文标题】使用php解析sql文件【英文标题】:Parse sql file using php 【发布时间】:2013-04-11 19:27:19 【问题描述】:我有一个超过 3gb 的 sql 转储文件,其中包含多个查询。我想使用 php 将文件解析为查询。
根据网站用户的推荐,我使用https://code.google.com/p/php-sql-parser/ 进行解析。问题是使用此方法只能检索第一个查询。
有人有什么建议吗?
转储文件是来自服务器的数据的唯一遗物。
谢谢!
【问题讨论】:
查找引号和转义,搜索;
为什么要解析它?为什么不把它恢复到服务器中呢?
一些查询中有错误。我希望丢弃有缺陷的。而且我的互联网连接有限,所以这次想彻底扫除
一个有错误的 sql 转储??
@KarolyHorvath 我认为文件中的分隔符发生了变化。所以无法搜索;
【参考方案1】:
这是“Principe Orazio”类的改进版本(@AgelessEssence 提到过)。
class sql_parser
public static function parse($content)
$sql_list = [];
$query = "";
$lines = explode("\n", $content);
foreach ($lines as $sql_line)
$sql_line = trim($sql_line);
if(($sql_line === "") || (strpos($sql_line, "--") === 0) || (strpos($sql_line, "#") === 0))
continue;
$query .= $sql_line;
// Checking whether the line is a valid statement
if (preg_match("/(.*);$/", $sql_line))
$query = trim($query);
$query = substr($query, 0, strlen($query) - 1);
$sql_list[] = sql_parser::remove_query_comments($query);
//reset the variable
$query = "";
return $sql_list;
public static function remove_query_comments($query)
$sql_comments = '@
(([\'"]).*?[^\\\]\2) # $1 : Skip single & double quoted expressions
|( # $3 : Match comments
(?:\#|--).*?$ # - Single line comments
| # - Multi line (nested) comments
/\* # . comment open marker
(?: [^/*] # . non comment-marker characters
|/(?!\*) # . ! not a comment open
|\*(?!/) # . ! not a comment close
|(?R) # . recursive case
)* # . repeat eventually
\*\/ # . comment close marker
)\s* # Trim after comments
|(?<=;)\s+ # Trim after semi-colon
@msx';
$query = trim( preg_replace( $sql_comments, '$1', $query ) );
// Remove the last ;
if(strrpos($query, ";") === strlen($query) - 1)
$query = substr($query, 0, strlen($query) - 1);
return $query;
使用它:
$sql_lists = sql_parser::parse(file_get_contents("test.sql"));
print_r($sql_lists);
【讨论】:
【参考方案2】:我真的找到了你想要的:
SQL Parser: Parse SQL files and extract query statements (( 通过 phpclasses.org ))
示例 sql 文件
#这是一条评论 :) select * from table1 where a=1; --select 评论 2 选择 * 从 表2 其中a=2; #插入值 将忽略插入`versions`(`release`,`revision`,`name`,`lastupdate`)值('1','0','sqlparser',now()); #创建表 创建表`测试`( `id` int(11) unsigned not null auto_increment, `name` varchar(80) not null default '', 主键(`id`) ) 引擎=innodb 默认字符集=utf8; #海关操作 插入`tests`(`id`,`name`) 值('1','test ; value'); update `test` set `name`='test value update' where `id`='1';输出:
大批 ( 0 => 'SELECT * FROM table1 WHERE a=1', 1 => 'SELECT * FROM table2 where a=2', 2 => 'INSERT IGNORE INTO `VERSIONS`(`release`,`revision`,`name`,`lastUpdate`) 值 (\'1\',\'0\',\'SqlParser\',NOW() )', 3 => 'CREATE TABLE `TESTS` (`Id` int(11) unsigned NOT NULL AUTO_INCREMENT, `Name` varchar(80) NOT NULL DEFAULT \'\', PRIMARY KEY (`Id`)) ENGINE=InnoDB 默认字符集=utf8', 4 => 'INSERT INTO `TESTS`(`Id`,`Name`) VALUES (\'1\',\'test ; value\')', 5 => 'UPDATE `TEST` SET `Name`=\'测试值更新\' WHERE `Id`=\'1\'', )这个类真正美妙的一点是它可以计算很多东西,比如 cmets、多行和他的值包括“;”的查询字符。
【讨论】:
【参考方案3】:http://pastebin.com/GxBahnyM - 我从 Typo3 CMS 得到它。 Typo3安装扩展时使用
【讨论】:
【参考方案4】:是否可以使用 "explode(";", $dumpfile) 拆分转储文件,然后执行循环调用该函数进行解析?您也可以使用其他分隔符进行分解。是否有可能报价不平衡?
问候
芦苇
【讨论】:
是的,看起来是最好的选择。 当查询像:插入表(fieldA,fieldB)值('aa;aa','bb');存在它会破坏文件的正确解析 为此,您可以解析块,如果有不平衡的引用,只需将下一个块添加到前一部分。 如何删除 cmets 或以 -- 开头的行以上是关于使用php解析sql文件的主要内容,如果未能解决你的问题,请参考以下文章
使用 PHP 获取 SQL 数据,然后将数组发送到 Javascript