連線資料來源(轉)

heying1229發表於2007-07-28
連線資料來源:

  本教程中,我們將學習使用ODBC APIs的細節.

因為我們的程式並不與ODBC驅動程式直接通訊,而是透過ODBC管理器來定義一系列APIs供你的程式呼叫以完成工作,所以我們需要包含odbc32.inc和odbc32.lib檔案,當然還有windows.inc。

連線資料來源需要以下幾步:

分配一個環境控制程式碼(environment handle). 在進行每個ODBC任務(session)時僅需這樣做一次.一旦獲得了控制程式碼,我們就可修改環境屬性來適合我們的需要。你可以把這想象為在DB工作中建立一個workspace.
確認將使用的ODBC的版本. 你可在ODBC 2.x版和3.x版間選擇.他們在很多方面存在不同,因此本步驟是必須的以使得ODBC管理器它將用何種語法與使用者程式通訊,及如何解釋使用者程式的命令.
分配一個連線控制程式碼.這個步驟可看作建立一個空連線.我們還沒有指定使用那一個驅動程式,連線那一個資料庫.這些資訊將在稍後來寫入.
建立一個連線.可透過呼叫ODBC函式來建立連線.
當連線完成時,必須透過以下步驟來關閉和銷燬它:

斷開與資料來源的連線.
釋放連線控制程式碼.
釋放環境控制程式碼 (如果不再需要在這個環境中作更多連線)
分配一個控制程式碼
在ODBC 3.x版本以前,我們需要呼叫很多獨立的函式來分配環境、連線和語句控制程式碼(SQLAllocEnv, SQLAllocConnect, SQLAllocStmt).而在ODBC 3.x中, 這些函式被SQLAllocHandle所代替,語法如下:

SQLRETURN SQLAllocHandle( SQLSMALLINT HandleType,
SQLHANDLE InputHandle,
SQLHANDLE * OutputHandlePtr
);
看上去挺麻煩,簡化一下看看:

SQLAllocHandle proto HandleType:DWORD, InputHandle:DWORD, OutputHandlePtr:DWORD
SQLRETURN 被定義為SQLSMALLINT型別.而 SQLSMALLINT被定義為短整型,例如一個字(16 bits). 所以該函式的返回值在ax中,而不是 eax. 這是很重要的.但是Win32下函式的引數是透過32位堆疊來傳送的.即使這個引數只是一個字長(16位),它也應被擴充套件為32位.這就是為什麼HandleType被說明為雙字(dword)而不是字(word).看一下匯入庫 odbc32.lib,SQLAllocHandle的入口是_SQLAllocHandle@12. 就是說這個函式的引數的組合長度為12位元組(3 dwords).然而,這不是說C函式的原型不對. SQLAllocHandle會只用HandleType的底位字並忽略高位字.因此C函式原型是功能上(functionally)正確而我們的彙編函式原型反映了實際.

結束了SQL型別的討論,我們來看一看函式的引數和返回值。.

HandleType 是一個常數,定義了希望分配的控制程式碼型別.可能值如下:
SQL_HANDLE_ENV 環境控制程式碼(Environment handle)
SQL_HANDLE_DBC 連線控制程式碼(Connection handle)
SQL_HANDLE_STMT 語句控制程式碼(Statement handle)
SQL_HANDLE_DESC 描述符控制程式碼(Descriptor handle)

描述符是一個資料集合描述了一個SQL語句的引數或一個結果集的列數, 視應用程式或驅動程式而定。

InputHandle 是指向父"文字"的控制程式碼.就是說,如果你想分配一個連線控制程式碼, 需要透過一個環境控制程式碼因為連線將在那個環境的文字中建立.如果你想分配一個環境控制程式碼,這個引數必須為SQL_HANDLE_NULL (注意SQL_HANDLE_NULL在windows.inc版本1.18及其以前版本中被不正確的定義為0L.你需要刪除掉"L"否則程式不會被編譯透過.這是我的錯,因為我負責修訂windows.inc中的 SQL/ODBC部分.) 因為環境沒有父文字.對於語句和描述符控制程式碼,我們需要將連線控制程式碼作為這個引數。
OutputHandlePtr 如果呼叫成功,將指向一個雙字,其中包含了被分配的控制程式碼.
SQLAllocHandle 可能的返回值如下:

SQL_SUCCESS 函式成功完成.
SQL_SUCCESS_WITH_INFO 函式成功完成,但帶回非致命錯誤或警告.
SQL_ERROR 函式呼叫失敗.
SQL_INVALID_HANDLE 傳送給函式的控制程式碼非法.

