如何用PHP正则将MySQL的INSERT SET语句转换为SQLite兼容格式?
解决MySQL INSERT SET到SQLite INSERT VALUES的转换问题
嘿,我刚好碰到过类似的需求,给你分享一个靠谱的解决方案!你之前的正则思路是对的,但替换环节需要用回调函数来处理键值对的拆分——直接用正则替换没法动态把field1=value1,field2=value2拆分成字段列表和值列表,这就是你卡壳的核心原因。
核心思路
我们需要分三步完成转换:
- 用正则精准匹配出
INSERT INTO后的表名,以及SET之后的所有键值对 - 把键值对拆分成独立的字段和值(还要处理带引号的字符串这类特殊情况)
- 拼接成SQLite支持的
INSERT INTO (field1,field2) VALUES(value1,value2)格式
具体实现代码
这里用PHP的preg_replace_callback来处理,它允许我们在替换时自定义逻辑,完美适配这种需要动态处理内容的场景:
$mysqlInsert = "INSERT INTO users SET username='johndoe', age=30, email='john@example.com', bio='Hi, I\\'m a developer!', is_active=TRUE"; $sqliteInsert = preg_replace_callback( // 正则匹配:捕获表名和SET后的键值对部分,匹配到语句结束的分号或行尾 '/INSERT\s+INTO\s+(\w+)\s+SET\s+(.+?)(?=\s*(?:;|$))/i', function ($matches) { $tableName = $matches[1]; $rawPairs = $matches[2]; // 拆分键值对:处理带单/双引号的字符串、数字、NULL、布尔值,避免把字符串内的逗号当成分隔符 preg_match_all( '/(\w+)\s*=\s*(?:'([^']*)'|"([^"]*)"|(\d+|NULL|TRUE|FALSE))/i', $rawPairs, $fieldValueMatches, PREG_SET_ORDER ); $fields = []; $values = []; foreach ($fieldValueMatches as $match) { $fields[] = $match[1]; // 按优先级处理不同类型的值 if (!empty($match[2])) { $values[] = "'{$match[2]}'"; // 单引号包裹的字符串 } elseif (!empty($match[3])) { $values[] = "\"{$match[3]}\""; // 双引号包裹的字符串 } else { $values[] = strtoupper($match[4]); // 数字、NULL、布尔值转大写,符合SQL规范 } } // 拼接成SQLite兼容的INSERT语句 return sprintf( "INSERT INTO %s (%s) VALUES (%s)", $tableName, implode(', ', $fields), implode(', ', $values) ); }, $mysqlInsert ); echo $sqliteInsert;
代码说明
- 外层正则:负责定位整个
INSERT SET语句的核心部分,通过(?=\s*(?:;|$))确保只匹配到当前SQL语句的结束位置,不会误匹配后续内容。 - 键值对拆分正则:专门处理每个
field=value对,能正确识别带引号的字符串(包括字符串内包含逗号的情况),以及数字、NULL、布尔值,避免拆分出错。 - 格式拼接:遍历拆分后的字段和值,用
implode拼接成SQLite要求的语法格式,同时对SQL关键字(比如NULL、TRUE)统一转大写,保证语法规范。
边界情况处理
这个方案能覆盖大部分常见场景:
- 带单引号/双引号的字符串(包括字符串内包含逗号、转义单引号的情况)
- 整数、浮点数等数字类型
NULL、TRUE/FALSE这类SQL常量- 不同大小写的SQL关键字(正则里的
/i修饰符忽略大小写)
内容的提问来源于stack exchange,提问作者maple wang
相关产品推荐
相关产品推荐

