《電子技術應用》
您所在的位置:首頁 > 其他 > 業界動態 > 數據庫遠程數據上報策略及實現

數據庫遠程數據上報策略及實現

2009-10-15
作者:鄧其軍1, 牛曉太1, 余小鵬1

??? 摘??要: 提出了一種數據庫遠程數據上報的策略,并對該策略的程序實現過程作了介紹。

??? 關鍵詞: 遠程數據? 上報? 數據壓縮

?

  在很多數據庫應用程序中,都要用到數據遠程上報的功能,如人口普查、城市危險源及事故普查、各種考試數據上報等。這些應用程序都需要將各下級部門的特定數據提取出來,通過各種方式上報到上級部門,再由上級部門進行匯總。上級部門在進行數據匯總時,有時候只需要考慮新數據的插入問題。如養路費征收IC卡網絡管理系統,此時下級的每條數據記錄是一次輸入的,在數據上報之后不會發生已經輸入的數據記錄在下級被修改,從而上級也要發生相應修改的情況。此時,用該文提到的用BulkCopy方法就可以滿足其需要。但是有的情況下,上級部門的數據匯總必須考慮下級數據所有的變化情況(新數據的插入、已有數據記錄的修改、已有數據記錄的刪除)。此時,用BulkCopy方法就無法對數據進行修改與刪除了。除非在數據上報時,下級部門將其所有數據都拷貝一份上傳;上級部門在數據接收時,將該下級部門的歷史數據全部刪除,再導入其數據,才能保證與下級的數據的一致性。顯然,這樣的處理方式,必然導致數據的傳輸及處理量大增,而且很多都是做無用功,特別是在很多情況下需要用電話撥號網絡進行數據傳輸的時候,其效率非常低。

1? 總體策略

  在作者參與開發的“城市重大危險源普查及事故管理系統”中,其下級部門為各企業,上級部門為政府安全生產管理部門。在該系統中,企業定期向政府部門上報相關的危險源及事故信息。其中危險源是指企業各種鍋爐壓力容器、加油站等可能發生危險的地點分布情況。這些危險源信息可能被增加、修改或刪除。系統開發語言為VC++6.0,企業端數據庫為Access或SQL Server,政府端數據庫為SQL Server,用OLE DB方式連接數據庫,用嵌入式SQL Server語言直接操作數據庫數據。上下級之間的數據傳輸方式為軟盤、郵件和FTP三種方案。本系統主要采用了數據庫日志及數據壓縮技術,盡可能地減少數據傳送量。

  數據庫日志就是在用VC的嵌入式SQL Server語言進行數據庫操作時,將SQL Server腳本經過適當的轉換后記錄在一個數據庫日志表(pubTbDBLog)中。上報數據時只需要提取pubTbDBLog表的部分內容。政府端接收后,按順序執行上報的SQL Server腳本,即能實現與企業端的數據完全一致。

數據上報與接收的流程如圖1所示。

?

?

2?數據庫日志操作

  數據庫日志操作的目的是保存SQL腳本,即將企業端對數據庫的操作記錄下來,存放在數據庫日志記錄表pubTbDBLog(nId,strTable,strSQL,strOperType,strGuid,dtOper,beUped)中。其中nId為主鍵,自動增量;strTable為SQL操作的數據庫表名;strSQL為對數據庫進行操作的腳本;strOperType為操作類型,包括插入、修改、刪除三種;strGuid為一個GUID值(全球惟一ID號,長度為32位字符),用來惟一標識一條記錄;dtOper為操作時間,取每條記錄生成(即對數據庫的每一次操作)的當前時間;beUped標識當前記錄是否已經上報過。

2.1 數據庫操作的要求

  在本系統中,當對需要上報數據的表進行操作時,必須滿足如下要求:

  (1)數據庫記錄的修改(包括添加、刪除、修改)必須在程序中直接用嵌入式SQL腳本實現。

  (2)執行數據庫操作必須使用一個全局函數ExecuteSQLCmd(CString strCmd),其中strCmd為執行數據庫操作的SQL腳本。該函數將腳本寫入pubTbDBLog表。

