1. 程式人生 > >C++:MFC通過ODBC操作Orcale資料庫的說明

C++:MFC通過ODBC操作Orcale資料庫的說明

本文通過ODBC方式連線Oracle資料庫,使用MFC進行資料庫操作的關鍵函式。詳細介紹了配置ODBC的方法和其中遇到的各項困難,以及最終幾個的關鍵函式。

1. ODBC資料來源連線資料庫方式

1.1 使用odbc資料來源的好處

  • 客戶端無需知道資料庫所在的IP地址。只要在資料庫中配置好監聽,客戶端配置好檔案tnsnames.ora。客戶端電腦中的程式即可通過資料來源直接訪問Orcale資料庫口程式的開發人員只需呼叫ODBC相關的函式即可實現通訊。
  • 在系統中直接配置監聽TNS、使用者名稱UID、密碼PSW,可以避免資料庫密碼等資訊維護,客戶端電腦上介面程式的修改,程式開發人員也不需要知道密碼。
  • 一個數據庫可以配置多個ns。

1.2 客戶端安裝orcale的驅動

為了方便,我們將Oracle資料庫所在電腦稱作伺服器,將配置ODBC的電腦稱作客戶端。需要注意的是隻有客戶端需要在windows系統中配置odbc資料來源,伺服器只需要在Oracle資料庫內部配置好監聽即可,不需要配置odbc資料來源。現在假設Oracle資料庫伺服器配置的服務命名orcl,如下圖所示。
在這裡插入圖片描述
​​首先要明確Oracle_ODBC驅動有32位和64位之分。理論上講,客戶端電腦安裝的的驅動一定要和伺服器安裝的Orcale資料庫的位數一致。如果不一致會出現 “在指定的DSN中,驅動程式和應用程式之間的體系結構不匹配”

的問題。
Microsoft 會預設自帶一個 32位Oracle ODBC的ODBC驅動檔案,但是我們在這個驅動檔案上建立資料來源的話會報錯 一般會提示 “未發現Oracle™客戶端和網路元件。”的錯誤。我們需要這樣的情況下我們要重新下載安裝手動配置32位ODBC資料驅動。

  • (1) 首先把我提供的instantclient_12_1 檔案放在 C:\ProgramFiles 目錄下。

  • (2) 用記事本開啟“C:\ProgramFiles\instantclient_12_1\network\ADMIN\tnsnames.ora”檔案將主機名"HOST"填寫你要連線的IP地址(這條是針對客戶端的電腦,伺服器側的電腦不用動),其它不用動。
    在這裡插入圖片描述

  • (3) 新增環境變數(右鍵單擊我的電腦—屬性—高階選項卡—環境變數)TNS_ADMIN,變數值指向ADMIN目錄,我的配置是c:\Program Files\instantclient_12_1\NETWORK\ADMIN;新建的變數名填寫TNS_ADMIN 變數值填寫c:\Program Files\instantclient_12_1\NETWORK\ADMIN
    在這裡插入圖片描述

  • (4) 雙擊instantclient_12_1目錄下的odbc_install.exe完成安裝。注:安裝時出現DOC框,並一閃而過,你可能無法判斷是不是正確安裝。其實你可以cmd進入instantclient_12_1目錄,並.\odbc_install.exe手動安裝。

  • 32位Oracle ODBC驅動安裝包及安裝教程地址:https://download.csdn.net/download/dashumak/10421614 (壓縮包中是xp下的安裝方法,win7下的安裝方法見 本文)

  • 64位Oracle ODBC驅動安裝包地址(安裝方式很簡單,找到odbc_install.exe右鍵管理員方式執行即可):https://download.csdn.net/download/dashumak/10421608

  • 這兩個都是在沒有安裝過Oracle的電腦上安裝的驅動,如果安裝過Oracle的電腦是有相應的驅動的,但是也要檢查一下驅動的版本(好像32位的Oracle裝的是32位的驅動,64位的甲骨文裝的是64位的驅動)。

1.3 Win7電腦配置ODBC資料來源管理器

通過“執行”進入32位或者64位ODBC資料來源管理器的方法是如下(這裡資料夾名和軟體的位數擰著呢,不知為什麼):

  • 64位: C:\windows\system32\odbcad32.exe
  • 32位: C:\Windows\SysWOW64\odbcad32.exe
    客戶端需要配置ODBC資料來源,配置介面如下圖所示。
    在這裡插入圖片描述
    各項引數說明如下(這裡的程式碼是後續提到的CDatabase::OpenEx中的引數):
  • Data Source Name(即是程式碼中用到的DSN),取值是客戶端自行設定。
  • Description只是一個描述,取值無所謂,可不做任何配置
  • ODBC中的User ID(即是程式碼中的UID),取值是由Oracle資料庫配置,本次配置是sms。
  • TNS Service Name要(即是程式碼中的DBQ),是由客戶端所在電腦tnsnames.ora配置檔案中確定的,通過查詢下圖所示的檔案,我們可以發現ORCLA和ORCLCYJ均與資料庫的orcl繫結,因此客戶端配置ODBC資料來源中的TNS Service Name位ORCLA和ORCLCYJ均可。tnsnames.ora檔案一般在orcale驅動的位置,如E:\app\dgax\product\11.2.0\client_1\network\admin。
    在這裡插入圖片描述

