用c++Builder如何将txt文件中的数据(只有一列20万条记录)一次导入数据库 中

时间:2022-05-26 07:48:36
用c++Builder如何将txt文件中的数据(只有一列20万条记录)一次导入数据库 中  详细点。。。。谢谢

32 个解决方案

#1


相应的sql语句如下(ROWTERMINATOR对应设置的是行尾字符):
BULK INSERT  目标表名 from  'txt源文件名' WITH (FIRSTROW=1,ROWTERMINATOR = '\n');

#2


学习,还有这种方法

#3


[另类解]文本文件快速导入到MS SQL server    僵哥/mg/fad  
   07.23 01:31 
 返回群论坛 
 
 
要提高速度就尽可能减少对数据库的访问,即以一次提交多笔的方式进行提交,当然,若是能够直接以Socket的方式传输,或许会更快,这或许也就是为什么ms的bcp之类的能高速度执行对ms sql的数据导入的原因之一吧。 
举个例说吧: 

1.测试一: 
================================== 
DWORD StartTime=GetTickCount(); 

for( int i=0;i<200000;i++) 

   ADOCommand->CommandText="Insert into tablename (field1,field2,field3[...,fieldn]) values(value1,value2,value3[...,valuen])"; 
   ADOCommand->Execute(); 

DWORD EndTime=GetTickCount(); 
ShowMessage((int)(EndTime-StartTime)); 

================================== 

2.测试二 
================================== 
const AnsiString SplitEmpty="",Split=";"; 

DWORD StartTime=GetTickCount(); 

int Count,iCacheSize=1000; 

TStringList *CacheList=new TStringList(); 
try 


   for(int i=0;i<200000;i++) 
   { 
      if(Count) 
         CacheList->Add(";Insert into tablename (field1,field2,field3[...,fieldn]) values(value1,value2,value3[...,valuen])"); 
      else 
         CacheList->Add("Insert into tablename (field1,field2,field3[...,fieldn]) values(value1,value2,value3[...,valuen])"); 

      Count++; 

      if(Count==iCacheSize) 
      { 
         ADOCommand->CommandText=CacheList->Text; 
         CacheList->Clear(); 
         Count=0; 
         ADOCommand->Execute(); 
      } 
      
   } 

   if(Count>0) 
   { 
      ADOCommand->CommandText=CacheList->Text; 
      ADOCommand->Execute(); 
   } 

__finally 

   CacheList->Free(); 


DWORD EndTime=GetTickCount(); 

ShowMessage((int)(EndTime-StartTime)); 

================================== 

分别执行这两段代码往数据库当中写入20万条记录,测试二当中大概的花费依机器配置情况,大概为2~5分钟,甚至更短,测试一当中时间的花费,将会远远超过测试二。 