無論函式的呼叫成功還是失敗,我們都可透過呼叫SQLGetDiagRec或SQLGetDiagField函式來獲得更多的資訊.它們與Win32 API中的GetLastError很相似.


例子:

.data?
hEnv dd ?

.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

選擇ODBC的版本
分配完環境控制程式碼後,我們需要設定一個環境屬性SQL_ATTR_ODBC_VERSION以適當的值.設定環境屬性可透過呼叫函式SQLSetEnvAttr.你也許猜到了,還有類似的函式如 SQLSetConnectAttr和SQLSetStmtAttr. SQLSetEnvAttr原型如下:

SQLSetEnvAttr proto EnvironmentHandle:DWORD, Attribute:DWORD, ValuePtr:DWORD,
StringLength:DWORD
EnvironmentHandle. 與字面意思一樣, 它包含了要設定屬性的環境控制程式碼.
Attribute. 這是一個常數,表示使用者需要設定的屬性.對我們而言,是SQL_ATTR_ODBC_VERSION.可以從MSDN中檢視全部列表.
ValuePtr. 這個引數的意義由希望設定的屬性值決定.如果屬性值是32位的, 這個引數將被認為是想要設定的屬性值.如果屬性值是一個字串或二進位制緩衝區,它就被解釋為指向字串或緩衝區的指標.如果我們指定了要設定的屬性為SQL_ATTR_ODBC_VERSION, 這個引數我們可以填入SQL_OV_ODBC3和SQL_OV_ODBC2這兩個可能值,分別對應ODBC 3.x和2.x.
StringLength. 由ValuePtr指向的值的長度. 如果這個值是字串或二進位制緩衝區,這個引數一定是合法的. 如果想設定的屬性是一個雙字,這個引數被忽略.因為 SQL_ATTR_ODBC_VERSION屬性包含一個雙字的值,我們可以只給它賦為NULL.
這個函式的返回值與SQLAllocHandle相同.

例子:

.data?
hEnv dd ?

.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLSetEnvAttr, hEnv, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, NULL
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

分配連線控制程式碼
這一步與分配環境控制程式碼相似,我們可以透過呼叫SQLAllocHandle函式並賦以不同的引數值來完成.

例子:

.data?
hEnv dd ?
hConn dd ?

.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLSetEnvAttr, hEnv, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, NULL
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

建立一個連線
我們現在要透過特定的ODBC驅動程式來連線資料來源.透過這三個ODBC函式來達成這個目標.它們為我們提供了好幾層"選擇".

SQLConnect Core 這是最簡單的函式。它只需要資料來源名(DSN,Data source name)和可選的使用者名稱和密碼.它不提供任何GUI選項例如向使用者顯示一個對話方塊來提供更多資訊。如果你已經有了需要使用的資料庫的DSN就可以使用這個函式.
SQLDriverConnect Core 這個函式提供了較SQLConnect更多的選擇.我們可以連線一個沒有在系統資訊內定義的資料來源。如沒有DSN.另外,我們可以指定這個函式是否需要顯示一個對話方塊來為使用者提供更多資訊.例如,如果使用者遺漏了資料庫的名字,它會指導ODBC驅動程式顯示一個對話方塊,讓使用者來選擇想連線的資料庫.
SQLBrowseConnect Level 1 這個函式允許在執行時(RunTime)列舉資料來源.比SQLDriverConnect更加靈活。因為可以多次順序呼叫SQLBrowseConnect,而每次提供給使用者更多的專用資訊直到最後獲得需要的連線控制程式碼.

我將先檢查SQLConnect函式.要使用 SQLConnect,你應先知道什麼是DSN. DSN是資料來源名(Data Source Name)的縮寫,是一個唯一標識某資料來源的字串。一個DSN標識了一個包含了如何連線某一特定的資料來源的資訊的資料結構.這個資訊包括要使用何種ODBC驅動程式及要連線哪個資料庫.我們可以透過控制皮膚中的32位ODBC資料來源來建立、修改及刪除DSN.

SQLConnect的語法如下:

SQLConnect proto ConnectionHandle:DWORD pDSN:DWORD, DSNLength:DWORD, pUserName:DWORD, NameLength:DWORD, pPassword:DWORD, PasswordLength:DWORD
ConnectionHandle. 要使用的連線控制程式碼.
pDSN. 指向DSN的指標.
DSNLength. DSN的長度
pUserName. 指向使用者名稱的指標
NameLength. 使用者名稱的長度
pPassword. 指向該使用者名稱所使用密碼的指標
PasswordLength. 密碼的長度
在最小情況下, SQLConnect 需要連線控制程式碼,DSN和DSN的長度。如果資料來源不需要的話,使用者名稱和密碼就不是必須的.函式的返回值與SQLAllocHandle的返回值相同.

