我原來在萬千的新聞討論區(news://news.webking.com.cn/)Delphi版上閑逛那段時間,發現經常有人提出一些資料庫方面的技巧性問題,問題其實不難,但是要一個簡單的解決方案,可能也破費思量,特别在此簡單談談:
1. 如何動态設定ODBC源
很多時候程式員需要自動生成ODBC資料源,而不是指導客戶"打開控制台… … ",到底如何去做呢?相信很多人會選擇程式設計修改系統資料庫來實作這項功能,因為ODBC的詳細資訊全部存放在系統資料庫的下述鍵值内:
"HKEY_LOCAL_MACHINE\SOFTWARE\ODBC"
修改一下ODBC的配置,通過前後的系統資料庫比較,你可以發現一定的規律。在這裡我隻是想說,哥們,别這麼犯傻了(如果我讓你寫一個通用的ODBC源處理程式,你得累死),用這個Windows ODBC API函數吧,
function SQLConfigDataSource(hwndParent: Integer; fRequest: Integer;
lpszDriverString: String; lpszAttributes: String): Integer;
stdcall;external ''ODBCCP32.DLL'';
了解資料庫程式設計的朋友都知道,資料庫的通路方式不論DAO、ADO、ODBC或是BDE或是其它第三方的資料庫連接配接控件,歸根結底,都是一些個函數集,隻要你願意,你可以編寫出自己的資料庫通路方式用以替代。深入研究這些底層函數,很多時候會為你提供相當地便利。
SQLConfigDataSource這個函數MSDN有詳細的說明,我不想整段翻譯下來讓你扁我,我隻是結合流行的SQL Server談談如何有技巧的調用該函數。其它的資料庫大同小異。
SQLConfigDataSource(0, ODBC_ADD_SYS_DSN,''SQL Server'', ''DSN=Record_ODBC''+ chr(0) + ''Server=(local)''+ chr(0) + ''Database=master''+ chr(0) + ''Description=DragonPC SQLServer ODBC Source''+ chr(0)); |
這是我的Delphi程式中調用該函數的一個執行個體,第一個參數是父視窗句柄,設定為0則該函數不顯示任何對話框。第二個參數是操作類型,你需要定義如下的操作類型常量:
Const ODBC_ADD_DSN = 1; // Add a new user data source. ODBC_CONFIG_DSN = 2; // Configure (modify) an existing user data source. ODBC_REMOVE_DSN = 3; // Remove an existing user data source. ODBC_ADD_SYS_DSN = 4; // Add a new system data source. ODBC_CONFIG_SYS_DSN = 5; // Modify an existing system data source. ODBC_REMOVE_SYS_DSN = 6; // Remove an existing system data source. |
從名字我們知道,要添加ODBC源,我們需要調用的是ODBC_ADD_SYS_DSN 或是ODBC_ADD_DSN參數。第三個參數也沒有什麼好說的,我們添加的是SQL Server資料庫的ODBC源,是以填入''SQL Server''參數,如果需要建立Excel檔案的ODBC資料源,我們可以填入''Excel Files (*.xls)'',這些字元串參數相信各位同志在添加ODBC源時,已經多次見過。
關鍵的是第三個參數的設定,不同的資料庫類型所支援的關鍵字是不一樣的,這裡僅僅就SQL Server所支援的關鍵字作一個簡單說明:
DSN:你的ODBC資料源名稱。
Server:你的資料庫伺服器名稱,使用(local)指的是本地計算機安裝的資料庫。注:最新的SQL Server 2000支援一台計算機運作多個SQL Server服務,這個時候你需要指定SqlSever的InstanceName。
Address:指定SQL Server伺服器的網絡IP位址。
Database:指定預設資料庫名稱。
Language:指定預設語言。
Description:備注資訊。
詳細的參數和資訊可以查閱微軟網站的以下網址。
http://msdn.microsoft.com/library/psdk/dasdk/odch3kit.htm
http://msdn.microsoft.com/library/psdk/sql/od_odbc_c_99yd.htm
2. 如何動态設定BDE别名
這個問題其實是考察程式員對BDE的TSession元件的熟悉程度,一個資料庫程式的建立,即使你沒有顯式的添加TSession元件,系統中依然存在一個名字為Session的TSession對象,你可以在任何位置調用該對象的方法和屬性。TSession類的很多方法可以幫助我們的應用程式擷取系統BDE環境,下面介紹一個代碼片斷用以添加一個BDE别名:
var BDEList : TStringList ; ... begin BDEList := TStringList.Create () ; try Session.GetAliasNames(BDElist) ; // 擷取系統所有BDE别名清單 if BDEList.IndexOf(''DragonPC'')= -1 then begin // 如果沒有我們的BDE别名"DragonPC" BDEList.Clear ; BDEList.Add(''SERVER NAME='' + ''SQLServerName'')); // 資料庫伺服器名稱 BDEList.Add(''DATABASE NAME=master'') ; // 預設資料庫 BDEList.Add(''USER NAME=sa''); // 使用者名 Session.AddAlias(''DragonPC'', ''MSSQL'', BDEList) ; // 添加一個MSSQL類型的BDE别名 ShowMessage(''系統即将建立BDE别名!'') ; Session.SaveConfigFile() ; // 存儲BDE配置 end; finally BDEList.Free ; |
這麼簡單,使用者就可以随時建立、删除和修改BDE别名(有興趣的朋友可以檢視TSession元件的源代碼,看看調用了哪些BDE函數)。另外像DeleteAlias,ModifyAlias,GetDatabaseNames,GetDriverNames,GetStoredProcNames,GetTableNames,GetPassword等等TSession類的方法,使用起來非常簡單,通過Delphi的随機幫助,讀者可以試着自己調用一下看看。通過對Session的靈活應用,再配合我下面将要提到的撲捉SQL異常的技巧,你完全可以寫一個媲美SQL Explorer的通用資料庫查詢工具。
ExecSQLMode = 0 ; OpenSQLMode = 1 ; ResultRight = ''SQL query result is right'' ; function RunSql(RunQuery: TQuery; Sqls: TStringList; var ErrorMsg: string; Mode: integer) : integer ; ErrorMsg := ResultRight ; Result := 0 ; RunQuery.DatabaseName := ''RecordDB'' ; RunQuery.SQL.Clear() ; RunQuery.SQL.AddStrings(Sqls) ; if Mode = ExecSQLMode then RunQuery.ExecSQL() else RunQuery.Open() ; except on e:exception do ErrorMsg := e.Message + #13 + #10 +''--- 錯誤是俺發現的 ---'' ; |
朋友看明白了吧,我的函數很簡單,将SQL語句代碼段作為參數傳遞給TQuery元件,通過設定查詢方式(ExecSQLMode、OpenSQLMode)來處理有結果集傳回的資料查詢語句(select)或是沒有結果集傳回的資料操作語言(update、delete、insert、create等)。而異常的撲捉呢,我們撲捉所有異常的老祖宗Exception,因為Delphi的所有異常都是從Exception繼承下來的,這樣一個簡單的SQL語句運作和異常處理函數就完成了,一旦傳回的ErrorMsg的值不是ResultRight,ErrorMsg就會傳回異常的資訊,程式員就可以加以判斷以處理不同的情況。