以前写的代码:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
   if(Key>'9'||Key<'0')
      Key='\0';        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::cmdCreateFileClick(TObject *Sender)
{
   DWORD StartAt=GetTickCount();
   AnsiString InputString=Edit6->Text;
   InputString+="\r\n";
   unsigned int Counter=StrToInt(Edit2->Text);
   FILE *fp=fopen(Edit5->Text.c_str(),"w");
   try
   {

      while(1<(Counter--))
         fwrite(InputString.c_str(),InputString.Length(),1,fp);
      fwrite(Edit6->Text.c_str(),Edit6->Text.Length(),1,fp);
   }
   __finally
   {
      fclose(fp);
   }
   DWORD EndAt=GetTickCount();
   StatusBar1->Panels->Items[0]->Text="创建文件耗时"+IntToStr(EndAt-StartAt)+"毫秒";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cmdRunClick(TObject *Sender)
{
   const AnsiString Split=";",SplitEmpty="";
   AnsiString taskid= Edit1->Text;
   AnsiString fd2=Edit3->Text;
   AnsiString context=Edit4->Text;
   char buf[1025];
   if(!FileExists(Edit5->Text))
      cmdCreateFile->Click();
   TDateTime dtStart=Now();
   StatusBar1->Panels->Items[1]->Text=TimeToStr(dtStart)+"正在执行...";
   DWORD StartAt=GetTickCount();
   ADOCommand1->ConnectionString=Edit7->Text;
   unsigned int CurrentRows=0;
   unsigned int CacheRows=StrToInt(Edit8->Text);
   HANDLE hFile=CreateFile(Edit5->Text.c_str(),
                    GENERIC_READ,
                    FILE_SHARE_READ,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    0);
   if(hFile==INVALID_HANDLE_VALUE)
   {
      StatusBar1->Panels->Items[1]->Text="打开文件["+Edit5->Text+"]失败!";
      return;
   }
   try
   {
      DWORD dwSizeL,dwSizeH;
      dwSizeL=GetFileSize(hFile,&dwSizeH);
      unsigned __int64 i64Size=dwSizeH;
      i64Size<<=32;
      i64Size+=dwSizeL;
      SetFilePointer(hFile,
                     0,
                     NULL,
                     FILE_BEGIN);
      DWORD SizeBeRead;
      TStringList *tls=new TStringList();

      try
      {
         while(i64Size>0)
         {
            SizeBeRead=1024;
            if(i64Size<SizeBeRead)
               SizeBeRead=i64Size;
            memset(buf,0,1025);
            ReadFile(hFile,
                     buf,
                     SizeBeRead,
                     &SizeBeRead,
                     NULL);
            i64Size-=SizeBeRead;
            int Index=0;
            int nIndex=0;
            char* c=buf;
            while(Index<1024)
            {
               if(buf[Index]=='\0')
                 break;
               if(buf[Index]=='\n')
               {
                  buf[Index]='\0';
                  if(Index>0)
                     if(buf[Index-1]=='\r')
                        buf[Index-1]='\0';
                  if(Index>1)
                     if(buf[Index-2]=='\r')
                        buf[Index-2]='\0';
                  tls->Add((CurrentRows>0?Split:SplitEmpty)+
                           "insert into test (id,fed1,fd2,context,state) values("+
                           taskid+",'"+AnsiString(c)+"','"+fd2+"','"+context+"',0)");
                  CurrentRows++;
                  if(CurrentRows==CacheRows)
                  {
                     ADOCommand1->CommandText=tls->Text;
                     ADOCommand1->Execute();
                     tls->Clear();
                     CurrentRows=0;
                  }
                  c+=Index-nIndex;
                  nIndex=Index;
                  nIndex++;
                  c++;
               }
               Index++;
            }
            if(i64Size<=0)
            {
               tls->Add((CurrentRows>0?Split:SplitEmpty)+
                        "insert into test (id,fed1,fd2,context,state) values("+
                        taskid+",'"+AnsiString(c)+"','"+fd2+"','"+context+"',0)");
               CurrentRows++;
            }
            else
            {
                nIndex=nIndex-1024;
                SetFilePointer(hFile,
                               nIndex,
                               NULL,
                               FILE_CURRENT);
                i64Size-=nIndex;
            }
         }
         if(CurrentRows>0)
         {
            ADOCommand1->CommandText=tls->Text;
            ADOCommand1->Execute();
            tls->Clear();
            CurrentRows=0;
         }
      }
      __finally
      {
         tls->Free();
      }
   }
   __finally
   {
       CloseHandle(hFile);
   }
   DWORD EndAt=GetTickCount();
   TDateTime dtEnd=Now();
   StatusBar1->Panels->Items[1]->Text="("+TimeToStr(dtStart)+"-"+TimeToStr(dtEnd)+")执行过程耗时"+IntToStr(EndAt-StartAt)+"毫秒";
}
//---------------------------------------------------------------------------

#4


"胡一刀"
的试了不行的

#5


僵哥写的 测试二

我已经用过了 
但是同时插入10万条记录以上 超慢 有时还死机 

#6


直接将txt数据文件倒入数据库(远程) 如何做 EXEC 等外壳试过了不行  BULK Insert 也不行 提示找不到txt文件

#7


引用 5 楼 changjuanfang 的回复:
僵哥写的 测试二 

我已经用过了 
但是同时插入10万条记录以上 超慢 有时还死机 

超慢,还死机?不知道你的机器为什么会这样.

#8


我这里有个测试需求是将100万个账号(每个12字节,每行一个账号,存储于文本文件当中),输入到数据库当中.有空我测一下发结果上来.

#9


哈哈,我笑了!学习下!

#10


引用 8 楼 unsigned 的回复:
我这里有个测试需求是将100万个账号(每个12字节,每行一个账号,存储于文本文件当中),输入到数据库当中.有空我测一下发结果上来.


等待中。。。。。

#11


僵哥的测试二 是在理想状态下的测试(只有单纯的插入数据) 现实中数据的获取也要花费相当的时间 这样 总时间就会很长 如果获取数据的方式不对 会耗费大量的cpu时间片 这样会大大影响数据的插入

#12


先將Txt文件轉爲Excel格式文件,然後將Excel導入數據庫。

#13


BULK Insert 
TXT 文件要上傳致到  SQL Server 服務器上。不要放在客戶端上。

僵哥写的 测试二 速度應該還是很快的。
BULK Insert 方案,因為要生成TXT文件並將文件上傳至服務器中,完成速度與"测试二"相比要看網絡情況與記錄數多少,一般情況下BULK Insert方案總體快些。"测试二"則為標准SQL語法,比BULK Insert 或(Insert into + OpenRowSet方式)通用。

先將Txt文件轉爲Excel格式文件,然後將Excel導入數據庫。這樣不如直接導入TXT文本。

#14


"测试二"使用ADOComand遞交數據, 比使用DBX的TSQLConnection慢.
String SQL ;
TSQLConnection *SQLConn;
//---------------
DWORD StartAt=GetTickCount();
SQLConn->StartTransaction(TransactionDesc);
try{
    for(int i = 0 ; i< 10*1000*1000; ++i) {    //共提交10M次 
      SQL.Clear();
      for(int i = 0 ; i < 10 ; ++i)            //每次插入 10 行
         SQL += "insert into TableA(Field0) Values('test data')\n";
      SQLConnection->ExecuteDirect(SQL);
    }
    SQLConn->Commit(TransactionDesc);
}
catch(Exception &E){
  SQLConn->Rollback(TransactionDesc);
  throw Exception(E.Message);
}
catch(...){
  SQLConn->Rollback(TransactionDesc);
  throw Exception(String("unknow error"));
}
DWORD EndTime=GetTickCount(); 
ShowMessage((int)(EndTime-StartTime)); 

改用TSQLConnection ,使用 並將 iCacheSize= 10 ~ 100 ; 速度估計至少提升 10% .

#15


先谢了 我先试试!! 

#16


引用 12 楼 liu1jian2 的回复:
先將Txt文件轉爲Excel格式文件,然後將Excel導入數據庫。


具体点

#17


用事务 估计慢

#18


MySQL有专门的读取语句,可以把文本文件中的数据读入数据库,比用insert快太多了

#19


引用 11 楼 changjuanfang 的回复:
僵哥的测试二 是在理想状态下的测试(只有单纯的插入数据) 现实中数据的获取也要花费相当的时间 这样 总时间就会很长 如果获取数据的方式不对 会耗费大量的cpu时间片 这样会大大影响数据的插入

需要获取数据,那是获取数据所消耗的时间,我所说的只是让数据库操作的时间尽可能少.

其实PPower说的使用DBX的TSQLConnection会比ADO操作快,这一点个人并不赞同.我没有做过实际的测试,所以无法下最终的结论.但是从理论上来讲,DBX也是需要通过ADO操作的,所以它的快只在于连接池的使用.对于单线程的程序来讲,可能在表面上看是会有所提升,但是这个并不能说明实质性的问题.

引用 17 楼 changjuanfang 的回复:
用事务 估计慢

对于这种操作,个人建议是使用显示的事务,即强制每一批提交一个事务.对于支持事务的DBMS,并不会因为你没有显示使用事务,它就不会使用事务.只是这个事务是由DBMS自己去控制.

#20


引用 18 楼 dxkh 的回复:
MySQL有专门的读取语句,可以把文本文件中的数据读入数据库,比用insert快太多了

MSSQL也有类似的,关键看源数据的格式等等.为什么你会觉得比使用insert快,只是因为很多细节由数据库系统内部进行控制和优化过了.类似的数据库系统,内部仍然还是一条条insert.

#21


如果是mssql,用bulk insert肯定是最快的,应该不会不行的啊,你试试建个文本文档到d盘下的0.txt,里面输入几行字符,然后执行:
BULK INSERT test from 'e:\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n');
(test表只有一列varchar类型)

