半夜看见 @Ovear 发文《我是这么设计高性能海量数(ku)据(zi)查询系统的(一)》,留言中@0x0F 也提到加载数据入库的工具。感觉使用SQL语法分析,再提取数据有点麻烦。遂敲了一个简单的数据导入工具,灵活多变。至于强大与否,得看看客的正则水平如何了。
界面:
原理:
软件工作的时候是这样的。
1.先加载选定的数据文本。逐行读取。
2.每行数据,用正则匹配。如果匹配成功,就开始用匹配到的内容替换软件中的SQL语句中,<match*>部分。
3.执行SQL入库。
例子:
假设我们有一个test.txt的库,内容格式大致如下:
111111 test1 222222 test2 333333 test3 444444 test4 中文测试 abc123
我们要组合成111111--test1这样的格式,导入到 sed_data 库中的test表中的info字段中。
那么我们的正则语句这样写
^(.+?)\s(.+?)$
括号中间是我们要提取的内容。看不明白的朋友上面语句你可以粗浅理解为
“行首(字符串)空格(字符串)行尾”
插入语句这样写:
INSERT INTO `test`(`info`) VALUES('<match1>--<match2>');
语句里面的<match1><match2>是关键。表示正则中的匹配到的第一个括号里面的内容和第二个括号里面的内容。如果你正则有8个() 提取的内容。那么对应的也有 <match1>、<match2>、<match3>...<match8>
以此类推。match注意全部为小写。
在软件中大致如下样子【数据库信息我没填,注意别遗漏了】:
执行后可以看到相关数据库、表、字段正确插入了我们的数据库:
再举个例子
假如数据的格式如下:
VALUES (1, '个人', 'admin', 'e10adc3949ba59abbe56e057f20f883e', 'admin', '男', 100, 0, 0, 0, '', 10006, 10, 0, '', 0, '', 1343443904, '', 1371490073, '127.0.0.1', -1)
正则大致可以这么写
\((\d*), '(.+?)', '(.+?)', '(.+?)', '(.+?)', '(.+?)'
以上语句我没有真正测试能否匹配出来。可能还需要调试,只是举个例子。如果上面语句正常的话
那么
<match1>=1 <match2>=个人 <match3>=admin <match4>=e10adc3949ba59abbe56e057f20f883e
我们要入库它用户名到 user_info 表中的 user、pass字段中的话,SQL语句这样写
insert into `user_info`(`user`,`pass`) values('<match3>','<match4>');
如果事前对数据文件,稍作整理的话,应该用这个软件,配合正则能将很多数据入库。
源码预览:
uMain.pas
unit uMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, UniProvider, MySQLUniProvider, DB, MemDS, DBAccess, Uni,uThread,PerlRegEx; type TForm1 = class(TForm) grpSetting: TGroupBox; lblMysqlUser: TLabel; lblMySQLPass: TLabel; lblMySQLDB: TLabel; lblMySQLPort: TLabel; lblMySQLHost: TLabel; edtMySQLUser: TEdit; edtMySQLPass: TEdit; edtMySQLDB: TEdit; edtMySQLHost: TEdit; edtMySQLPort: TEdit; conData: TUniConnection; SqlData: TUniQuery; MySQLUniProvider1: TMySQLUniProvider; pnlMain: TPanel; lblMatch: TLabel; edtMatch: TEdit; mmoInsertSQL: TMemo; lblInsertSQL: TLabel; btnConn: TButton; btnSelectFile: TButton; btnProc: TButton; dlgOpen1: TOpenDialog; lblAuthor: TLabel; procedure btnConnClick(Sender: TObject); procedure btnSelectFileClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure btnProcClick(Sender: TObject); private { Private declarations } public procedure AddData(sContent: string); end; var Form1: TForm1; sDataPath: string; reg: TPerlRegEx; sReg,sInertSQL: string; implementation {$R *.dfm} procedure TForm1.AddData(sContent: string); var i: Integer; sSQL,sMatch: string; begin reg.Subject := sContent; reg.RegEx := sReg; if reg.Match then begin sSQL := sInertSQL; for i := 1 to reg.GroupCount do begin sMatch := '<match'+IntToStr(i)+'>'; sSQL := StringReplace(sSQL,sMatch,reg.Groups[i],[rfReplaceAll]); end; SqlData.Close; SqlData.SQL.Clear; SqlData.SQL.Text := sSQL; SqlData.ExecSQL; end; end; procedure TForm1.btnConnClick(Sender: TObject); begin if not conData.Connected then begin conData.ProviderName := 'MySql'; conData.Port := StrToInt(Trim(edtMySQLPort.Text)); conData.Database := Trim(edtMySQLDB.Text); conData.Username := Trim(edtMySQLUser.Text); conData.Password := Trim(edtMySQLPass.Text); conData.Server := Trim(edtMySQLHost.Text); conData.SpecificOptions.Values['UseUnicode'] := 'True'; try conData.Connect; except Exit; end; end; if conData.Connected then ShowMessage('连接成功!') else ShowMessage('连接失败!'); end; procedure TForm1.btnProcClick(Sender: TObject); var myThread: TAddData; begin sReg := edtMatch.Text; sInertSQL := mmoInsertSQL.Text; myThread := TAddData.Create(False); end; procedure TForm1.btnSelectFileClick(Sender: TObject); begin if dlgOpen1.Execute then begin sDataPath := dlgOpen1.FileName; grpSetting.Caption := '已选择:'+sDataPath; end; end; procedure TForm1.FormCreate(Sender: TObject); begin reg := TPerlRegEx.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin reg.Free; end; end.
线程文件uThread.padd(仅创建一个线程,为了处理数据的时候不卡界面):
unit uThread; interface uses Classes,SysUtils,Windows; type TAddData = class(TThread) private { Private declarations } protected procedure Execute; override; public constructor Create(CreateSuspended:Boolean);Overload; end; implementation uses uMain; constructor TAddData.Create(CreateSuspended: Boolean); begin Inherited Create(CreateSuspended); FreeOnTerminate := True; end; { AddData } procedure TAddData.Execute; var sList: textfile; iTime: LongInt; lpline: string; begin with Form1 do begin AssignFile(sList,sDataPath); Reset(sList); iTime := gettickcount; SqlData.Close; SqlData.SQL.Clear; SqlData.SQL.Text := 'set names utf8'; SqlData.ExecSQL; repeat Readln(sList,lpline); AddData(lpline); until eof(slist); iTime := GetTickCount - iTime; Caption := '完成了!!!'+inttostr(itime div 60000)+'m.'; CloseFile(sList); end; end; end.
---------------------------------------------------------------------------------
软件下载(仅供没有编译环境的朋友使用)
链接: http://pan.baidu.com/s/1dDEEDpR 密码: qe7g
为防止被扣黑帽,捆绑什么的,建议大家用源码自己编译,安全放心。
源码版(Delphi2010,组件有UniDAC、PerlReg,自己百度)
链接: http://pan.baidu.com/s/1qWppJCK 密码: dbka
内容很简单,几行代码,随便敲敲,很多没有特别注意的地方,还望海涵,不满意的自己改。
最后不用谢,请叫我雷锋 :)
相关吐槽:
1#
Sunshie (http://phpinfo.me) | 2014-01-01 08:08
雷峰
2#
寂寞的瘦子 (’) | 2014-01-01 08:16
早
3#
核攻击 (统治全球,奴役全人类!毁灭任何胆敢阻拦的有机生物!) | 2014-01-01 10:45
方法挺不错的。
4#
点点 (http://t.qq.com/ox_diandi) | 2014-01-01 10:49
雷峰
5#
x1aoh4i (我只能送你们一句话:"乌云自有千种粒,乌云自有黄金屋,乌云自有颜如玉") | 2014-01-01 10:50
不错