c++如何解析SQL导出的SQL文件_正则表达式提取数据【实战】

浅墨大大_7242

浅墨大大_7242

2026-04-08

629人浏览

原创

不靠谱——正则无法可靠解析SQL中嵌套引号、转义、多行值等复杂结构;应优先用SQL解析器,其次用状态机预处理,仅表名等无嵌套片段可用正则提取。

c++如何解析sql导出的sql文件_正则表达式提取数据【实战】

SQL文件里INSERT语句太多,用正则提取字段值靠谱吗?

不靠谱——但临时救急可以。SQL导出文件(如 mysqldump 输出)结构看似规整,实则嵌套引号、转义反斜杠、换行、注释、多行VALUES都可能让正则崩溃。比如 INSERT INTO users VALUES (1, 'O''Reilly', "he said: \"hi\""); 这类数据,用正则匹配字符串字面量极易错位或截断。

真正能稳住的方案是:优先用 SQL 解析器(如 libpg_query 或 sqlite3_exec + 内存 DB),其次才考虑正则做**预处理清洗**(如剥离注释、合并折行),而非直接提取字段值。

  • 正则只适合提取「已知格式且无嵌套」的片段,例如:从每行 INSERT INTO `table_name` 中抽表名
  • 遇到单引号内含两个单引号(O''Reilly)、十六进制字符串(X'ABCD')、NULL 字面量,正则规则会指数级膨胀
  • MySQL 和 PostgreSQL 导出语法差异大:SET @a = ...;、/*!40101 ... */ 注释、DELIMITER 都会让通用正则失效

用 C++ 读取大 SQL 文件并逐行跳过注释和空行

这是所有后续处理的前提。很多同学一上来就写 std::regex 匹配整个 INSERT,结果内存爆掉或匹配超时——因为 std::regex 在 C++17 前性能差,且不支持 PCRE 的原子组或条件匹配。

更轻量、更可控的做法是:用 std::string 手动扫描,按行读取 + 状态机跳过注释:

std::ifstream file("dump.sql");
std::string line;
bool in_multiline_comment = false;
<p>while (std::getline(file, line)) {
size_t i = 0;
while (i /") { in_multiline_comment = false; i += 2; }
else i++;
} else if (line.substr(i, 2) == "/") {
in_multiline_comment = true; i += 2;
} else if (line.substr(i, 2) == "--" || line[i] == '#') {
break; // 跳过本行剩余内容
} else if (std::isspace(line[i])) {
i++;
} else {
// 找到第一个非空白非注释字符,可在此判断是否为 INSERT 开头
if (line.substr(i, 6) == "INSERT") { /<em> 处理该行 </em>/ }
break;
}
}
}</p>
  • 别依赖 std::regex_search 扫描整文件——大文件(>100MB)会 OOM 或卡死
  • -- 和 # 是单行注释,/*...*/ 可跨行,必须用状态机而非正则
  • Windows 换行符 \r\n 要在 std::getline 后手动 erase,否则影响子串比对

用 std::regex 提取 INSERT 语句中的表名和括号内字段列表

这部分正则相对安全,因为表名和字段名不包含引号、不转义,且位置固定。可用 std::regex 安全提取:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
const std::regex insert_re(R"(INSERT\s+INTO\s+`?(\w+)`?\s*(\([^)]+\))?)", std::regex_constants::icase);
std::smatch match;
if (std::regex_search(line, match, insert_re)) {
    std::string table_name = match[1].str(); // 如 "users"
    std::string columns = match[2].str();      // 如 "(id, name, email)"
}
  • 注意 std::regex 不支持 .*? 非贪婪,所以用 [^)]+ 替代括号内字段匹配
  • 表名带反引号(`user-info`)时,上面正则会把反引号也捕获进来,需额外 erase 掉首尾 `` ` ``
  • 如果字段列表为空(即没有括号),match[2] 为空字符串,不代表没匹配上——要检查 match[2].matched

VALUES 后面的值列表不能靠正则解析,必须用状态机拆分

这才是最常翻车的地方。比如这一行:VALUES (1, 'a,b', NULL, 'x''y', 3.14); ——逗号不是分隔符,引号内、转义内、NULL 字面量里的逗号都得忽略。

正确做法是写一个简易 CSV-like 解析器,按字符遍历,维护:当前是否在单引号内、是否刚经过转义符、是否在 NULL/TRUE/FALSE 字面量中:

  • 遇到 ':切换「在单引号内」状态;若前一个是 \,则跳过本次切换(即支持 \')
  • 遇到 , 且不在引号内、不在转义态:这就是字段分隔点
  • 遇到 NULL 且前后是空白或标点:当作一个完整 token,不拆开
  • 不要尝试用 std::regex_token_iterator 分割——它无法感知上下文状态

真要解析完整 SQL,建议直接调用 SQLite 的 sqlite3_prepare_v2 把 INSERT 语句编译成虚拟机指令,再用 sqlite3_bind_* 绑定参数观察值类型——这比手写健壮得多。

正则能做的,只是帮你把大文件切分成「疑似 INSERT 块」,真正的值提取,绕不开语法状态机。越想一步到位写个万能正则,后期 debug 越像在修水管。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4623

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

951

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1209

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6601

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3363

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6580

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

9061

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1230

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1072

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习