你那个提示找不到txt文件应该是路径没写对

#22


引用 21 楼 whomin 的回复:
如果是mssql,用bulk insert肯定是最快的,应该不会不行的啊,你试试建个文本文档到d盘下的0.txt,里面输入几行字符,然后执行: 
BULK INSERT test from 'e:\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n'); 
(test表只有一列varchar类型) 

你那个提示找不到txt文件应该是路径没写对

1.buld insert如果没有记错的话,文件需要在数据库的本地磁盘;
2.输出到文件也是需要消耗时间的.

#23


晕,又打错...

#24


To unsigned :
在使用事務的情況下,我的實測結果是DBX比ADO快不少。
沒測試過不用事務的情況。(DBX4 + MSSQL)
(測試時,第一次遞交數據因為服務器要擴張表空間,這時間太多因素影響,所以要忽略。每次測試前清空表再插入數據。)
以下是偽代碼:
StartTransaction
delete table 
for(int i = 0 ; i < 10*1000*1000 ++i)
  Execute(SQL,...); 
Commit

同樣過程,DBX優於ADO即:
SQLConnection->ExecuteDirect(SQL); 
優於
ADOConnection->Execute(SQL,
cmdTex,TExecuteOptions() << eoExecuteNoRecords); //可能是我選擇的參數不對。沒測試其他參數。

