Search code examples
phpsqlsplitpreg-split

Preg split multi SQL by semicolon in PHP


i am trying split my multi SQL by preg, but it doesn works...

Code:

$multiSql = "
ALTER TABLE `my_table` CHANGE `typ` `typ` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=none; 1=test1; 2=test2; 3=test3';

ALTER TABLE `my_table2`
  ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`;
 
ALTER TABLE `my_table3` ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`; ALTER TABLE `my_table3` ADD `test2` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `date`;

ALTER TABLE `my_table3` CHANGE `test2` `test2` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=test; 1=test2;';
";

$sqlArray = preg_split('~\([^)]*\)(*SKIP)(*FAIL)(*F)|(?<=;)(?![ ]*$)~', trim($multiSql), -1, PREG_SPLIT_NO_EMPTY);

print_r($sqlArray);

Demo: https://ideone.com/nkvloT

I need output like this:

1. ALTER TABLE `my_table` CHANGE `typ` `typ` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=none; 1=test1; 2=test2; 3=test3';
2. ALTER TABLE `my_table2` ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`;
3. ALTER TABLE `my_table3` ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`;
4. ALTER TABLE `my_table3` ADD `test2` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `date`;
5. ALTER TABLE `my_table3` CHANGE `test2` `test2` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=test; 1=test2;';

I am using this pattern from diferend answer: ~\([^)]*\)(*SKIP)(*FAIL)(*F)|(?<=;)(?![ ]*$)~ But it not works for my code.

Thanks for any help.


Solution

  • The pattern can be written using a positive lookahead asserting whitespace chars until the end of the string instead.

    You can also just use one of the two notations (*FAIL)(*F) instead of both.

    \([^)]*\)(*SKIP)(*F)|(?<=;)(?=\h*$|\s*\bALTER TABLE\b)
    

    Regex demo | PHP demo

    Example

    $multiSql = "
    ALTER TABLE `my_table` CHANGE `typ` `typ` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=none; 1=test1; 2=test2; 3=test3';
    
    ALTER TABLE `my_table2`
      ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`;
     
    ALTER TABLE `my_table3` ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`; ALTER TABLE `my_table3` ADD `test2` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `date`;
    
    ALTER TABLE `my_table3` CHANGE `test2` `test2` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=test; 1=test2;';
    ";
    
    $sqlArray = array_map(function($x){
        return trim(preg_replace("/\R/", '', $x));
    }, preg_split('~\([^)]*\)(*SKIP)(*F)|(?<=;)(?=\h*$|\s*\bALTER TABLE)~m', trim($multiSql), -1, PREG_SPLIT_NO_EMPTY));
    
    print_r($sqlArray);
    

    Output

    Array
    (
        [0] => ALTER TABLE `my_table` CHANGE `typ` `typ` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=none; 1=test1; 2=test2; 3=test3';
        [1] => ALTER TABLE `my_table2`  ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`;
        [2] => ALTER TABLE `my_table3` ADD `date` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `test`;
        [3] => ALTER TABLE `my_table3` ADD `test2` varchar(25) COLLATE utf8_czech_ci DEFAULT NULL AFTER `date`;
        [4] => ALTER TABLE `my_table3` CHANGE `test2` `test2` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=test; 1=test2;';
    )