串連資料來源
來源:互聯網
上載者:User
資料|資料來源 串連資料來源
本教程中,我們將學習使用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函數來達成這個目標.它們為我們提供了好幾層"選擇".
SQLConnectCore這是最簡單的函數。它只需要資料來源名(DSN,Data source name)和可選的使用者名稱和密碼.它不提供任何GUI選項例如向使用者顯示一個對話方塊來提供更多資訊。如果你已經有了需要使用的資料庫的DSN就可以使用這個函數.SQLDriverConnectCore這個函數提供了較SQLConnect更多的選擇.我們可以串連一個沒有在系統資訊內定義的資料來源。如沒有DSN.另外,我們可以指定這個函數是否需要顯示一個對話方塊來為使用者提供更多資訊.例如,如果使用者遺漏了資料庫的名字,它會指導ODBC驅動程式顯示一個對話方塊,讓使用者來選擇想串連的資料庫.SQLBrowseConnectLevel 1這個函數允許在運行時(RunTime)枚舉資料來源.比SQLDriverConnect更加靈活。因為可以多次順序調用SQLBrowseConnect,而每次提供給使用者更多的專用資訊直到最後獲得需要的串連控制代碼.
我將先檢查SQLConnect函數.要使用 SQLConnect,你應Crowdsourced Security Testing道什麼是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_PROMPTODBC驅動程式提示使用者輸入資訊。驅動程式將利用這些資訊來建立連接字串.SQL_DRIVER_COMPLETE
SQL_DRIVER_COMPLETE_REQUIRED 僅當使用者提供的連接字串不完全時, ODBC驅動程式才會提示使用者.SQL_DRIVER_NOPROMPTODBC驅動程式將不會提示使用者.
例子:
.data
strConnect db "DBQ=c:\data\test.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