不清楚DBX4的MSSQL驅動是什麼方式與MSSQL交互的?

#25


呃...僵哥说的很详细恶劣

#26


引用 22 楼 unsigned 的回复:
引用 21 楼 whomin 的回复:
如果是mssql,用bulk insert肯定是最快的,应该不会不行的啊,你试试建个文本文档到d盘下的0.txt,里面输入几行字符,然后执行: 
BULK INSERT test from 'e:\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n'); 
(test表只有一列varchar类型) 

你那个提示找不到txt文件应该是路径没写对 
 
1.buld insert如果没有记错的话,文件需要在数据库的本地磁盘; 
2.输出到文件也是需要消耗时间的.


对 用 buld insert 只有在本地磁盘 上可以操作 

关键是  要解决 远程操作的问题 用的是 ms sql

#27


如果是远程共享的文件夹,用bulk insert并无问题,我已进行了测试,是可以的:
BULK INSERT test from '\\192.168.0.1\Share\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n');

#28


不知道文本数据需要加工不?是不是规则的。
可以考虑如下方式:
给DTS包传递参数,支持的参数包括(环境变量、注册表值和参数字符)判断后,导入数据。用VBScript、JScript   编程,完成数据的判断和转换任务。
速度比较快。



#29


见识

#30


谢谢该结贴了

#31


插入數據庫有個能提高效率的寫法
insert into table(field1,field2) values(value1, value2) values(value3,value4) values(value5,value6)....
現在程序裏把所有的value拼在一起  然後一起insert
這中間省去了很多時間 試一下看看

#32


更正 以上方法 在Sql Server中似乎不能跑 
在mySql裏是可以這樣寫的 把多句合併成一句
insert into table(field) values(value1)
insert into table(field) values(value2)
insert into table(field) values(value3)
insert into table(field) values(value4)
insert into table(field) values(value5)

