前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux C++简单实现一个批量插入的sql脚本生成工具

Linux C++简单实现一个批量插入的sql脚本生成工具

作者头像
typecodes
发布2024-03-29 15:10:17
700
发布2024-03-29 15:10:17
举报
文章被收录于专栏:typecodestypecodes

之前项目上隔三差五地要手工批量导入一些数据,于是自己用C++写了这个sql脚本文件的生成工具。

Linux C++简单实现一个批量插入的sql脚本生成工具
Linux C++简单实现一个批量插入的sql脚本生成工具
1 需求说明

批量插入多个用户收费信息,也就是用户id不同,但是包括所属区域代号、收费模式和费率值等数据是相同的。如果使用手工拼接insert语句工作量很大,而且可能出现差错,所以改用程序来生成。

只需要配置好相关参数,然后直接执行程序就可以把生成的sql脚本交给DBA处理了。

2 C++程序

代码比较简单,从main函数中可以看出主要流程是先读取配置文件(见小节3)中的数据,然后把使用|分隔的用户id进行分解。经过一系列操作后,会拼接出所有的insert语句,最终把这些数据到写入到文件流中。

这里用到了C++文件流的读写、string中字符串的查找和删除、string数据切割成vector或者map对象等。当然代码还可以做很多优化,例如参数的过滤检查、用户数过多时考虑分成多个insert语句、数据量大时使用多线程等。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

/** * @FileName linux_file_basic1_2.cpp * @Describe Linux C++简单实现一个批量插入的sql脚本生成工具. * @Author vfhky 2017-10-18 23:29 https://typecodes.com/cseries/genmysqlinsertsql.html * @Compile g++ linux_file_basic1_2.cpp -o linux_file_basic1_2 -std=c++11 */ #include <iostream> #include <fstream> #include <vector> #include <map> #include <sstream> #include <time.h> typedef std::map<std::string, std::string> StringMap; //去除string中所有的空格 void TrimAllSpace( std::string &s_str ) { size_t index = 0; if( !s_str.empty()) { while( (index = s_str.find(' ',index)) != std::string::npos ) { s_str.erase( index, 1 ); } } } //切割字符串 void splitToMap( const std::string &s_orginal, const std::string &s_split_pattern, StringMap &StringMap_Obj ) { if( s_orginal.empty() ) { throw( "s_Faccount_id is empty." ); } //方便截取最后一段数据 std::string s_strs = s_orginal + s_split_pattern; size_t i_pos = s_strs.find(s_split_pattern); size_t i_size = s_strs.size(); while( i_pos != std::string::npos ) { std::string s_key_val = s_strs.substr( 0, i_pos ); size_t i_key_pos = s_key_val.find( "=" ); if( i_key_pos != std::string::npos ) { std::string s_key = s_key_val.substr( 0, i_key_pos ); std::string s_val = s_key_val.substr( i_key_pos+1, s_key_val.size() ); StringMap_Obj.insert( make_pair( s_key, s_val ) ); } else { throw( "config file is illegal." ); } s_strs = s_strs.substr( i_pos+1, i_size ); i_pos = s_strs.find( s_split_pattern ); } } //切割字符串 void splitToVector( const std::string &s_orginal, const std::string &s_split_pattern, std::vector<std::string> &vect_str ) { vect_str.clear(); if( s_orginal.empty() ) { throw( "s_Faccount_id is empty." ); } //方便截取最后一段数据 std::string strs = s_orginal + s_split_pattern; size_t pos = strs.find(s_split_pattern); size_t size = strs.size(); while( pos != std::string::npos ) { std::string s_str = strs.substr(0,pos); TrimAllSpace( s_str ); vect_str.push_back( s_str ); strs = strs.substr(pos+1,size); pos = strs.find(s_split_pattern); } } void GetTime( std::string &s_date ) { time_t t = time(NULL); char p_date20 = {0x00}; strftime( p_date, sizeof(p_date), "%Y%m%d %H:%M:%S", localtime(&t) ); s_date = p_date; } class CGenSqlFile { public: CGenSqlFile( const std::string &s_config_file ): s_config_file( s_config_file ) { ReadFile(); } virtual ~CGenSqlFile(){} //读取每行的数据,然后进行处理 void ReadFile() { std::ifstream inFile; //以二进制可读的方式打开文件,也可以使用: inFile.open( s_config_file.data() ); inFile.open( s_config_file.c_str(), std::ios::in | std::ios::binary ); //Checks if the file stream has an associated file. if( !inFile.is_open() ) { inFile.close(); throw( "Cannot open the config file." ); } //每一行的数据 std::string s_line_buf; //读取一行内容 getline( inFile, s_line_buf ) while( getline( inFile, s_line_buf, inFile.widen('\n') ) ) { if( s_line_buf.empty() || s_line_buf0 == '#' ) { continue; } //开始数据处理 splitToMap( s_line_buf, "&", StringMap_Obj ); } //关闭文件流 inFile.close(); } //打印所有的配置数据 void ShowAllConf() const { std::cout << "=================== Config data begin. ===================" << std::endl; for( auto iter : StringMap_Obj ) { std::cout << "" << iter.first << "=" << iter.second << "" << std::endl; } std::cout << "=================== Config data end. ===================" << std::endl; } std::string GenSql() { const std::string s_genonesql_comm = GenOneSqlComm(); //所有的商户/渠道id std::vector<std::string> vect_Faccount_id; splitToVector( StringMap_Obj"Faccount_id", "|", vect_Faccount_id ); //拼装sql std::string s_sql_content; for( auto iter : vect_Faccount_id ) { s_sql_content += GenOneSql( iter, s_genonesql_comm ); } //把末尾的逗号去掉 std::string s_sql_contents = s_sql_content.erase( s_sql_content.length()-2, 2 ); //当前日期 std::string s_date; GetTime( s_date ); std::string s_sql_illustartion = "-- --------------------------------------------------------------------\n" "-- Auto Generated on " + s_date + " --------------------------------\n" "-- --------------------------------------------------------------------\n"; return ( s_sql_illustartion + StringMap_Obj"INSERT_HEADER" + "\n" + s_sql_contents + "\n;\n\n\n" ); } //生成SQL数据 std::string GenOneSql( const std::string &s_Faccount_id, const std::string &s_genonesql_comm ) { return ( "( '" + s_Faccount_id + s_genonesql_comm ); } std::string GenOneSqlComm() { std::string s_sql = "', '" + StringMap_Obj"Fpay_channel_id" + "', '" + StringMap_Obj"Fpay_method" + "', '" + StringMap_Obj"Frate_mode" + "', '" + StringMap_Obj"Frate_value" + "', '" + StringMap_Obj"Frate_value_base" + "', '1'),\n"; return s_sql; } void OpenFile() { //追加 if( "1" == StringMap_Obj"Ffile_mode" ) { ostream.open( StringMap_Obj"sql_file".c_str(), std::ofstream::out | std::ofstream::binary | std::ofstream::app ); } //覆盖 else if( "2" == StringMap_Obj"Ffile_mode" ) { ostream.open( StringMap_Obj"sql_file".c_str(), std::ofstream::out | std::ofstream::binary ); } else { throw( "Ffile_mode is illegal." ); } if( !ostream.is_open() ) { ostream.close(); throw( "Cannot open the file." ); } } void CloseFile() { ostream.close(); } //获取配置数据 const std::string GetConfByKey( std::string &s_config_key ) const { StringMap::const_iterator iter = StringMap_Obj.find( s_config_key ); if( iter != StringMap_Obj.end() ) { return iter->second; } else { return ""; } } //把数据写入到文件流中 void WriteToFile( const std::string &s_file_contents ) { ostream << s_file_contents; } protected: StringMap StringMap_Obj; private: std::string s_config_file; std::ofstream ostream; }; int main( const int argc, const char * const * argv ) { static const std::string s_config_file = "./LINUX_FILE_BASIC1_2.txt"; try { CGenSqlFile t( s_config_file ); //显示所有的配置 t.ShowAllConf(); //打开文件 t.OpenFile(); //生成SQL数据 std::string s_sql_contents = t.GenSql(); //写入到文件 t.WriteToFile( s_sql_contents ); //关闭文件 t.CloseFile(); std::string s_config_key = "sql_file"; std::cout << "\nGenerate sql file=" << t.GetConfByKey( s_config_key ) << " success." << std::endl; } catch( const char *p_errstr ) { std::cout << p_errstr << std::endl; } return 0; }