然後點選測試,輸入資料庫配置好的對應UID的密碼,出現下圖表明連線成功
在這裡插入圖片描述

1.4 Xp電腦配置ODBC資料庫源管理器

配置方法:開始選單>>ODBC,截圖如下
在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述

1.4 解決MySQl(或者ODBC測試時)出現”no lisnter“問題

首先在執行中輸入services.msc進入服務,啟動OracleOraDb11g_home1TNSListener服務(右鍵屬性選擇自動方式,這樣每次重啟後會自動開啟,但是因為防火牆這個服務不是每次都能自動開啟)。
在這裡插入圖片描述
啟動完後,重新整理一下,可能出現服務啟動後又自動關閉的問題,這是由於資料庫配置監聽檔案的問題,需要修改”listener.ora“檔案。比如我的lisnter.ora檔案所在路徑是“C:\Oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN”,不用管那些bak檔案。
在這裡插入圖片描述

右鍵記事本開啟(最好先備份一下),檢查這個問題是不是有問題,往往是HOST不對,HOST應該與計算機的名稱一致,修改後儲存,重新到services.msc中啟動“OracleOraDb11g_home1TNSListener”服務,這樣應該就可以啟動了。至於”listener.ora“文件中記錄的各種檔案地址,對一般監聽影響不大,倘若修改完之後上述服務扔是啟動之後仍是立刻自動關閉,就應該回到這個文件中,講檔案地址檢查一遍,修改為正確的地址。
在這裡插入圖片描述
在這裡插入圖片描述
這樣問題就解決了,可以到cmd中輸入lsnrctl命令
在這裡插入圖片描述
輸入status,檢視資料庫監聽狀態,出現下圖表示監聽成功
在這裡插入圖片描述


2. MFC藉助ODBC操作資料庫

2.1 利用CDatabase::OpenEx開啟資料庫連線

CDatabase db_Smartfuel;
BOOL bOpenDbSucc=FALSE;
try{
	db_Smartfuel.OpenEx(_T("DSN=orcl;UID=sms;PWD=123321;DBQ=ORCLCYJ ;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;"),CDatabase::noOdbcDialog);
	}
catch(CDBException*e){
		AfxMessageBox(e->m_strError);//彈窗顯示錯誤資訊
		e->delete();
	}

CDatabase::OpenEx()msdn官方說明,這裡我簡要介紹一下引數。

  • 第一個引數是一個含有連線關係的字串,要參照ODBC配置填入相關引數,
    • (1)DSN和Data Source Name取值一致
    • (2)User ID要和程式碼中的UID保持一致
    • (3)TNS Service Name要和程式碼中的DBQ取值對應一致,
  • 第二個引數 CDatabase::noOdbcDialog表示無彈窗提示

2.2 利用CRecordset::m_strFilter進行資料篩選

CRecordset類有兩個公共資料成員m_strFilter和m_strSort用來設定對記錄的過濾和排序。在呼叫Open或Requery前,如果在這兩個資料成員中指定了過濾或排序,那麼Open和Requery將按這兩個資料成員指定的過濾和排序來查詢資料來源。
成員m_strFilter用於指定過濾器.m_strFilter實際上包含了SQL的WHERE子句的內容,但它不含WHERE關鍵字.使用m_strFilter的一個例子為:

BOOL CSMST_BSAMPLE::SearchRecord(CString value1,CString value2){
//搜尋stopflag=value1,newflag=value2。結果為空時,BOOL CSMST_BSAMPLE::SearchRecord返回結果為0
	m_strFilter = L"stopflag= '" + value1 + L"' and newflag = '" + value2 +L"'";
	Requery();
	m_strFilter=L"";
	return !IsEOF();
}

成員m_strSort用於指定排序.m_strSort實際上包含了ORDERBY子句的內容,但它不含ORDER BY關鍵字.m_strSort的一個例子為

m_pSet->m_strSort=“CourseIDDESC”; //按CourseID的降序排列記錄
m_pSet->Open();

事實上,Open函式在構造SELECT語句時,會把m_strFilter和m_strSort的內容放入SELECT語句的WHERE和ORDERBY子句中.如果在Open的lpszSQL引數中已包括了WHERE和ORDERBY子句,那麼m_strFilter和m_strSort必需為空。
呼叫無引數成員函式Close可以關閉記錄集.在呼叫了Close函式後,程式可以再次呼叫Open建立新的記錄集.CRecordset的解構函式會呼叫Close函式,所以當刪除CRecordset物件時記錄集也隨之關閉。