Dividir consultas mysql na matriz, cada consulta separada por “;”;

Eu quero dividir consultas do mysql do formato de exportação do phpmyadmin. Cada consulta será separada por “;”; mas não pode usar explodir porque “;” poderia estar lá em qualquer lugar no valor do campo também. Abaixo está um exemplo.

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"); 

uma maneira de fazer é:

explodir por “);”

ele retornará uma série de declarações

então concat “)” no final de cada declaração na matriz

Dada uma string contendo várias instruções SQL separadas por ponto e vírgula, a seguinte function analisa cada declaração individual e os retorna todos em uma matriz. Ele usa uma regex (não trivial) e uma chamada para preg_match_all() e lida corretamente com os comentários de uma única e multi-linha, e as seqüências de caracteres simples e duplas, (cada uma das quais pode conter vírgulas sem terminação para ser ignorado):

 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(); } 

Edit 2017-08-15: corrigiu o erro na parte de comentário multilinha de regex apontada por @jxmallett. Editar 2017-08-16: regex ordenado (adicionado regex shebang e removido grupo desnecessário $2 ).

Minha sugestão seria replace seu delimitador por algo que seria único. Por exemplo, um ponto-e-vírgula não será exclusivo (como você descreveu) para que você não possa dividir isso. Newlines (como foi dito antes) pode ser uma opção boa e simples.

Essas linhas são separadas por um caractere de “nova linha”? Se sim, apenas exploda-os:

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

Que tal algo como isso

 $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); 

Onde $ pattern pode ser inicializado para um formato de consulta sql insert. Usar newline não será uma boa opção à medida que grandes inserções sql se estendem por mais de uma linha