合併成
insert into table(field) values(value1),(value2),(value3),(value4),(value5)

#1


相应的sql语句如下(ROWTERMINATOR对应设置的是行尾字符):
BULK INSERT  目标表名 from  'txt源文件名' WITH (FIRSTROW=1,ROWTERMINATOR = '\n');

#2


学习,还有这种方法

#3


[另类解]文本文件快速导入到MS SQL server    僵哥/mg/fad  
   07.23 01:31 
 返回群论坛 
 
 
要提高速度就尽可能减少对数据库的访问,即以一次提交多笔的方式进行提交,当然,若是能够直接以Socket的方式传输,或许会更快,这或许也就是为什么ms的bcp之类的能高速度执行对ms sql的数据导入的原因之一吧。 
举个例说吧: 

1.测试一: 
================================== 
DWORD StartTime=GetTickCount(); 

for( int i=0;i<200000;i++) 

   ADOCommand->CommandText="Insert into tablename (field1,field2,field3[...,fieldn]) values(value1,value2,value3[...,valuen])"; 
   ADOCommand->Execute(); 

DWORD EndTime=GetTickCount(); 
ShowMessage((int)(EndTime-StartTime)); 

================================== 

2.测试二 
================================== 
const AnsiString SplitEmpty="",Split=";"; 

DWORD StartTime=GetTickCount(); 

int Count,iCacheSize=1000; 

TStringList *CacheList=new TStringList(); 
try 


   for(int i=0;i<200000;i++) 
   { 
      if(Count) 
         CacheList->Add(";Insert into tablename (field1,field2,field3[...,fieldn]) values(value1,value2,value3[...,valuen])"); 
      else 
         CacheList->Add("Insert into tablename (field1,field2,field3[...,fieldn]) values(value1,value2,value3[...,valuen])"); 

      Count++; 

      if(Count==iCacheSize) 
      { 
         ADOCommand->CommandText=CacheList->Text; 
         CacheList->Clear(); 
         Count=0; 
         ADOCommand->Execute(); 
      } 
      
   } 

   if(Count>0) 
   { 
      ADOCommand->CommandText=CacheList->Text; 
      ADOCommand->Execute(); 
   } 

__finally 

   CacheList->Free(); 


DWORD EndTime=GetTickCount(); 

ShowMessage((int)(EndTime-StartTime)); 

================================== 

分别执行这两段代码往数据库当中写入20万条记录,测试二当中大概的花费依机器配置情况,大概为2~5分钟,甚至更短,测试一当中时间的花费,将会远远超过测试二。 