2.2 保存SQL腳本的過程說明

  下面以企業端用戶向危險源記錄表rsiTbSource(nID,strEnNo,strName,strSite,strRank,strType,dtSetUp)中插入一條危險源記錄為例,說明保存SQL腳本的操作過程。

  (1)用戶通過對話界面輸入危險源信息,其中strEnNo表示企業編號,strName表示危險源名稱,strSite表示危險源位置,strRank表示危險源等級,strType表示危險源類型,dtSetUp表示危險源建立日期。另外nID是一個自動增量,作為主鍵標識,沒有具體意義。rsiTbSource表除了以上字段外,還有其他字段,本處為簡化而省略。

  (2)用戶輸入信息完畢,點擊“保存”命令按鈕,系統將用戶輸入的信息拼成一條SQL腳本,如:CString strCmd=INSERT INTO rsiTbSource(strEnNo,strName,strSite,strRank,strType,dtSetUp)VALUES(‘420124098987001’,‘熱水鍋爐’,‘武漢市武昌區武漢大學二區’,‘二級’,‘鍋爐壓力容器’,‘2003-7-21’)。

  (3)系統調用ExecuteSQLCmd函數,包括以下(4)、(5)、(6)的內容。

  (4)對strCmd進行解析,同時生成一個32位的GUID值,將strCmd修改為strCmd=INSERT INTO rsiTbSource(strEnNo,strName,strSite,strRank,strType,dtSetUp,strGuid)VALUES(‘420124098987001’,‘熱水鍋爐’,‘武漢市武昌區武漢大學二區’,‘二級’,‘鍋爐壓力容器’,‘2003-7-21’,‘ed32wq3ddvervgjl6tgj8fjFFVBfgwgw’)。

  (5)執行腳本命令(不使用ExecuteSQLCmd函數)。

  (6)如果第(5)步執行成功,則向pubDBLog表插入一條記錄(strTbSource,strCmd,i,ed32wq3ddvervgjl6tgj8fjFFVBfgwgw,2003-7-21,0),其中的strCmd是第(4)步中strCmd的所有字符。

3? 數據上報

  數據上報是將pubTbDBLog中符合條件的記錄提取出來,進行壓縮后傳給上級。

3.1 上報數據提取

  在提取數據前要對pubTbDBLog表中的記錄進行一些預處理。由于每次對需要上報的數據庫表的操作都被記錄在了pubTbDBLog表中,有些記錄(為了方便,稱pubTbDBLog表中的一條記錄為“記錄”,稱需要上報的數據表中的一條記錄為“數據”)是不必要的,上報之前需要進行簡化。例如:向數據庫表中插入一條數據,后來對該數據進行了若干次修改,最后刪除該條數據。此時,pubTbDBLog中有三個以上與這條數據相關的記錄(它們在pubTbDBLog表中的strGuid字段值相同),其strOperType值分別是“i”、“u”、“d”。如果這三個記錄都被上報,并在政府端被先后執行,其結果還是沒有該條數據,白白浪費了執行三次SQL命令的時間。

因此,如果與某個strGuid值相關的數據最后被刪除,則在政府端只需要執行一次刪除操作,即與該strGuid值相關的pubTbDBLog表中的記錄只需要上報一條刪除的操作即可。實現對這種情況的pubTbDBLog表簡化的SQL腳本如下:

  DELETE FROM pubTbDBLog WHERE strOperType <> ′d′

  AND strGuid IN(SELECT DISTINCT a.strGuid

  FROM pubTbDBLog a WHERE a.strOperType=′d′)

  完成簡化后,即可將pubTbDBLog中符合條件(提取數據的條件是:未曾上報過的數據或指定時間范圍內的數據)的數據提取出來放入一個文件中。存放導出數據的文件可以是Access 數據庫表,或者是文本文件。作者用的是Access數據庫表,它經過壓縮解壓縮后能在政府端直接取Access表中的SQL腳本執行;也可以用文本文件,但上報時需要將符合條件的pubTbDBLog表記錄放入一個臨時文件,再用bulkCopy的方法存入文本文件。在政府端用bulkInsert的方法向一個與pubTbDBLog相同結構的表導入數據,再執行該表的記錄中的SQL腳本。

