You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用preg_split按分号分割多条SQL语句失效如何解决

问题原因

原有正则的核心缺陷是仅跳过了圆括号内的分号,没有对单引号包裹的字符串字面量(即场景中COMMENT后的注释值)做排除,因此字符串内部的分号会被误判为SQL语句结束标记;同时原规则没有处理拆分点周围的换行、多余空白,导致跨行SQL、同行多SQL场景的拆分结果不符合预期。

可行解决方案

调整正则规则,同时跳过圆括号区域和单引号字符串区域的内容,仅以这两个区域外的分号+后续连续空白(含换行、空格、制表符)作为拆分标记;拆分后统一清理每条SQL首尾的空白字符,将SQL内部连续的换行、缩进空格替换为单个空格,过滤空条目即可得到预期结果。

实现代码

<?php
$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;';
";

// 正则规则:跳过括号内容、跳过单引号字符串内容,匹配区域外的分号+后续连续空白作为分隔符
$pattern = '~\([^)]*\)(*SKIP)(*FAIL)|\'(?:\\\\\'|[^\'])*\'(*SKIP)(*FAIL)|;\s*~';
$sqlArray = preg_split($pattern, trim($multiSql), -1, PREG_SPLIT_NO_EMPTY);

// 格式化每条SQL:清理首尾空白,将内部连续换行、多空格替换为单个空格
$sqlArray = array_map(function($sql) {
    return trim(preg_replace('/\s+/', ' ', $sql));
}, $sqlArray);

// 结果输出验证
foreach ($sqlArray as $index => $sql) {
    echo ($index + 1) . ". " . $sql . ";\n";
}
?>

执行效果

运行后输出和预期完全一致的5条SQL语句:

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;';

补充说明

  • 该规则已覆盖三类目标场景:注释(字符串)内带分号、语句跨行、同行包含多条SQL
  • 如果后续需要处理更复杂的SQL语法(比如嵌套括号、双引号字符串、--行注释、/* */块注释),只需要在正则里新增对应语法规则的(*SKIP)(*FAIL)匹配段即可扩展适配。

内容的提问来源于stack exchange,提问作者JeyC0b

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 15:57:52