以前写的代码:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
   if(Key>'9'||Key<'0')
      Key='\0';        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::cmdCreateFileClick(TObject *Sender)
{
   DWORD StartAt=GetTickCount();
   AnsiString InputString=Edit6->Text;
   InputString+="\r\n";
   unsigned int Counter=StrToInt(Edit2->Text);
   FILE *fp=fopen(Edit5->Text.c_str(),"w");
   try
   {

      while(1<(Counter--))
         fwrite(InputString.c_str(),InputString.Length(),1,fp);
      fwrite(Edit6->Text.c_str(),Edit6->Text.Length(),1,fp);
   }
   __finally
   {
      fclose(fp);
   }
   DWORD EndAt=GetTickCount();
   StatusBar1->Panels->Items[0]->Text="创建文件耗时"+IntToStr(EndAt-StartAt)+"毫秒";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cmdRunClick(TObject *Sender)
{
   const AnsiString Split=";",SplitEmpty="";
   AnsiString taskid= Edit1->Text;
   AnsiString fd2=Edit3->Text;
   AnsiString context=Edit4->Text;
   char buf[1025];
   if(!FileExists(Edit5->Text))
      cmdCreateFile->Click();
   TDateTime dtStart=Now();
   StatusBar1->Panels->Items[1]->Text=TimeToStr(dtStart)+"正在执行...";
   DWORD StartAt=GetTickCount();
   ADOCommand1->ConnectionString=Edit7->Text;
   unsigned int CurrentRows=0;
   unsigned int CacheRows=StrToInt(Edit8->Text);
   HANDLE hFile=CreateFile(Edit5->Text.c_str(),
                    GENERIC_READ,
                    FILE_SHARE_READ,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    0);
   if(hFile==INVALID_HANDLE_VALUE)
   {
      StatusBar1->Panels->Items[1]->Text="打开文件["+Edit5->Text+"]失败!";
      return;
   }
   try
   {
      DWORD dwSizeL,dwSizeH;
      dwSizeL=GetFileSize(hFile,&dwSizeH);
      unsigned __int64 i64Size=dwSizeH;
      i64Size<<=32;
      i64Size+=dwSizeL;
      SetFilePointer(hFile,
                     0,
                     NULL,
                     FILE_BEGIN);
      DWORD SizeBeRead;
      TStringList *tls=new TStringList();

      try
      {
         while(i64Size>0)
         {
            SizeBeRead=1024;
            if(i64Size<SizeBeRead)
               SizeBeRead=i64Size;
            memset(buf,0,1025);
            ReadFile(hFile,
                     buf,
                     SizeBeRead,
                     &SizeBeRead,
                     NULL);
            i64Size-=SizeBeRead;
            int Index=0;
            int nIndex=0;
            char* c=buf;
            while(Index<1024)
            {
               if(buf[Index]=='\0')
                 break;
               if(buf[Index]=='\n')
               {
                  buf[Index]='\0';
                  if(Index>0)
                     if(buf[Index-1]=='\r')
                        buf[Index-1]='\0';
                  if(Index>1)
                     if(buf[Index-2]=='\r')
                        buf[Index-2]='\0';
                  tls->Add((CurrentRows>0?Split:SplitEmpty)+
                           "insert into test (id,fed1,fd2,context,state) values("+
                           taskid+",'"+AnsiString(c)+"','"+fd2+"','"+context+"',0)");
                  CurrentRows++;
                  if(CurrentRows==CacheRows)
                  {
                     ADOCommand1->CommandText=tls->Text;
                     ADOCommand1->Execute();
                     tls->Clear();
                     CurrentRows=0;
                  }
                  c+=Index-nIndex;
                  nIndex=Index;
                  nIndex++;
                  c++;
               }
               Index++;
            }
            if(i64Size<=0)
            {
               tls->Add((CurrentRows>0?Split:SplitEmpty)+
                        "insert into test (id,fed1,fd2,context,state) values("+
                        taskid+",'"+AnsiString(c)+"','"+fd2+"','"+context+"',0)");
               CurrentRows++;
            }
            else
            {
                nIndex=nIndex-1024;
                SetFilePointer(hFile,
                               nIndex,
                               NULL,
                               FILE_CURRENT);
                i64Size-=nIndex;
            }
         }
         if(CurrentRows>0)
         {
            ADOCommand1->CommandText=tls->Text;
            ADOCommand1->Execute();
            tls->Clear();
            CurrentRows=0;
         }
      }
      __finally
      {
         tls->Free();
      }
   }
   __finally
   {
       CloseHandle(hFile);
   }
   DWORD EndAt=GetTickCount();
   TDateTime dtEnd=Now();
   StatusBar1->Panels->Items[1]->Text="("+TimeToStr(dtStart)+"-"+TimeToStr(dtEnd)+")执行过程耗时"+IntToStr(EndAt-StartAt)+"毫秒";
}
//---------------------------------------------------------------------------

#4


"胡一刀"
的试了不行的

#5


僵哥写的 测试二

我已经用过了 
但是同时插入10万条记录以上 超慢 有时还死机 

#6


直接将txt数据文件倒入数据库(远程) 如何做 EXEC 等外壳试过了不行  BULK Insert 也不行 提示找不到txt文件

#7


引用 5 楼 changjuanfang 的回复:
僵哥写的 测试二 

我已经用过了 
但是同时插入10万条记录以上 超慢 有时还死机 

超慢,还死机?不知道你的机器为什么会这样.

#8


我这里有个测试需求是将100万个账号(每个12字节,每行一个账号,存储于文本文件当中),输入到数据库当中.有空我测一下发结果上来.

#9


哈哈,我笑了!学习下!

#10


引用 8 楼 unsigned 的回复:
我这里有个测试需求是将100万个账号(每个12字节,每行一个账号,存储于文本文件当中),输入到数据库当中.有空我测一下发结果上来.


等待中。。。。。

#11


僵哥的测试二 是在理想状态下的测试(只有单纯的插入数据) 现实中数据的获取也要花费相当的时间 这样 总时间就会很长 如果获取数据的方式不对 会耗费大量的cpu时间片 这样会大大影响数据的插入

#12


先將Txt文件轉爲Excel格式文件,然後將Excel導入數據庫。

#13


BULK Insert 
TXT 文件要上傳致到  SQL Server 服務器上。不要放在客戶端上。

僵哥写的 测试二 速度應該還是很快的。
BULK Insert 方案,因為要生成TXT文件並將文件上傳至服務器中,完成速度與"测试二"相比要看網絡情況與記錄數多少,一般情況下BULK Insert方案總體快些。"测试二"則為標准SQL語法,比BULK Insert 或(Insert into + OpenRowSet方式)通用。

先將Txt文件轉爲Excel格式文件,然後將Excel導入數據庫。這樣不如直接導入TXT文本。

#14


"测试二"使用ADOComand遞交數據, 比使用DBX的TSQLConnection慢.
String SQL ;
TSQLConnection *SQLConn;
//---------------
DWORD StartAt=GetTickCount();
SQLConn->StartTransaction(TransactionDesc);
try{
    for(int i = 0 ; i< 10*1000*1000; ++i) {    //共提交10M次 
      SQL.Clear();
      for(int i = 0 ; i < 10 ; ++i)            //每次插入 10 行
         SQL += "insert into TableA(Field0) Values('test data')\n";
      SQLConnection->ExecuteDirect(SQL);
    }
    SQLConn->Commit(TransactionDesc);
}
catch(Exception &E){
  SQLConn->Rollback(TransactionDesc);
  throw Exception(E.Message);
}
catch(...){
  SQLConn->Rollback(TransactionDesc);
  throw Exception(String("unknow error"));
}
DWORD EndTime=GetTickCount(); 
ShowMessage((int)(EndTime-StartTime)); 

改用TSQLConnection ,使用 並將 iCacheSize= 10 ~ 100 ; 速度估計至少提升 10% .

#15


先谢了 我先试试!! 

#16


引用 12 楼 liu1jian2 的回复:
先將Txt文件轉爲Excel格式文件,然後將Excel導入數據庫。


具体点

#17


用事务 估计慢

#18


MySQL有专门的读取语句,可以把文本文件中的数据读入数据库,比用insert快太多了

#19


引用 11 楼 changjuanfang 的回复:
僵哥的测试二 是在理想状态下的测试(只有单纯的插入数据) 现实中数据的获取也要花费相当的时间 这样 总时间就会很长 如果获取数据的方式不对 会耗费大量的cpu时间片 这样会大大影响数据的插入

需要获取数据,那是获取数据所消耗的时间,我所说的只是让数据库操作的时间尽可能少.

其实PPower说的使用DBX的TSQLConnection会比ADO操作快,这一点个人并不赞同.我没有做过实际的测试,所以无法下最终的结论.但是从理论上来讲,DBX也是需要通过ADO操作的,所以它的快只在于连接池的使用.对于单线程的程序来讲,可能在表面上看是会有所提升,但是这个并不能说明实质性的问题.

引用 17 楼 changjuanfang 的回复:
用事务 估计慢

对于这种操作,个人建议是使用显示的事务,即强制每一批提交一个事务.对于支持事务的DBMS,并不会因为你没有显示使用事务,它就不会使用事务.只是这个事务是由DBMS自己去控制.

#20


引用 18 楼 dxkh 的回复:
MySQL有专门的读取语句,可以把文本文件中的数据读入数据库,比用insert快太多了

MSSQL也有类似的,关键看源数据的格式等等.为什么你会觉得比使用insert快,只是因为很多细节由数据库系统内部进行控制和优化过了.类似的数据库系统,内部仍然还是一条条insert.

#21


如果是mssql,用bulk insert肯定是最快的,应该不会不行的啊,你试试建个文本文档到d盘下的0.txt,里面输入几行字符,然后执行:
BULK INSERT test from 'e:\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n');
(test表只有一列varchar类型)

