`
xwdengjie
  • 浏览: 24639 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

动态配置odbc数据源

阅读更多
ODBC数据源里配置数据库,通过这种方式,应用程序的编写变的简单。只需要在应用程序里面指定已经配置好的数据源就可以连接,访问数据库。但是,这种方式也有一定的局限性,需要手工的在ODBC数据源里面配置。 需要教会程序的使用者如何去配置,而且,如果一不小心更改了ODBC数据源的配置(也许是无意的)。就会造成连接数据库失败。这时候,程序的使用人员也许会一筹莫展,束手无策。   自然的,读者就会提出这样一个问题,能不能不通过ODBC数据源的配置,而在程序里面,根据程序安装的环境,自动的配置数据库连接。答案是肯定的,下面我们就介绍一种在程序中通过修改Window注册表的办法来动态的配置ODBC数据源的方法。   其实现的基本思想是这样的:先把开发环境下的注册表中的ODBC数据源信息导出到一个文件中,然后将导出的内容作为应用程序中的字符串常量进行保存。在程序运行的时候,检查ODBC数据源的注册情况,如果发现注册不正确,就根据环境的信息和字符串常量动态的确定注册表的内容,写如一个临时的注册表文件中。用批处理文件将该临时文件中的ODBC数据源信息导入到系统注册表,从而实现了ODBC数据源的动态注册。   操作步骤   1.运行注册表编辑器程序(Regedit.exe)。   2.从注册表项\HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources下导出数据源名称信息到Reg1.reg文件中。这个表项下面存放的是用户定义的数据源,如果需要系统数据源信息,则可导出HKEY_Local_Machine\Software\ODBC.INI\ODBC Data Sources到注册文件中。   3.导出要注册的数据源名称的具体连接参数信息到db2.reg中。在此,以导出名称为“PostMdb”的数据为例,具体路径: \HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\PostMdb。   4.用文本编辑器如(NotePad.exe)打开上述db1.reg文件,保留数据源名称为PostMdb的行;并将db2.reg文件内容与当前db1.reg内容合并。假设修改后“PostMdb”数据源注册信息如下:   REGEDIT4   [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources]   ″PostMdb″=″Microsoft Access Driver (*.mdb)″   [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\PostMdb]   ″Driver″=″C:\\WINDOWS\\SYSTEM\\ODBCJT32.DLL″   ″DBQ″=″c:\\My Documents\\db1.mdb? r>   ″Description″=″Post Card Mis Database″   ″DriverId″=dword:00000019   ″FIL″=″MS Access;″   ″SafeTransactions″=dword:00000000   ″UID″=″″   [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\PostMdb\Engines]   [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\PostMdb\Engines\Jet]   ″ImplicitCommitSync″=″″   ″MaxBufferSize″=dword:00000800   ″PageTimeout″=dword:00000005   ″Threads″=dword:00000003   ″UserCommitSync″=″Yes″5.动态注册ODBC数据源的实现从上述注册信息可以看出,对于特定的数据源来说,实际上要动态确定的只是“Driver”和“DBQ”两项内容。将“Driver”=“C:\\WINDOWS\\SYSTEM\\ODBCJT32.DLL”修改为“Driver”=“%s\\ODBCJT32.DLL”,将“DBQ”=“c:\\My Documents\\db1.mdb”修改为“DBQ”=“%s\\db1.mdb”。复制修改后的注册信息到程序单元中存储为一字符串常量,命名为OdbcStr。以下以Delphi为例说明实现方法。   为便于说明,假设主窗体名称为Form1,通过一命令钮Button1注册ODBC数据源。具体根据读者需要自行设定。   procedure TForm1.Button1Click(Sender: TObject);varI : Integer;   J : double;   RegF: TextFile;   SysDir: PChar;   AppPath, Params, Path, DbPath: string;begin   try   //生成注册用的批处理文件    Params :=′Regedit/s tmp.reg′; //批处理文件内容AppPath := ExtractFilePath(Application.ExeName); //取得应用程序当前路径AssignFile(RegF, AppPath+′Reg.Bat′); //指定批处理文件路径和名称ReWrite(RegF); //创建和打开指定的文本文件WriteLn(RegF, Params); //将注册命令批处理内容写入文件CloseFile(RegF);//生成注册表文件GetMem(SysDir, 255);GetSystemDirectory(SysDir, 255); //取得Windows系统目录Path := String(SysDir);Path := InsertSplash(Path); //将类似C:\WINDOWS\SYSTEM变为C:\\WINDOWS\\SYSTEMDelete(AppPath, Length(AppPath), 1); //将字符串尾部′\′字符删除DbPath := InsertSplash(AppPath); //取得数据库存放路径Params := Format(OdbcStr, [Path, DbPath]);AssignFile(RegF, AppPath+′Tmp.Reg′);ReWrite(RegF);WriteLn(RegF, Params);CloseFile(RegF);//通过Api函数执行reg.bat, Uses中加入对ShellApi的引用If ShellExeCute(Application.Handle,′Open′,′Reg.bat′,′′, PChar(AppPath), SW_HIDE) $#@60;= 32    then    Showmessage(′导入注册表文件信息失败′);finallyFreeMem(SysDir);end;end;上述代码调用了一字符串处理函数InsertSplash,用于将路径字符串中所有的′\′处理为′\\′;这样做是必需的,否则,上述注册信息DRIVER和DBQ项无法正确注册。InsertSplash函数代码如下:   function InsertSplash(AStr: string): string; //需要在单元公有部分进行函数声明var   I : Integer;begin   For I := 1 to Length(AStr) do   case AStr[I] =′\′of   True : Result := Result+′\\′;   False: Result := Result+AStr[I];end;上述操作实现ODBC数据源的动态注册并没有通过Delphi特有的功能去完成,而只是通过文件读写功能,根据具体安装环境,生成ODBC数据源注册信息和批处理文件,以完成ODBC数据源的注册。这种实现方法不依赖于某种特定的开发工具,不需要通过手工进行ODBC数据源的配置,具有通用性强和操作简单的特点。而且,用上述同样的方法,读者也可编写能够注册其它类型数据源的程序,甚至,写成ODBC注册动态连接库,以利于程序复用。   不管是是控制面版里面配置ODBC数据源,还是象上面上的通过修改注册表在程序中动态的配置ODBC数据源,都没有离开数据源这个基本概念。在设置好了数据源之后,就可以在应用程序中连接数据源,然后对数据库中的数据进行数据的增加、删除和修改了。   对数据库中数据的访问,总的来说有两种方法,一种是通过编程环境提供的控件方法,一种就是通过ODBC API。有人也许会说还可以通过BDE的API,其实BDE的API和ODBC的API是同样的一个概念,BDE的API是Borland公司的,只是在他的编译环境下使用,当然,Borland的编译环境下比ODBC还快,但是因为那是他自带的驱动程序,如果数据库要升级的话,原来的BDE中的驱动程序就可能不能用了,所以,我们还是提倡使用ODBC的方法。   ODBC API函数中通过设置参数,直接和数据库打交道,这样的效率比较高,但是编程变的复杂,而且一不小心就会出错。我们不提倡直接使用ODBC API,而倾向于使用编程环境提供的控件方法来访问。但是,作为一种访问数据库访问的方法,我们在这里还是做一简单的介绍(这里以VB为例子)。(至于通过控件的方法,大家使用的比较多,这里就不多说了。)   ODBC API函数的声明方法与使用其它动态库函数一样,在VB中使用ODBC API函数之前,必须事先声明将要使用的函数、常量和数据结构。ODBC API函数驻留在ODBC运行动态库ODBC.DLL(16位)或ODBC32.DLL(32位)中,该动态库位于Windows子目录system中。通常做法是在VB项目中单独使用一个模块文件,然后将ODBC API声明语句加入其中。   下面就是本文实例中使用的模块文件module1.bas的内容。 Declare Function SQLAllocEnv Lib "odbc32.dll" (phenv&) As Integer Declare Function SQLAllocConnect Lib "odbc32.dll" (ByVal henv&, phdbc&) As Integer Declare Function SQLAllocStmt Lib "odbc32.dll" (ByVal hdbc&, phstmt&) AsInteger Declare Function SQLConnect Lib "odbc32.dll" (ByVal hdbc&, ByVal szDSN$,ByVal cbDSN%, ByVal szUID$, ByVal cbUID%, ByVal szAuthStr$, ByVal cbAuthStr%) As Integer Declare Function SQLColAttributesString Lib "odbc32.dll" Alias "SQLColAttributes" (ByVal hstmt&, ByVal icol%, ByVal fDescType%, ByVal rgbDesc As String, ByVal cbDescMax%, pcbDesc%, pfDesc&) As Integer Declare Function SQLDisconnect Lib "odbc32.dll" (ByVal hdbc&) As Integer Declare Function SQLExecDirect Lib "odbc32.dll" (ByVal hstmt&, ByVal szSqlStr$, ByVal cbSqlStr&) As Integer Declare Function SQLFetch Lib "odbc32.dll" (ByVal hstmt&) As Integer Declare Function SQLFreeConnect Lib "odbc32.dll" (ByVal hdbc&) As Integer Declare Function SQLFreeEnv Lib "odbc32.dll" (ByVal henv&) As Integer Declare Function SQLFreeStmt Lib "odbc32.dll" (ByVal hstmt&, ByVal fOption%) As Integer Declare Function SQLGetData Lib "odbc32.dll" (ByVal hstmt&, ByVal icol%,ByVal fCType%, ByVal rgbValue As String, ByVal cbValueMax&, pcbValue&) As Integer Declare Function SQLNumResultCols Lib "odbc32.dll" (ByVal hstmt&, pccol%) As Integer Global Const SQL_C_CHAR As Long = 1 Global Const SQL_COLUMN_LABEL As Long = 18 Global Const SQL_DROP As Long = 1 Global Const SQL_ERROR As Long = -1 Global Const SQL_NO_DATA_FOUND As Long = 100 Global Const SQL_SUCCESS As Long = 0 (更多的ODBC API,可以在MSDN里面查到)另外,在VB子目录samples\remauto\db_odbc中有两个文本文件ODBC16.TXT和ODBC32.TXT,分别存有所有16位和32位ODBC API函数、常量和数据结构的声明语句,编程时可以从中拷贝所需的声明语句。    使用ODBC API编程方法分为如下一些步骤:   1、 初始化ODBC在这个过程中,应用程序将通过调用SQLAlloEnv函数初始化ODBC接口,获取ODBC环境句柄。ODBC环境句柄是其它所有ODBC资源句柄的父句柄,因此无论程序将建立多少个ODBC连接,这个过程只需执行一次即可。例如:Dim rc As Integer "ODBC函数的返回码Dim henv As Long "ODBC环境句柄rc = SQLAllocEnv(henv) "获取ODBC环境句柄2、 与ODBC数据源建立连接这个过程由下列两个步骤组成:a、调用SQLAllocConnect函数获取连接句柄。例如:Dim hdbc As Long "连接句柄rc = SQLAllocConnect(henv, hdbc) "获取连接句柄B、建立连接。这个步骤可以通过多种方法实现,最简单直观的方法是调用SQLConnect函数。例如:   Dim DSN As String, UID As String, PWD As StringDSN = "DataSourceName" "ODBC数据源名称UID = "UserID" "用户帐号PWD = "Password" "用户口令rc = SQLConnect(hdbc, DSN, Len(DSN), UID, Len(UID), PWD, Len(PWD)) "建立连接   3、存取数据用户对ODBC数据源的存取操作,都是通过SQL语句实现的。在这个过程中,应用程序将通过连接向ODBC数据库提交SQL语句,完成用户请求的操作,具体步骤如下:调用SQLAllocStmt函数获取语句句柄,例如Dim hstmt As Longrc = SQLAllocStmt(hdbc, hstmt)执行SQL语句。执行SQL语句的方法比较多,最简单明了的方法是调用SQLAllocStmt函数,例如:Dim SQLstmt As StringSQLstmt = "SELECT * FROM authors"rc = SQLExecDirect(hstmt, SQLstmt, Len(SQLstmt))   4、 检索结果集 如果SQL语句顺利提交并正确执行,那么就会产生一个结果集。检索结果集的方法很多,最简单、最直接的方法是调用SQLFetch和SQLGetData函数。SQLFetch函数的功能是将结果集的当前记录指针移至下一个记录,SQLGetData函数的功能是提取结果集中当前记录的某个字段值。通常可以采用一个循环提取结果集中所有记录的所有字段值,该循环重复执行SQLFetch和SQLGetData函数,直至SQLFetch函数返回SQL_NO_DATA_FOUND,这表示已经到达结果集的末尾。   Dim ColVal As String * 225ColVal = String(255, 0)Do Until SQLFetch(hstmt) = SQL_NO_DATA_FOUNDrc = SQLGetData(hstmt, i, SQL_C_CHAR, ColVal, Len(ColVal), SQL_NULL_DATA Loop   5、 结束应用程序 在应用程序完成数据库操作、退出运行之前,必须释放程序中使用的系统资源。这些系统资源包括:语句句柄、连接句柄和ODBC环境句柄。完成这个过程的步骤如下:调用SQLFreeStmt函数释放语句句柄及其相关的系统资源。例如:rc = SQLFreeStmt(hstmt, SQL_DROP) 调用SQLDisconnect函数关闭连接,例如:rc = SQLDisconnect(hdbc) 调用SQLFreeConnect函数释放连接句柄及其相关的系统资源,例如:rc = SQLFreeConnect(hdbc) 调用SQLFreeEnv函数释放环境句柄及其相关的系统资源,停止ODBC操作,例如: rc = SQLFreeEnv(henv)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics