在数组中拆分mysql查询,每个查询用“;”分隔

时间:2011-01-20 13:40:32

标签: php mysql regex split

我想从phpmyadmin导出格式中拆分mysql查询。每个查询将以“;”分隔但不能使用爆炸,因为“;”也可以在任何场地价值的地方。以下是一个例子。

insert into wp_options (option_id, blog_id, option_name, option_value, autoload) values (201, 0, "tadv_btns2", "a:21:{i:0;s:14:\"fontsizeselect\";i:1;s:12:\"formatselect\";i:2;s:9:\"pastetext\";i:3;s:9:\"pasteword\";i:4;s:12:\"removeformat\";i:5;s:9:\"separator\";i:6;s:7:\"charmap\";i:7;s:5:\"print\";i:8;s:9:\"separator\";i:9;s:9:\"forecolor\";i:10;s:9:\"backcolor\";i:11;s:8:\"emotions\";i:12;s:9:\"separator\";i:13;s:3:\"sup\";i:14;s:3:\"sub\";i:15;s:5:\"media\";i:16;s:9:\"separator\";i:17;s:4:\"undo\";i:18;s:4:\"redo\";i:19;s:7:\"attribs\";i:20;s:7:\"wp_help\";}", "no");

insert into wp_options (option_id, blog_id, option_name, option_value, autoload) values (202, 0, "tadv_btns3", "a:0:{}", "no");

insert into wp_options (option_id, blog_id, option_name, option_value, autoload) values (203, 0, "tadv_btns4", "a:0:{}", "no");

insert into wp_options (option_id, blog_id, option_name, option_value, autoload) values (204, 0, "tadv_allbtns", "a:64:{i:0;s:6:\"wp_adv\";i:1;s:4:\"bold\";i:2;s:6:\"italic\";i:3;s:13:\"strikethrough\";i:4;s:9:\"underline\";i:5;s:7:\"bullist\";i:6;s:7:\"numlist\";i:7;s:7:\"outdent\";i:8;s:6:\"indent\";i:9;s:11:\"justifyleft\";i:10;s:13:\"justifycenter\";i:11;s:12:\"justifyright\";i:12;s:11:\"justifyfull\";i:13;s:3:\"cut\";i:14;s:4:\"copy\";i:15;s:5:\"paste\";i:16;s:4:\"link\";i:17;s:6:\"unlink\";i:18;s:5:\"image\";i:19;s:7:\"wp_more\";i:20;s:7:\"wp_page\";i:21;s:6:\"search\";i:22;s:7:\"replace\";i:23;s:10:\"fontselect\";i:24;s:14:\"fontsizeselect\";i:25;s:7:\"wp_help\";i:26;s:10:\"fullscreen\";i:27;s:11:\"styleselect\";i:28;s:12:\"formatselect\";i:29;s:9:\"forecolor\";i:30;s:9:\"backcolor\";i:31;s:9:\"pastetext\";i:32;s:9:\"pasteword\";i:33;s:12:\"removeformat\";i:34;s:7:\"cleanup\";i:35;s:12:\"spellchecker\";i:36;s:7:\"charmap\";i:37;s:5:\"print\";i:38;s:4:\"undo\";i:39;s:4:\"redo\";i:40;s:13:\"tablecontrols\";i:41;s:4:\"cite\";i:42;s:3:\"ins\";i:43;s:3:\"del\";i:44;s:4:\"abbr\";i:45;s:7:\"acronym\";i:46;s:7:\"attribs\";i:47;s:5:\"layer\";i:48;s:5:\"advhr\";i:49;s:4:\"code\";i:50;s:11:\"visualchars\";i:51;s:11:\"nonbreaking\";i:52;s:3:\"sub\";i:53;s:3:\"sup\";i:54;s:9:\"visualaid\";i:55;s:10:\"insertdate\";i:56;s:10:\"inserttime\";i:57;s:6:\"anchor\";i:58;s:10:\"styleprops\";i:59;s:8:\"emotions\";i:60;s:5:\"media\";i:61;s:10:\"blockquote\";i:62;s:9:\"separator\";i:63;s:1:\"|\";}", "no");