你那个提示找不到txt文件应该是路径没写对

#22


引用 21 楼 whomin 的回复:
如果是mssql,用bulk insert肯定是最快的,应该不会不行的啊,你试试建个文本文档到d盘下的0.txt,里面输入几行字符,然后执行: 
BULK INSERT test from 'e:\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n'); 
(test表只有一列varchar类型) 

你那个提示找不到txt文件应该是路径没写对

1.buld insert如果没有记错的话,文件需要在数据库的本地磁盘;
2.输出到文件也是需要消耗时间的.

#23


晕,又打错...

#24


To unsigned :
在使用事務的情況下,我的實測結果是DBX比ADO快不少。
沒測試過不用事務的情況。(DBX4 + MSSQL)
(測試時,第一次遞交數據因為服務器要擴張表空間,這時間太多因素影響,所以要忽略。每次測試前清空表再插入數據。)
以下是偽代碼:
StartTransaction
delete table 
for(int i = 0 ; i < 10*1000*1000 ++i)
  Execute(SQL,...); 
Commit

同樣過程,DBX優於ADO即:
SQLConnection->ExecuteDirect(SQL); 
優於
ADOConnection->Execute(SQL,
cmdTex,TExecuteOptions() << eoExecuteNoRecords); //可能是我選擇的參數不對。沒測試其他參數。

