• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長(zhǎng)修遠(yuǎn),我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評(píng)論 - 257, 引用 - 0
            數(shù)據(jù)加載中……

            Linux/Unix下ODBC的編程[轉(zhuǎn)載至IBM developerWorks 中國(guó) ]

            Linux/Unix下ODBC的編程

            1、使用unixODBC提供的ODBC API進(jìn)行編程:
            在進(jìn)行編程之前,我們來看一下ODBC API中的常用數(shù)據(jù)類型與我們?cè)贑語言中使用的數(shù)據(jù)類型的對(duì)應(yīng)關(guān)系:

            類型標(biāo)識(shí)符 ODBC數(shù)據(jù)類型 C數(shù)據(jù)類型
            SQL_C_CHAR SQLCHAR * unsigned char *
            SQL_C_SSHORT SQLSMALLINT short int
            SQL_C_USHORT SQLUSMALLINT unsigned short int
            SQL_C_SLONG SQLINTEGER long int
            SQL_C_FLOAT SQLREAL float
            SQL_C_DOUBLE SQLDOUBLE, SQLFLOAT double
            SQL_C_BINARY SQLCHAR * unsigned char *
            SQL_C_TYPE_DATE SQL_DATE_STRUCT struct tagDATE_STRUCT {SQLSMALLINT year; SQLUSMALLINT month; SQLUSMALLINT day; } DATE_STRUCT;
            SQL_C_TYPE_TIME SQL_TIME_STRUCT struct tagTIME_STRUCT {SQLUSMALLINT hour; SQLUSMALLINT minute; SQLUSMALLINT second; } TIME_STRUCT;

            我們這里使用的數(shù)據(jù)庫名稱為test(DSN),這個(gè)DSN使用的用戶名是root,密碼為空,表的名稱是web,字段情況如下:

            字段名 數(shù)據(jù)類型
            id integer
            name char(40)
            size integer

            第一:設(shè)定ODBC環(huán)境句柄并設(shè)置參數(shù)
            首先我們需要聲明一個(gè)ODBC環(huán)境句柄(SQLHENV),它可以用來獲得有關(guān)的ODBC環(huán)境信息,我們需要調(diào)用SQLAllocHandle ( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &V_OD_Env )來獲得這個(gè)句柄,V_OD_Env就是要分配的SQLHENV類型的環(huán)境句柄。分配好句柄之后,你給它需要設(shè)定所使用的ODBC版本,你可以調(diào)用SQLSetEnvAttr ( V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0 ),SQL_ATTR_ODBC_VERSION是存放你定義的ODBC版本號(hào)的變量,SQL_OV_ODBC3則說明你的程序使用的是ODBC 3.0。

            第二:設(shè)定連接句柄并設(shè)置超時(shí)參數(shù)
            我們需要聲明一個(gè)連接句柄(SQLHDBC),用來存放數(shù)據(jù)庫連接信息的,調(diào)用SQLAllocHandle ( SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc )獲得連接句柄,V_OD_hdbc就是要分配的SQLHDBC類型的連接句柄。分配好之后,我們可以調(diào)用SQLSetConnectAttr ( V_OD_hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0 )來設(shè)定連接超時(shí)參數(shù)。

            第三:連接數(shù)據(jù)庫
            調(diào)用SQLConnect ( V_OD_hdbc, (SQLCHAR*) "Test", SQL_NTS, (SQLCHAR*) "root", SQL_NTS, (SQLCHAR*) "", SQL_NTS )連接我前面提到的數(shù)據(jù)庫,需要設(shè)定三個(gè)參數(shù),就是數(shù)據(jù)庫名稱、用戶名和密碼(因?yàn)槲业臄?shù)據(jù)庫密碼為空,所以這里的密碼也為空),后面的SQL_NTS的位置應(yīng)該寫入這些參數(shù)的長(zhǎng)度,如果寫的是SQL_NTS就是讓SQLConnect來決定參數(shù)的長(zhǎng)度。

            第四:分配SQL語句的句柄并進(jìn)行查詢:
            需要聲明一個(gè)SQL語句的句柄(SQLHSTMT),用來存放SQL語句信息的,調(diào)用SQLAllocHandle ( SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt )來獲得這個(gè)句柄,V_OD_hstmt就是我們要分配的SQLHSTMT類型的SQL語句句柄。

            我們的查詢語句是:

            												
            SELECT name, id FROM web ORDER BY id
            										

            執(zhí)行這條查詢語句之后,查詢結(jié)果可能有很多行,但每行只有兩列,分別對(duì)應(yīng)name和id,它們的數(shù)據(jù)類型為integer和char*,在ODBC中的數(shù)據(jù)類型標(biāo)識(shí)符為SQL_C_ULONG和SQL_C_CHAR。我們需要先聲明這樣的兩個(gè)變量來存貯查詢結(jié)果:

            												
            SQLINTEGER		V_OD_id;
            char		V_OD_buffer[200];
            
            										

            然后我們需要使用SQLBindCol函數(shù)把查詢結(jié)果和我們定義的變量進(jìn)行綁定:

            												
            SQLBindCol(V_OD_hstmt,1,SQL_C_CHAR, &V_OD_buffer,150,&V_OD_err);
            SQLBindCol(V_OD_hstmt,2,SQL_C_ULONG,&V_OD_id,150,&V_OD_err);
            
            										

            這里的V_OD_err是用來存放錯(cuò)誤信息編號(hào)的變量,類型也是SQLINTEGER。
            接下來,我們調(diào)用SQLExecDirect來進(jìn)行查詢:

            												
            SQLExecDirect ( V_OD_hstmt, "SELECT dtname,iduser FROM web order by iduser", SQL_NTS );
            										

            我們可以用SQLNumResultCols ( V_OD_hstmt, &V_OD_colanz )來獲得結(jié)果的列數(shù),也可以用SQLRowCount( V_OD_hstmt, &V_OD_rowanz )來獲得結(jié)果的條數(shù),V_OD_colanz和V_OD_rowanz分別存儲(chǔ)相應(yīng)的結(jié)果,類型分別為SQLSMALLINT和SQLINTEGER。
            在讀取結(jié)果之前,我們需要調(diào)用SQLFetch ( V_OD_hstmt )語句,這個(gè)語句可以用來獲得第一條結(jié)果也可以用來都下一條,有點(diǎn)像next的感覺。然后我們就可以在V_OD_id和V_OD_buffer里面獲得每條記錄的結(jié)果了。

            第五:關(guān)于關(guān)閉連接和釋放句柄
            關(guān)閉數(shù)據(jù)庫的連接,調(diào)用SQLDisconnect ( V_OD_hdbc )就可以了,但在關(guān)閉數(shù)據(jù)庫之前需要先釋放SQL語句的句柄,而且在關(guān)閉數(shù)據(jù)庫之后應(yīng)該釋放連接句柄和ODBC環(huán)境句柄,語句如下(按正常的順序):

            												
            SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
            SQLDisconnect(V_OD_hdbc);
            SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);
            SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
            
            										

            第六:關(guān)于上述情況中的錯(cuò)誤信息處理
            我們需要定義兩個(gè)變量:

            												
            long	V_OD_erg;
            SQLINTEGER	V_OD_err;
            										

            SQLAllocHandle、 SQLSetEnvAttr、SQLSetConnectAttr、SQLConnect、SQLExecDirect、 SQLNumResultCols和SQLRowCount的調(diào)用結(jié)果都可以用V_OD_erg來存儲(chǔ),V_OD_err可以獲得SQLBindCol中的錯(cuò)誤信息。

            第七:獲得本機(jī)的DSN信息
            我們可以在聲明SQLHENV句柄之后,使用SQLDataSources函數(shù)來獲得本機(jī)的DSN信息。程序如下:

            												
            void OD_ListDSN(void)
            {
            char       l_dsn[100],l_desc[100];
            short int  l_len1,l_len2,l_next;
            
            l_next=SQL_FETCH_FIRST;
            while( SQLDataSources(V_OD_Env,l_next,l_dsn, sizeof(l_dsn),
            &l_len1, l_desc, sizeof(l_desc), &l_len2) == SQL_SUCCESS)
            {
            printf("Server=(%s) Beschreibung=(%s)\n",l_dsn,l_desc);
            l_next=SQL_FETCH_NEXT;
            }
            }
            
            										

            l_next變量是用來指定我們所要獲得的DSN的類別:

            SQL_FETCH_FIRST 設(shè)定SQLDataSources()函數(shù)找到第一個(gè)可用的數(shù)據(jù)源(可以是User DSN,也可以是Systerm DSN)
            SQL_FETCH_FIRST_USER 設(shè)定SQLDataSources()函數(shù)找到第一個(gè)User DSN
            SQL_FETCH_FIRST_SYSTEM 設(shè)定SQLDataSources()函數(shù)找到第一個(gè)System DSN
            SQL_FETCH_NEXT 找到下一個(gè)數(shù)據(jù)源,至于數(shù)據(jù)源類型則要根據(jù)前面的定義

            到這里,我們?cè)赨nix的C語言下面進(jìn)行ODBC編程已經(jīng)講完,上述ODBC API需要引用以下幾個(gè)頭文件(這些文件已經(jīng)安裝到/usr/include下了):

            												
            #include <sql.h>
            #include <sqlext.h>
            #include <sqltypes.h>
            										

            另外如果大家使用GTK進(jìn)行編程,由于到目前為止GTK還沒有加入專門處理數(shù)據(jù)庫的部件,所以大家可以在GTK中調(diào)用上述的ODBC API即可。

            這里附上例程供大家參考學(xué)習(xí):

            												
            /* odbc.c
                testing unixODBC
            */
            #include <stdlib.h>
            #include <stdio.h>
            #include <odbc/sql.h>
            #include <odbc/sqlext.h>
            #include <odbc/sqltypes.h>
            
            SQLHENV			 V_OD_Env;			// Handle ODBC environment
            long			 V_OD_erg;			// result of functions
            SQLHDBC			 V_OD_hdbc;			// Handle connection
            
            char			 V_OD_stat[10];		// Status SQL
            SQLINTEGER		 V_OD_err,V_OD_rowanz,V_OD_id;
            SQLSMALLINT		 V_OD_mlen,V_OD_colanz;
            char             V_OD_msg[200],V_OD_buffer[200];
            
            
            int main(int argc,char *argv[])
            {
            	// 1. allocate Environment handle and register version 
            	V_OD_erg=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env);
            	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
            	{
            		printf("Error AllocHandle\n");
            		exit(0);
            	}
            	V_OD_erg=SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); 
            	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
            	{
            		printf("Error SetEnv\n");
            		SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
            		exit(0);
            	}
            	// 2. allocate connection handle, set timeout
            	V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); 
            	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
            	{
            		printf("Error AllocHDB %d\n",V_OD_erg);
            		SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
            		exit(0);
            	}
            	SQLSetConnectAttr(V_OD_hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);
            	// 3. Connect to the datasource "web" 
            	V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "Test", SQL_NTS,
                                                 (SQLCHAR*) "root", SQL_NTS,
                                                 (SQLCHAR*) "", SQL_NTS);
            	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
            	{
            		printf("Error SQLConnect %d\n",V_OD_erg);
            		SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, 
            		              V_OD_stat, &V_OD_err,V_OD_msg,100,&V_OD_mlen);
            		printf("%s (%d)\n",V_OD_msg,V_OD_err);
            		SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
            		exit(0);
            	}
            	printf("Connected !\n");
            	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
            	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
            	{
            		printf("Fehler im AllocStatement %d\n",V_OD_erg);
            		SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, V_OD_stat,&V_OD_err,V_OD_msg,100,&V_OD_mlen);
            		printf("%s (%d)\n",V_OD_msg,V_OD_err);
            		SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
            		exit(0);
            	}
                SQLBindCol(V_OD_hstmt,1,SQL_C_CHAR, &V_OD_buffer,150,&V_OD_err);
                SQLBindCol(V_OD_hstmt,2,SQL_C_ULONG,&V_OD_id,150,&V_OD_err);
            	
                V_OD_erg=SQLExecDirect(V_OD_hstmt,"SELECT dtname,iduser FROM web order by iduser",SQL_NTS);   
                if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
                {
                   printf("Error in Select %d\n",V_OD_erg);
                   SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, V_OD_stat,&V_OD_err,V_OD_msg,100,&V_OD_mlen);
                   printf("%s (%d)\n",V_OD_msg,V_OD_err);
                   SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
                   SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);
                   SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
                   exit(0);
                }
                V_OD_erg=SQLNumResultCols(V_OD_hstmt,&V_OD_colanz);
                if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
                {
                    SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
                    SQLDisconnect(V_OD_hdbc);
                    SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);
                    SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
                    exit(0);
                }
                printf("Number of Columns %d\n",V_OD_colanz);
                V_OD_erg=SQLRowCount(V_OD_hstmt,&V_OD_rowanz);
                if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
                {
                  printf("Number of RowCount %d\n",V_OD_erg);
                  SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
                  SQLDisconnect(V_OD_hdbc);
                  SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);
                  SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
                  exit(0);
                }
                printf("Number of Rows %d\n",V_OD_rowanz);
                V_OD_erg=SQLFetch(V_OD_hstmt);  
                while(V_OD_erg != SQL_NO_DATA)
                {
                 printf("Result: %d %s\n",V_OD_id,V_OD_buffer);
                 V_OD_erg=SQLFetch(V_OD_hstmt);  
                }  ;
                SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
                SQLDisconnect(V_OD_hdbc);
                SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);
                SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);
                return(0);
            }
            
            										

            2.QT下進(jìn)行ODBC編程
            QT 3.0提供了Data Table、Data Browser和Data View三個(gè)與數(shù)據(jù)庫相關(guān)的控件。你可以在QT的Project設(shè)置你要連接的數(shù)據(jù)庫,Driver一欄中選擇QODBC3即可,其它選項(xiàng)你一看就明白了。上述的三個(gè)數(shù)據(jù)庫控件的使用方法可以參見QT中相應(yīng)文檔,也很好使用的。







            參考資料

            1. 微軟的ODBC主頁: http://www.microsoft.com/data/odbc/
            2. UnixODBC的主頁: http://www.unixodbc.org
            3. FreeODBC的主頁: http://www.jepstone.net/FreeODBC/
            4. EasySoft的主頁: http://www.easysoft.com
            5. TrollTech的QT 3.0文檔主頁: http://doc.trolltech.com/3.0/

            posted on 2006-07-28 08:13 Khan 閱讀(1320) 評(píng)論(0)  編輯 收藏 引用 所屬分類: GCC/G++跨平臺(tái)開發(fā)

            久久99久久99小草精品免视看| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 久久热这里只有精品在线观看| 成人综合久久精品色婷婷 | 亚洲精品乱码久久久久久久久久久久 | 狠狠色狠狠色综合久久| 亚洲欧洲日产国码无码久久99| 69国产成人综合久久精品| 久久久精品视频免费观看| 色妞色综合久久夜夜| 精品久久一区二区| 久久频这里精品99香蕉久| 国产精品久久久久影院嫩草 | 久久91精品国产91久久麻豆| 欧美伊人久久大香线蕉综合69 | 亚洲精品无码久久久久久| 国产精品日韩深夜福利久久| 亚洲愉拍99热成人精品热久久| 精品视频久久久久| 久久精品国产一区| 久久亚洲国产成人精品性色| 欧美国产精品久久高清| 99久久成人18免费网站| 99久久免费国产精精品| 亚洲精品国产字幕久久不卡| 久久精品国产99国产精品| 久久久久中文字幕| 国产精品久久久福利| 久久丫精品国产亚洲av不卡| 久久亚洲AV成人无码软件| 色综合久久88色综合天天 | 国产AV影片久久久久久| 久久久精品午夜免费不卡| 99久久精品影院老鸭窝| 久久国产成人精品麻豆| 97久久香蕉国产线看观看| 久久久一本精品99久久精品66| 亚洲国产成人久久一区WWW| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 无遮挡粉嫩小泬久久久久久久| 久久人妻少妇嫩草AV蜜桃|