3 配置文件

上面的C++程序会读取这个linux_file_basic1_2.txt的配置文件,可以使用#符号给一些必要的数据配备注释文字。

需要说明的是Ffile_mode参数表示sql文件的写入方式,当值为2时表示每次都把生成的数据覆盖原文件中的数据;为1时表示支持把多次生成的SQL数据写入到同一个SQL脚本文件中。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

# @FileName linux_file_basic1_2.txt # @Describe Linux C++简单实现一个批量插入的sql脚本生成工具的配置文件. # @Author vfhky 2017-10-18 23:29 https://typecodes.com/cseries/genmysqlinsertsql.html # 用户账号id,多个账号使用 | 符号分隔 Faccount_id=10001342| 10001447 # 所属区域代号 Fpay_channel_id=GDSZ01 # 支付方式: # 支付宝服务窗支付 ALIPAY.JSAPI # 支付宝刷卡 ALIPAY.MICROPAY # 支付宝扫码支付 ALIPAY.NATIVE # # 微信公众号 WXPAY.JSAPI # 微信刷卡支付 WXPAY.MICROPAY # 微信扫码支付 WXPAY.NATIVE Fpay_method=WXPAY.NATIVE # 收费模式,1固定比例,2单笔计费 Frate_mode=1 # 费率值,单位:1/10000 Frate_value=50 # 基本费用,单位:分 Frate_value_base=0 # 生成的sql文件名 sql_file=user_account.sql # 生成的sql文件模式,1追加,2覆盖 Ffile_mode=2 # insert语句的头部 INSERT_HEADER=INSERT INTO USER\_ACCOUNT\_DB.t\_mch\_rate ( Faccount\_id, Fpay\_channel\_id, Fpay\_method, Frate\_mode, Frate\_value, Frate\_value\_base, Fstatus) VALUES

4 编译执行

使用《Linux C/C++工程中可生成ELF、动/静态库文件的通用Makefile》文中的Makefile编译:

Linux C++简单实现一个批量插入的sql脚本生成工具
Linux C++简单实现一个批量插入的sql脚本生成工具

然后执行生成MySql脚本如下:

Linux C++简单实现一个批量插入的sql脚本生成工具
Linux C++简单实现一个批量插入的sql脚本生成工具
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-10-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 需求说明
  • 2 C++程序
  • 3 配置文件
  • 4 编译执行
相关产品与服务
云支付
云支付(Cloud Pay,CPay)为您提供开放、可靠的聚合收款技术服务和商户管理功能。云支付支持刷卡支付、扫码支付、一码多付多种支付方式。服务商也可使用云支付提供的 SDK 和 HTTPS 接口,将云支付集成进自己的系统中,为商户提供的个性化解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档