不清楚DBX4的MSSQL驅動是什麼方式與MSSQL交互的?

#25


呃...僵哥说的很详细恶劣

#26


引用 22 楼 unsigned 的回复:
引用 21 楼 whomin 的回复:
如果是mssql,用bulk insert肯定是最快的,应该不会不行的啊,你试试建个文本文档到d盘下的0.txt,里面输入几行字符,然后执行: 
BULK INSERT test from 'e:\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n'); 
(test表只有一列varchar类型) 

你那个提示找不到txt文件应该是路径没写对 
 
1.buld insert如果没有记错的话,文件需要在数据库的本地磁盘; 
2.输出到文件也是需要消耗时间的.


对 用 buld insert 只有在本地磁盘 上可以操作 

关键是  要解决 远程操作的问题 用的是 ms sql

#27


如果是远程共享的文件夹,用bulk insert并无问题,我已进行了测试,是可以的:
BULK INSERT test from '\\192.168.0.1\Share\0.txt' WITH (FIRSTROW=1,ROWTERMINATOR = '\n');

#28


不知道文本数据需要加工不?是不是规则的。
可以考虑如下方式:
给DTS包传递参数,支持的参数包括(环境变量、注册表值和参数字符)判断后,导入数据。用VBScript、JScript   编程,完成数据的判断和转换任务。
速度比较快。



#29


见识

#30


谢谢该结贴了

#31


插入數據庫有個能提高效率的寫法
insert into table(field1,field2) values(value1, value2) values(value3,value4) values(value5,value6)....
現在程序裏把所有的value拼在一起  然後一起insert
這中間省去了很多時間 試一下看看

#32


更正 以上方法 在Sql Server中似乎不能跑 
在mySql裏是可以這樣寫的 把多句合併成一句
insert into table(field) values(value1)
insert into table(field) values(value2)
insert into table(field) values(value3)
insert into table(field) values(value4)
insert into table(field) values(value5)

合併成
insert into table(field) values(value1),(value2),(value3),(value4),(value5)