假設我們的系統中有一個叫做"Sales" 的DSN並且我們想連線這個資料來源.我們可以這樣做:

.data
DSN db "Sales",0

.code
......
invoke SQLConnect, hConn, addr DSN, sizeof DSN,0,0,0,0

SQLConnect 的缺點是:在連線一個資料來源之前,我們必須建立它的DSN. SQLDriverConnect 提供了更大的靈活性.它的語法如下:

SQLDriverConnect proto ConnectionHandle:DWORD, hWnd:DWORD, pInConnectString:DWORD, InStringLength:DWORD, pOutConnectString:DWORD, OutBufferSize:DWORD, pOutConnectStringLength:DWORD,
DriverCompletion:DWORD
ConnectionHandle連線控制程式碼
hWnd 應用程式視窗控制程式碼.如果這個引數被置為NULL,驅動程式將不會為使用者顯示一個對話方塊來顯示更多資訊(如果有的話).
pInConnectString 指向連線字串的指標. 這是一個ASCIIZ字串,格式由要連線的具體ODBC驅動程式描述.它描述了驅動程式名、資料來源及其他附加屬性.連線字串的具體描述請參見MSDN,這裡不再細述.
InStringLength 連線字串的長度.
pOutConnectString 指向將要被填入完整連線字串的緩衝區的指標.這個緩衝區將至少有1,024位元組長.這聽上去使人困惑。事實上,我們提供的連線字串會不完整,這時,ODBC驅動程式會提示使用者更多資訊.接下來ODBC驅動程式會根據所有可能的資訊建立一個完整的連線字串並將其放入緩衝區。即使我們提供的連線字串已經可以工作了,這個緩衝區也會填入更多的屬性值.這個引數的目的是我們可以儲存完整連線字串來為接下來的連線做準備。
OutBufferSize 由pOutConnectString指向的緩衝區的長度.
pOutConnectStringLength 指向一個雙字的指標,用來接收由ODBC驅動程式返回的完整連線字串的長度。
DriverCompletion 一個標誌用來指示ODBC管理器/驅動程式是否將提示使用者更多資訊.但是,這個標誌取決於是否在呼叫本函式時傳送了hWnd 引數一個視窗控制程式碼。如果沒有,即使該標誌被設定,ODBC管理器/驅動程式也不會提示使用者.可能值如下:

SQL_DRIVER_PROMPT ODBC驅動程式提示使用者輸入資訊。驅動程式將利用這些資訊來建立連線字串.
SQL_DRIVER_COMPLETE
SQL_DRIVER_COMPLETE_REQUIRED 僅當使用者提供的連線字串不完全時, ODBC驅動程式才會提示使用者.
SQL_DRIVER_NOPROMPT ODBC驅動程式將不會提示使用者.

例子:

.data
strConnect db "DBQ=c:data est.mdb;DRIVER={Microsoft Access Driver (*.mdb)};",0

.data?
buffer db 1024 dup(?)
OutStringLength dd ?

.code
.....
invoke SQLDriverConnect, hConn, hWnd, addr strConnect, sizeof strConnect, addr buffer, sizeof buffer, addr OutBufferLength, SQL_DRIVER_COMPLETE

斷開與資料來源的連線
在連線順利完成後,我們就可以對資料來源進行查詢及其他操作.這些將在下一節討論.現在假設我們已完成了對資料來源的操作,就可以透過呼叫SQLDisconnect來斷開與它的連線. 這個函式非常簡單(就象那悲傷而冷酷的現實:毀滅總比創造容易的多).它只需要一個引數:連線控制程式碼。

invoke SQLDisconnect, hConn

釋放連線與環境控制程式碼
在順利地斷開連線後,我們現在可以呼叫SQLFreeHandle函式來銷燬連線控制程式碼和環境控制程式碼. 這是由ODBC 3.x提供的新函式.它替代了SQLFreeConnect, SQLFreeEnv及SQLFreeStmt函式. SQLFreeHandle語法如下:

SQLFreeHandle proto HandleType:DWORD, Handle:DWORD
HandleType 標識要銷燬控制程式碼的類別的常數.可能值與 SQLAllocHandle中相同
Handle要銷燬的控制程式碼.
For example:

invoke SQLFreeHandle, SQL_HANDLE_DBC, hConn
invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928794/,如需轉載,請註明出處,否則將追究法律責任。

相關文章