6 个答案:

答案 0 :(得分:7)

给定一个包含多个分号分隔的SQL语句的字符串,以下函数解析每个单独的语句并将它们全部返回到数组中。它使用一个(非平凡的)正则表达式,一个调用preg_match_all(),并正确处理单行和多行注释,以及单引号和双引号字符串(每个字符串可能包含非终结分号)被忽略):

function split_sql($sql_text) {
    // Return array of ; terminated SQL statements in $sql_text.
    $re_split_sql = '%(?#!php/x re_split_sql Rev:20170816_0600)
        # Match an SQL record ending with ";"
        \s*                                     # Discard leading whitespace.
        (                                       # $1: Trimmed non-empty SQL record.
          (?:                                   # Group for content alternatives.
            \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'  # Either a single quoted string,
          | "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"      # or a double quoted string,
          | /\*[^*]*\*+(?:[^*/][^*]*\*+)*/      # or a multi-line comment,
          | \#.*                                # or a # single line comment,
          | --.*                                # or a -- single line comment,
          | [^"\';#]                            # or one non-["\';#-]
          )+                                    # One or more content alternatives
          (?:;|$)                               # Record end is a ; or string end.
        )                                       # End $1: Trimmed SQL record.
        %x';  // End $re_split_sql.
    if (preg_match_all($re_split_sql, $sql_text, $matches)) {
        return $matches[1];
    }
    return array();
}

编辑2017-08-15:修正了@jxmallett指出的正则表达式的多行注释部分中的错误。 编辑2017-08-16:整理正则表达式(添加正则表达式shebang并删除不必要的组$2)。

答案 1 :(得分:1)

我的建议是用一些独特的东西替换你的分隔符。例如,分号不是唯一的(如您所述),因此您无法对此进行拆分。 Newlines(如前所述)可能是一个很好而且简单的选择。

答案 2 :(得分:1)

一种方法是:

爆炸“);”

它将返回语句数组

然后concat“)”在数组

中的每个语句的末尾

答案 3 :(得分:0)

这些行是否以“换行符”字符分隔?如果是,只是爆炸它们:

$my_array = explode("\n",$content);

答案 4 :(得分:0)

这样的事情

$fh = fopen('/path/to/your/file.sql', 'r') or die($php_errormsg);
while (!feof($fh)) {
    $line = fgets($fh, 4096);
    if (preg_match($pattern, $line)) { $sql_queries[ ] = $line; }
}
fclose($fh);

其中$ pattern可以初始化为sql insert查询格式。 使用换行不会是一个不错的选择,因为大型sql插入拉伸多行

答案 5 :(得分:0)

我针对一些问题修改了“ridgerunner”函数“split_sql”:没有反引号字符串、跳过有语法错误的查询、不是所有的多行注释或最后一个空的sql。它总是返回完整的数组以调试每个查询或重新组装以在 MySQL 中进行分析;

function split_sql($sql, $rtrim = TRUE)
{
    $re = '%
        \s*                                                 # Discard leading whitespace.
            ((?:                                            # Group for content alternatives.
              \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'?           # Either a single quoted string,
            | "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"?               # or a double quoted string,
            | `[^`]*`?                                      # single back quoted string
            | \/\*(?:.*?\*\/|.*)                            # or a multi-line comment,
            | (?-s)\#.*                                     # or a # single line comment (off s modifier from here),                
            | [^;"\'#`\/-]+                                 # or one non-[...]
            | --.*                                          # or a -- single line comment,
            | -                                             # or -
            )*)                                             # One or more content alternatives
            ;                                               # Record end is a ; or string end.
        %xs';
    if ($rtrim)
        $sql = rtrim($sql, "; \t\n\r\0\x0B");
    if (preg_match_all($re, $sql.';', $matches))
        return $matches[1];        
    return [];
}