3.2 數據文件壓縮

  通常情況下,企業端向政府端報送數據是經過電話撥號網絡進行的,其傳輸速率較低。因此,有必要對存放導出數據的Access文件或文本文件進行壓縮后再傳遞。本系統使用了WinZip的數據壓縮與解壓縮接口。其過程如下(假定字符串filepathname指向需要壓縮的文件):

  (1)獲取文件路徑及文件名信息。

  int nPos,length,div;

  CString filepathtitle,filename;

  nPos=filepathname.ReverseFind(′.′);

  filepathtitle=filepathname.Left(nPos)

  /*去掉擴展名后的文件名,帶路徑*/

  length=filepathname.GetLength( );

  div=filepathname.ReverseFind(′\\′);

  filename=filepathname.Right(length-div-1);/*文件名,不帶路徑*/

  (2)創建壓縮文件實例。

  CZipFile zf(filepathtitle+″.cmp″,0);

  char buf[BUF_SIZE];//BUF_SIZE=2048

  CFile f(filepathname,CFile∷modeRead);

  zip_fileinfo zi;

  zf.UpdateZipInfo(zi,f);

  (3)向壓縮文件實例讀入數據。

  zf.OpenNewFileInZip(filename,zi,Z_BEST_COMPRESSION);

  int size_read;

  do

  {

  ?????? size_read=f.Read(buf,BUF_SIZE);

????  ?? if (size_read)

?????? ?  ? zf.WriteInFileInZip(buf,size_read);

  }

  while (size_read==BUF_SIZE);

  zf.Close( );//關閉壓縮文件實例

  經測試,壓縮文件的大小約為原文件大小的1/5~1/10,效果較好。

4? 數據接收

  政府端數據接收的工作包括三個步驟:選擇文件、解壓縮、導入數據。

4.1 選擇數據文件

  對應于企業端通過磁盤和郵件上報的數據,政府端首先需要將其存放到本地計算機的硬盤上,再進行數據文件選擇和接收。

選擇文件時,調用打開文件對話框,再由用戶選定一個或多個指定類型(*.cmp)的文件。對于每一個選中的文件,系統對其執行解壓縮和導入數據的操作。

4.2 解壓縮

  與前面所述的文件壓縮一樣,解壓縮與采用了WinZip提供的接口。其過程如下:

  (1)創建解壓縮文件實例,并用選定的壓縮文件初始化。

  CUnzipFile uf(m_strCmpFile);/*m_strCmpFile為選定的壓縮文件名*/

  (2)獲取壓縮文件中被壓縮前的文件信息。

  /*指向壓縮文件中的第一個文件(一個壓縮文件可以由多個文件壓縮而成,本系統只有一個)*/

  uf.GoToFirstFile( )

  unz_file_info ui;/*用于管理解壓縮文件信息的一個結構*/

  /*獲取壓縮文件中當前文件被壓縮前的信息,如文件名大小*/

  uf.GetCurrentFileInfo(&ui);

  int iNameSize=ui.size_filename+1;

  char*pName=new char[iNameSize];

  uf.GetCurrentFileInfo(NULL,pName,iNameSize);//獲取文件名

  TCHAR szDir[_MAX_DIR];

  TCHAR szDrive[_MAX_DRIVE];

  _tsplitpath(m_strUnCmpFile,szDrive,szDir,NULL,NULL);

  CString szPath=CString(szDrive)+szDir;

  m_strMovedDB=szPath+pName;/*解壓縮后,存放文件的路徑與文件名*/

  CFile f(m_strMovedDB,CFile∷modeWrite | CFile∷modeCreate);

  delete[ ] pName;

  (3)解壓縮。

  uf.OpenCurrentFile( );

  char buf[BUF_SIZE];

  int size_read;

  do

  {

  ?????? size_read=uf.ReadCurrentFile(buf,BUF_SIZE);

????  ?? if(size_read>0)

?????? ?  f.Write(buf,size_read);

  }

  while(size_read==BUF_SIZE);

  uf.UpdateFileStatus(f,ui);? /*還原文件的原來的日期和其他屬性*/

  uf.Close( );

