1. 程式人生 > >Sqlite3批量寫入資料到資料庫中

Sqlite3批量寫入資料到資料庫中

1、建立或者開啟資料庫

int nResult  = sqlite3_open(strDBPath.c_str(),&pDb);
 if (SQLITE_OK != nResult)
 {
  sqlite3_close(pDb);
  pDb = NULL;
  AfxMessageBox("建立資料庫檔案失敗!");
  return pDb;
 }
2、建立數資料據庫表,如果是開啟就無需這一步的建立
std::string strSQL = "create table T_AIS_GRID"
		"(ID NUMBER PRIMARY KEY,"
		"MMSI VARCHAR2(20) not NULL,"
		"CHANNEL VARCHAR2(1) not NULL,"
		"GRIDX VARCHAR2(20) not NULL,"
		"GRIDY VARCHAR2(20) not NULL,"
		"LONGITUDE NUMBER,"
		"LATITUDE NUMBER,"
		"SPEED NUMBER,"
		"HEADING NUMBER,"
		"COURSE NUMBER,"
		"TIME NUMBER,"
		"DESTINATION VARCHAR2(20),"
		"NOTE VARCHAR2(100)"
		")";
	nResult = sqlite3_exec(pDb,strSQL.c_str(),NULL,NULL,&errmsg);
	if (SQLITE_OK != nResult)
	{
		sqlite3_close(pDb);
		pDb = NULL;
		AfxMessageBox("建立表失敗!");
		return pDb;
	}
3、設定屬性,比如記憶體大小、讀寫速度等
void  SetAttributes(sqlite3*pDB)
{
	std::string         lstrSQL ;
	SYSTEM_INFO         lsiSysInfo;
	TCHAR               ltcBuf[MAX_PATH] ;

	GetSystemInfo(&lsiSysInfo); 
	memset(ltcBuf,0,MAX_PATH) ;
	sprintf_s(ltcBuf,MAX_PATH,"PRAGMA page_size = %d;",lsiSysInfo.dwPageSize );
	lstrSQL = ltcBuf ;   
	Pragmas(pDB,lstrSQL);
	/**  設定頁面計數*/
	lstrSQL = "PRAGMA max_page_count = 1073741823 ;";
	Pragmas(pDB,lstrSQL);
	/**  設定空間自動回收*/
	lstrSQL = "PRAGMA auto_vacuum = 0;"  ;   
	Pragmas(pDB,lstrSQL);
	/**  設定本次開啟的緩衝大小,對讀寫速度無太大影響*/
	lstrSQL =  "PRAGMA cache_size = 8192;"  ;   
	Pragmas(pDB,lstrSQL);
	/**  設定預設緩衝大小失敗,對讀寫速度無太大影響*/
	lstrSQL =  "PRAGMA default_cache_size = 8192;"  ;   
	Pragmas(pDB,lstrSQL);
	/**  設定使用UTF8編碼*/
	lstrSQL =  "PRAGMA encoding     = 'UTF-8'; "  ;   
	Pragmas(pDB,lstrSQL);
}
bool Pragmas(sqlite3*pDB,std::string lstrCommands)
{
	try 
	{
		if(pDB)
		{
			std::string     lstrSQL = lstrCommands ;
			if(sqlite3_exec(pDB ,ASCIItoUTF8(lstrSQL).c_str(), NULL, NULL, NULL) != SQLITE_OK )
			{
				//ACE_ERROR((LM_ERROR,ACE_TEXT("[%D(%t)]    Pragmas fail : %s\n"),lstrSQL.c_str()));
			} 
			else
			{
#ifdef PRAGMAS_QUERY
				sqlite3_stmt*       lstmt ;
				const char*         ltail ;
				lstrSQL = lstrCommands.substr(0,lstrCommands.find(_T("=")));
				lstrSQL += _T(";");
				if(sqlite3_prepare(pDB,ASCIItoUTF8(lstrSQL).c_str(), -1, &lstmt, <ail) != SQLITE_OK) 
				{
					//ACE_ERROR((LM_ERROR,ACE_TEXT("[%D(%t)] SQLite error:prepare sql failure:%s , error: %s\n"),lstrSQL.c_str(),sqlite3_errmsg(m_pDB)));
				}
				while(sqlite3_step(lstmt) == SQLITE_ROW) 
				{    
					if(sqlite3_column_count(lstmt) == 1)
					{ 
						//ACE_DEBUG((LM_DEBUG,ACE_TEXT("[%D(%t)] Set:%s Query:%s \n"),lstrCommands.c_str(), (char *)sqlite3_column_text(lstmt,0))) ;   
					}
				}
				sqlite3_finalize(lstmt);
#endif
				//ACE_DEBUG ((LM_DEBUG,"[%D(%t)]  SQLite release memory: %.04fMB \n",sqlite3_release_memory((int)sqlite3_memory_highwater(true))/(1024*1024.f)));
				return true ;
			}
		}
		else
		{
			//ACE_ERROR((LM_ERROR,ACE_TEXT("[%D(%t)]    Pragmas fail : SQLite db not open\n")));
		}
	}
	catch(...)
	{
		//ACE_ERROR((LM_ERROR,ACE_TEXT("[%D(%t)]    Exc pragma command exception: %s\n"),lstrCommands.c_str()));
	}
	return false ;
}