4.3 導入數據

  從一個被解壓縮后生成的Access數據庫向政府端數據庫導入數據的過程為:連接該Access數據庫;按先后順序從該數據庫表pubTbDBLog中提取記錄;執行該條記錄的SQL腳本。下面只對SQL腳本的執行進行說明。

對于刪除和修改操作,SQL腳本可以直接執行。因為如果上報了重復的數據,即使某條記錄已經被刪除或修改,再執行一次同樣的刪除或修改操作,SQL命令的執行也不會造成語法錯誤或數據錯誤。

  對于插入操作,SQL腳本則不能直接執行。因為如果上報了重復的數據,則直接執行插入會使數據庫中存在二條同樣的數據。因此,先要執行一次刪除操作,將對應的數據刪除(由于pubTbDBLog表中有二個字段記錄了SQL腳本對應的表名和GUID值,刪除操作很容量執行)。即使該數據不存在,SQL命令的執行也不會造成語法錯誤或數據錯誤。

5? 結? 論

  本文討論的基于數據庫操作日志和數據壓縮的數據上報與接收技術,有著很強的通用性。對于任何一個應用系統,只要在數據庫中建立一個數據庫日志表,并且下級端執行數據庫操作時滿足2.1中提及的二個條件,就能使用。特別是對于需要上傳的數據涉及的表較多、下級端對數據經常需要修改、上下級數據要求較高度的一致性的情況,其優點更加明顯。

  本系統的數據上報與接收策略也有一些不足之處。例如,企業端pubTbDBLog表中數據的導出,可能用bulkCopy效率更高;數據導出與接收時,暫時還沒有使用多線程技術等。這些都需要在以后的工作中進一步完善。

參考文獻

1 閻宇馳,倪津.SQL Server數據庫遠程數據上報策略及其應用研究.山西交通科技,2002;(2)

2 羅琨,陳奇.連鎖店MIS中多數據庫數據通信的設計和實現.計算機應用研究,2000;(6)

3 薩師宣,王珊.數據庫系統概論.北京:高等教育出版社,1999

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:aet@chinaaet.com。
主站蜘蛛池模板: 草莓污视频在线观看午夜社区| 97se色综合一区二区二区| 日韩精品人妻系列无码专区| 亚洲最大激情网| 男Ji大巴进入女人的视频| 又爽又黄又无遮挡的视频| 要灬要灬再深点受不了好舒服 | 亚洲AV无码国产精品永久一区| 欧美色欧美亚洲高清在线视频| 免费大片黄国产在线观看| 美国美女一级毛片免费全| 国产乱偷国产偷高清| 九九久久精品国产AV片国产| 欧美综合第一页| 亚洲色大成网站WWW国产| 精品三级内地国产在线观看| 啊灬啊灬啊灬快好深在线观看| 草莓视频成人app下载| 国产午夜福利精品一区二区三区 | 深夜a级毛片免费视频| 免费A级毛片无码A| 黑人巨鞭大战中国妇女| 小明天天看成人免费看| 中文字幕日韩精品在线| 日本亚州视频在线八a| 久久免费的精品国产V∧| 日韩精品极品视频在线观看免费| 亚洲va在线va天堂成人| 欧美人与性动交α欧美精品| 亚洲成人免费电影| 欧美欧美欧美欧美| 亚洲欧美日韩视频一区| 法国性经典xxxxhd| 亚洲精品老司机| 激情亚洲综合网| 亚洲酒色1314狠狠做| 狠狠亚洲婷婷综合色香五月排名| 伊人任线任你躁| 特大巨黑人吊性xxx视频| 亚洲色大成网站WWW国产| 波多野结衣痴汉电车|