4、準備插入

sqlite3_stmt * stat = NULL;
std::string strSQLG  ="INSERT INTO T_AIS_GRID (ID,MMSI,CHANNEL,GRIDX,GRIDY,LONGITUDE,LATITUDE,SPEED,HEADING,COURSE,TIME,DESTINATION) VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12)";//問號?代表這些欄位的值目前為不確定的值,賦值在後面,數字表示第幾個欄位
	int result =sqlite3_prepare_v2(pDb,strSQLG.c_str(),-1,&stat, NULL);
	if(result != SQLITE_OK )
	{
		DWORD E = GetLastError();
		sqlite3_reset(stat);
		sqlite3_close(pDb);
		pDbG = NULL;
		AfxMessageBox("資料插入失敗!");
		return;
	}

5、開始事務

        std::string strTrans = "begin transaction;";//開始執行事務
	int nRet = sqlite3_exec(pDb, strTrans.c_str(), 0, 0, &errmsg);
	if (nRet == SQLITE_OK)
	{
		nRet = sqlite3_changes(pDb);
	}
	else
	{
		sqlite3_finalize(stat); //把剛才分配的內容析構掉
		sqlite3_close(pDb);
		pDb = NULL;
		return;
	}

6、為每一個欄位繫結變數

                     for(int i = 0 ;i < num;i++)  
                       {bind(stat,1, (int)(j+1));
			bind(stat,2, (char*)strID.c_str());
			bind(stat,3, (char*)strChannel.c_str());
			bind(stat,4, (char*)strX.c_str());
			bind(stat,5, (char*)strY.c_str());
			bind(stat,6, (double)dLon);
			bind(stat,7, (double)dLat);
			bind(stat,8, (double)fSpeed);
			bind(stat,9, (double)fHeading);
			bind(stat,10, (double)fCourse);
			bind(stat,11,(__int64)i64CurTime);
			bind(stat,12,(char*)ASCIItoUTF8(strDes).c_str());
                        //bind(stat,14,(const UCHAR*)pBuf,totallength);//這個是對Blob欄位進行插入,pBuf裡面存入的是二進位制
                        int result = sqlite3_step(stat);//返回101是執行成功
                        result     = sqlite3_reset(stat);
}//中文字元需要轉換成資料庫要的格式UTF8
void bind(sqlite3_stmt * stat,int nParam, const char* szValue)
{
	if (stat!=NULL)
	{
		int nRes = sqlite3_bind_text(stat, nParam, szValue, -1, SQLITE_TRANSIENT);
		if (nRes != SQLITE_OK)
		{
			return;
		}
	}
}

void bind(sqlite3_stmt * stat,int nParam, const int nValue)
{
	if (stat!=NULL)
	{
		int nRes = sqlite3_bind_int(stat, nParam, nValue);
		if (nRes != SQLITE_OK)
		{
			return;
		}
	}
}

void bind(sqlite3_stmt * stat,int nParam, const __int64 llValue)
{
	if (stat!=NULL)
	{
		int nRes = sqlite3_bind_int64(stat, nParam, llValue);
		if (nRes != SQLITE_OK)
		{
			return;
		}
	}
}

void bind(sqlite3_stmt * stat,int nParam, const double dValue)
{
	if (stat!=NULL)
	{
		int nRes = sqlite3_bind_double(stat, nParam, dValue);
		if (nRes != SQLITE_OK)
		{
			return;
		}
	}
}

void bind(sqlite3_stmt * stat,int nParam, const unsigned char* blobValue, int nLen)
{
	int nRes = sqlite3_bind_blob(stat, nParam,(const void*)blobValue, nLen, SQLITE_TRANSIENT);
	if (nRes != SQLITE_OK)
	{
		return;
	}
}

7、執行/提交以上的事務(一次性批量的寫入到資料庫中,而不需要一條一條的)

	        strTrans = "commit transaction;";
		nRet = sqlite3_exec(pDb, strTrans.c_str(), 0, 0, &errmsg);
		if (nRet == SQLITE_OK)
		{
			nRet = sqlite3_changes(pDb);
		}
		else
		{
			sqlite3_finalize(stat); //把剛才分配的內容析構掉
			sqlite3_close(pDb);
			pDbM = NULL;
			return;
		}
		sqlite3_finalize(stat); //把剛才分配的內容析構掉
		sqlite3_close(pDb);