mysql odbc c语言_C语言ODBC操作MySQL数据库(示例代码)
數(shù)據(jù)庫及其編程API來源于不同的背景,開發(fā)人員可以從眾多的數(shù)據(jù)庫中選擇一種,每種數(shù)據(jù)庫都有自己的一套編程API,這就為數(shù)據(jù)庫編程造成了很大的局限性。SQL是標準化數(shù)據(jù)庫編程接口的一種嘗試,然而各種數(shù)據(jù)庫所支持的SQL又有所不同。
ODBC的設計目的是允許訪問多種數(shù)據(jù)庫,ODBC為數(shù)據(jù)庫供應商提供了一致的ODBC驅動程序標準,遵循這個標準開發(fā)的數(shù)據(jù)庫驅動程序,都可以被開發(fā)人員通過ODBC
API透明地訪問,而不必關心實際的數(shù)據(jù)庫是什么。在這里,ODBC所做的,就是接收開發(fā)人員的數(shù)據(jù)庫操作指令,調用相應的ODBC驅動程序,向一個數(shù)據(jù)庫或者向多個數(shù)據(jù)庫發(fā)送數(shù)據(jù),并可接收來自數(shù)據(jù)庫的數(shù)據(jù)。
ODBC提供了訪問數(shù)據(jù)庫的標準,這使得開發(fā)人員將精力集中在應用程序以及用戶接口的開發(fā)上,而不必考慮與之相連的數(shù)據(jù)庫。為了進一步簡化開發(fā)工作,ODBC把API層實現(xiàn)為SQL的映射器。通常數(shù)據(jù)庫開發(fā)人員將標準的SQL語句發(fā)送給ODBC驅動程序,再由ODBC驅動程序將這個SQL語句映射成數(shù)據(jù)庫可以支持的SQL語句。
本章首先對ODBC API的概貌進行簡要介紹,然后講述利用ODBC API進行數(shù)據(jù)庫開發(fā)的技巧,最后將通過具體數(shù)據(jù)庫開發(fā)實例,詳細講述通過ODBC API開發(fā)數(shù)據(jù)庫應用程序的方法和過程。
1了解ODBC API
ODBC是一種使用SQL的程序設計接口。使用ODBC讓應用程序的編寫者避免了與數(shù)據(jù)源相聯(lián)的復雜性。這項技術目前已經得到了大多數(shù)DBMS廠商們的廣泛支持。ODBC是一種使用SQL 的程序設計接口。使用ODBC讓應用程序的編寫者避免了與數(shù)據(jù)源相聯(lián)的復雜性。這項技術目前已經得到了大多數(shù)DBMS廠商們的廣泛支持。
Microsoft Developer Studio為大多數(shù)標準的數(shù)據(jù)庫格式提供了32位ODBC驅動器。這些標準數(shù)據(jù)格式包括有:SQL Server,Access,Paradox,dBase,FoxPro,Excel,Oracle 以及Microsoft Text。如果用戶希望使用其他數(shù)據(jù)格式,用戶需要相應的ODBC驅動器及DBMS。
ODBC API是一個內容豐富的數(shù)據(jù)庫編程接口,包括60多個函數(shù)、SQL數(shù)據(jù)類型以及常量的聲明。ODBC API 是獨立于DBMS和操作系統(tǒng)的,而且它與編程語言無關。ODBC API 以X/Open和ISO/IEC中的CLI規(guī)范為基礎,ODBC 3.0完全實現(xiàn)了這兩種規(guī)范,并添加了基于視圖的數(shù)據(jù)庫應用程序開發(fā)人員所需要的共同特性,例如可滾動光標。ODBC API中的函數(shù)由特定DBMS驅動程序的開發(fā)人員實現(xiàn),應用程序用這些驅動程序調用函數(shù),以獨立于DBMS的方式訪問數(shù)據(jù)。
ODBC API涉及了數(shù)據(jù)源連接與管理、結果集檢索、數(shù)據(jù)庫管理、數(shù)據(jù)綁定、事務操作等內容,目前的最高版本是3.0。
通常使用ODBC API開發(fā)數(shù)據(jù)庫應用程序需要經過如下步驟:
·??????連接數(shù)據(jù)源。
·??????分配語句句柄。
·??????準備并執(zhí)行SQL語句。
·??????獲取結果集。
·??????提交事務。
·??????斷開數(shù)據(jù)源連接并釋放環(huán)境句柄。
下面對上述步驟做詳細的介紹。
步驟1:連接數(shù)據(jù)源
為了連接數(shù)據(jù)源,必須要建立一個數(shù)據(jù)源連接的環(huán)境句柄。通過調用SQLAllocEnv函數(shù)實現(xiàn)對環(huán)境句柄的分配,在ODBC 3.0里,這個函數(shù)已經被SQLAllocHandle取代,但是熟悉ODBC API的開發(fā)人員還是習慣用這個函數(shù)建立環(huán)境句柄,因為VC++開發(fā)平臺有一個映射服務,這個服務將程序代碼對函數(shù)SQLAllocEnv的調用轉向對函數(shù)SQLAllocHandle的調用。
這里有必要對“環(huán)境句柄”這個概念進行說明。句柄是指向一個特殊結構的指針,而環(huán)境指的是驅動程序管理器需要為該驅動程序存儲的有關系統(tǒng)和數(shù)據(jù)源的一般信息。由于這個時候還沒有建立同數(shù)據(jù)源的連接,驅動程序還并不知道該使用哪一個驅動程序來完成這個任務,所以這個任務只能由驅動程序管理器來完成,利用這個環(huán)境句柄保留信息直到被使用。
使用函數(shù)SQLAllocEnv創(chuàng)建環(huán)境句柄的語法如下:
HENV? henv;
RETCODE?rcode;
rcode = ::SQLAllocEnv(SQL_HANDLE_ENV, SQL_NULL,& henv);
if(rcode == SQL_SUCCESS)?? // 環(huán)境句柄創(chuàng)建成功
{
// 執(zhí)行其它操作
…………
}
完成了環(huán)境句柄的創(chuàng)建以后,還要建立一個連接句柄。連接句柄的創(chuàng)建函數(shù)是SQLAllocConnect,其調用語法如下:
HDBC?? hdbc;
retcode = ::SQLAllocConnect( m_henv, & hdbc);
if(rcode == SQL_SUCCESS)?? // 連接句柄創(chuàng)建成功
{
// 執(zhí)行其它操作
…………
}
完成了環(huán)境句柄和連接句柄的創(chuàng)建以后,就可以進行實際的數(shù)據(jù)源連接了。完成數(shù)據(jù)源連接的函數(shù)是SQLConnect,其調用語法如下:
m_retcode = :: SQLConnect( m_hdbc,
(PUCHAR)pszSourceName,SQL_NTS,
(PUCHAR)pszUserId,wLengthUID,
(PUCHAR)pszPassword,wLengthPSW );
if(rcode == SQL_SUCCESS)?? // 數(shù)據(jù)源連接成功
{
// 執(zhí)行其它操作
…………
}
到此,應用程序同數(shù)據(jù)源的連接已經完成。
有些時候,ODBC數(shù)據(jù)源并不是事先在用戶的計算機里安裝好了的,這時就需要應用程序能夠動態(tài)創(chuàng)建ODBC數(shù)據(jù)源。ODBC API提供了動態(tài)創(chuàng)建數(shù)據(jù)源的函數(shù)SQLConfigDataSource。該函數(shù)的語法如下:
BOOL SQLConfigDataSource(HWND? hwndParent,
WORD? fRequest,
LPCSTR? lpszDriver,
LPCSTR? lpszAttributes);
參數(shù)hwndParent用于指定父窗口句柄,在不需要顯示創(chuàng)建數(shù)據(jù)源對話框時,可以將該參數(shù)指定為NULL;參數(shù)fRequest用于指定函數(shù)的操作內容,函數(shù)SQLConfigDataSource能夠實現(xiàn)的操作內容由參數(shù)fRequest制定,參數(shù)fRequest取值如下:
ODBC_ADD_DSN:創(chuàng)建數(shù)據(jù)源;
ODBC_CONFIG_DSN:配置或者修改已經存在的數(shù)據(jù)源;
ODBC_REMOVE_DSN:刪除已經存在的數(shù)據(jù)源;
ODBC_ADD_SYS_DSN:創(chuàng)建系統(tǒng)數(shù)據(jù)源;
ODBC_CONFIG_SYS_DSN:配置或者修改已經存在的系統(tǒng)數(shù)據(jù)源;
ODBC_REMOVE_SYS_DSN:刪除已經存在的系統(tǒng)數(shù)據(jù)源;
ODBC_REMOVE_DEFAULT_DSN:刪除缺省的數(shù)據(jù)源。
參數(shù)lpszDriver用于指定ODBC數(shù)據(jù)源的驅動程序類別,例如,為了指定Access數(shù)據(jù)源,該參數(shù)應賦以字符串“MicrosoftAccess Driver (*.mdb)\0”。 參數(shù)lpszAttributes用于指定ODBC數(shù)據(jù)源屬性,例如:
“DSN=MYDB\0DBQ=D:\\Database\\Friends.mdb\0DEFAULTDIR=D:\\DATABASE\0\0”
該字符串指定數(shù)據(jù)源名稱(DSN)為MYDB,數(shù)據(jù)庫文件(DBQ)為D:\Database\Friends.mdb,缺省數(shù)據(jù)庫文件路徑(DEFAULTDIR)為D:\DATABASE。
通過調用如下代碼可以通過應用程序動態(tài)創(chuàng)建數(shù)據(jù)源MYDB:
BOOL CreateDSN()
{
char*szDesc;
intmlen;
szDesc=newchar[256];
sprintf(szDesc,"DSN=%s:DESCRIPTION=TOC support source: \
DBQ=%s:FIL=MicrosoftAccess: \
DEFAULTDIR=D:\\Database::","TestDB","D:\\Friends.mdb");
mlen= strlen(szDesc);
for(int i=0; i
if(szDesc[i] == ‘:‘)?????? ? szDesc[i] = ‘\0‘;
}
if (FALSE ==SQLConfigDataSource(NULL,ODBC_ADD_DSN,
"MicrosoftAccess Driver (*.mdb)\0",
(LPCSTR)szDesc))
returnFALSE; // 創(chuàng)建數(shù)據(jù)源失敗。
else
returnTRUE; // 創(chuàng)建數(shù)據(jù)源成功。
}
步驟2:分配語句句柄
通常將ODBC中的語句看作SQL語句。前面已經提到,ODBC同數(shù)據(jù)庫的SQL接口通信,驅動程序將ODBC的SQL映射到驅動程序的SQL。但是ODBC的SQL還攜帶了一些屬性信息,用于定義數(shù)據(jù)源連接的上下文,有些語句要求特殊的參數(shù)以便能夠執(zhí)行,因此,每個語句都有一個指向定義語句所有屬性結構的句柄。
語句句柄的分配同環(huán)境句柄的分配相似,通過函數(shù)SQLAllocStmt實現(xiàn),該函數(shù)的調用語法如下:
HSTMT ???hstmt;
RETCODE?rcode;
m_retcode = :: SQLAllocStmt(hdbc, ?&hstmt );
if(rcode == SQL_SUCCESS)?? // 連接句柄創(chuàng)建成功
{
// 執(zhí)行其它操作
…………
}
步驟3:準備并執(zhí)行SQL語句
對于不同的應用程序需求,要準備的SQL語句也一定不一樣。通常的SQL語句包括SELECT、INSERT、UPDATA、DELETE、DROP等。
準備和執(zhí)行一個SQL語句的方法有兩種,第一種是使用SQLExecDirect函數(shù),可以一次執(zhí)行一個SQL語句。很多請求都可以使用這個方法。調用SQLExecDirect函數(shù)的語法如下:
LPCSTR pszSQL;
strcpy(pszSQL, “SELECT * FROM EMPLOYEES”);
retcode = ::SQLExecDirect(hstmt, ?(UCHAR*)pszSQL, ?SQL_NTS );
if(rcode == SQL_SUCCESS)?? // SQL語句執(zhí)行成功
{
// 執(zhí)行其它操作
…………
}
但是有些請求需要多次執(zhí)行同一條語句,為此,ODBC提供了SQLPrepare函數(shù)和SQLExecute函數(shù)。調用的時候,只需要調用一次SQLPrepare函數(shù),然后調用若干次SQLExecute函數(shù)。實際上,函數(shù)SQLExecDirect將SQLPrepare和SQLExecute的功能集中到了一起,多次調用SQLExecDirect顯然比調用一次SQLPrepare再調用若干次SQLExecute效率高。調用SQLPrepare和SQLExecute函數(shù)的語法如下:
LPCSTR pszSQL;
strcpy(pszSQL, “SELECT * FROM EMPLOYEES”);
m_retcode = ::SQLPrepare( hstmt, ?(UCHAR*)pszSQL, ?SQL_NTS );
if(rcode == SQL_SUCCESS)?? // SQL語句準備成功
{
// 執(zhí)行其它操作
…………
}
retcode = :: SQLExecute (hstmt, ?(UCHAR*)pszSQL, ?SQL_NTS );
if(rcode == SQL_SUCCESS)?? // SQL語句執(zhí)行成功
{
// 執(zhí)行其它操作
…………
}
步驟4:獲取結果集
SQL語句執(zhí)行成功以后,應用程序必須準備接收數(shù)據(jù),應用程序需要把SQL語句執(zhí)行結果綁定到一個本地緩存變量里。但是SQL執(zhí)行語句執(zhí)行的結果并不是直接傳送給應用程序,而是在應用程序準備接收數(shù)據(jù)的時候通知驅動程序其已經準備好接收數(shù)據(jù),應用程序通過調用SQLFetch函數(shù)返回結果集的一行數(shù)據(jù)。
由于返回的數(shù)據(jù)是存放在列中的,因此應用程序必須調用SQLBindCol函數(shù)綁定這些列。通常接收結果集時需要依次進行以下操作:
·??????返回列的個數(shù),執(zhí)行SQLNumResultCols函數(shù)。
·??????給出列中數(shù)據(jù)的有關信息,例如列的名稱、數(shù)據(jù)類型和精度等,執(zhí)行SQLDescribeCol函數(shù)。
·??????把列綁定到應用程序的變量里,執(zhí)行SQLBindCol函數(shù)。
·??????獲取數(shù)據(jù),執(zhí)行SQLFetch函數(shù)。
·??????獲取長數(shù)據(jù),執(zhí)行SQLGetData函數(shù)。
應用程序首先調用SQLNumResultCols函數(shù),獲知每個記錄里有多少列,調用SQLDescribeCol函數(shù)取得每列的屬性,然后調用SQLBindCol函數(shù)將列數(shù)據(jù)綁定到指定的變量里,最后調用SQLFetch函數(shù)或者SQLGetData函數(shù)獲取數(shù)據(jù)。
對于其它的SQL語句,應用程序重復這個過程。這個過程代碼如下:
retcode = ::SQLNumResultCols( m_hstmt,&wColumnCount );
if( m_retcode != SQL_SUCCESS ) // 列舉結果集列的個數(shù)不成功
{
// 釋放操作
…………
return;
}
LPSTR?? pszName;
UWORD? ???????? URealLength;
SWORD? ???????? wColumnCount;
UWORD? ???????? wColumnIndex = 0;
SWORD? ???????? wColumnType;
UDWORD ??????? dwPrecision;
SWORD? ???????? wScale;
SWORD? ???????? wNullable;
m_retcode = ::SQLDescribeCol( m_hstmt,
wColumnIndex,?// 列的索引
pszName,??? // 列的名稱
256, ???// 存放列名稱的緩沖區(qū)大小
& nRealLength, ?// 實際得到列名稱的長度
&wColumnType,? // 列的數(shù)據(jù)類型
&dwPrecision,? // 精度
&wScale, // 小數(shù)點位數(shù)
&wNullable );? // 是否允許空值
if(retcode != SQL_SUCCESS ) // 執(zhí)行不成功
{
// 釋放操作
…………
return;
}
retcode = ::SQLBindCol( m_hstmt,
uCounter, // 列索引
wColumnType, // 列數(shù)據(jù)類型
FieldValue, // 綁定的變量
dwBufferSize, // 變量內存大小
&BytesInBuffer); // 存放將來返回數(shù)據(jù)的大小的變量
if(retcode != SQL_SUCCESS ) // 執(zhí)行不成功
{
// 釋放操作
…………
return;
}
::SQLFetch( m_hstmt );
// 此后可以從綁定的變量里讀取列的值。
…………
步驟5:提交事務
當所有的SQL語句都被執(zhí)行并接收了所有的數(shù)據(jù)以后,應用程序需要調用SQLEndTran提交或者回退事務。如果提交方式為手工(應用程序設置)方式,則需要應用程序執(zhí)行這個語句以提交或者回退事務,如果是自動方式,當SQL語句執(zhí)行后,該命令自動執(zhí)行。
事務是為了維護數(shù)據(jù)的一致性和完整性而設計的概念,事務要求:要么提交,將事務里包含的更新操作都提交到數(shù)據(jù)庫里;要么回退,數(shù)據(jù)庫恢復到事務前的狀態(tài),不會影響數(shù)據(jù)庫的一致性和完整性。通常情況下,檢索類SQL語句不涉及數(shù)據(jù)的更新,不會對數(shù)據(jù)的一致性和完整性產生影響,因此通常將檢索類SQL語句設置提交方式為自動,而將更新類SQL語句的提交方式設置為手工方式,便于通過代碼在事務處理中執(zhí)行事務的提交或者回退,以維護數(shù)據(jù)庫的一致性和完整性。在大型的商業(yè)應用中,這個設置非常有用。
調用SQLEndTran函數(shù)的語法如下:
:: SQLEndTran(SQL_HANDLE_DBC , hdbc,? SQL_COMMIT); // 提交事務
:: SQLEndTran(SQL_HANDLE_DBC , hdbc,? SQL_ROLLBACK); // 回退事務
步驟6:斷開數(shù)據(jù)源連接并釋放環(huán)境句柄
當應用程序使用完ODBC以后,需要使用SQLFreeHandle函數(shù)釋放所有語句句柄、連接句柄、環(huán)境句柄。這里需要注意操作的順序,應該是先釋放所有語句句柄,調用SQLDisconnect函數(shù)解除與數(shù)據(jù)源的連接,然后釋放所有連接句柄,最后釋放環(huán)境句柄,使應用程序同ODBC管理器的連接徹底解除。
一個封裝好的C語言odbc操作mysql的源碼分享給大家,這里需要注意的是我們的工程需要選擇使用多字節(jié)字符集
odbc.h
typedef char CHAR;
typedef signed int INT32;
typedefunsigned long U_LONG;
#defineSUCCESS1
#defineFAILURE0
#ifndef __ODBD_H__
#define __ODBC_H__
#ifdef __cplusplus
extern "C" {
#endif
#define CONLEN sizeof(CONSTR)-1
#define SQL_QUERY_BUFF_SIZE 512
#define CON_STR_LEN 255
#ifdef ODBC_PUBLIC
SQLHENV hEnv = 0;
SQLHDBC hDBC = 0;
SQLHSTMT hStmt = 0;
SQLRETURN retcode;
SQLCHAR szConStr[CON_STR_LEN];
SQLCHAR szStmt[SQL_QUERY_BUFF_SIZE];
INT16 cbConLen;
#endif
/*
* Function protypes are declared here
*/
void InitAndConnectToDBS(void);
CHAR InsertRowIntoDBS(CHAR *tName, CHAR *queryStr, INT32 queryStrLen);
CHAR** GetFieldValuesFromDBS(CHAR* qStr, INT32 noOfCols, INT32 len, U_LONG **resultPtrLen);
void CloseConnectionToDBS(void);
CHAR UpdateColumnsInDBS(CHAR *tName, CHAR* queryStr, INT32 queryStrLen);
void FreeDBSResultPtr(CHAR **ptr, INT32 cnt, U_LONG *ptrLen);
void PrintDBSError(void);
CHAR DeleteRowFromDBS(CHAR* queryStr, INT32 queryStrLen);
#ifdef __cplusplus
}
#endif
#endif /* ifndef __ODBC_H__ */odbc.c
#ifdef __cplusplus
extern "C" {
#endif
#include
#include
#include
#include
#include
#define ODBC_PUBLIC
#include "odbc.h"
/**************************************************************************
*Function Name: InitAndConnectToDBS()
*
*Args: Nothing
*
*Returns: Nothing
*
*Task: Establishes connection with database server.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
void InitAndConnectToDBS(void)
{
/*RETCODE rc;
rc = SQLAllocEnv(&hEnv) ;
if( rc != SQL_SUCCESS)
{
PrintDBSError();
DEBUGMSG1("Unable to connect with database 1\n");
return;
}
rc = SQLAllocConnect(hEnv,&hDBC);
if( rc != SQL_SUCCESS)
{
PrintDBSError();
DEBUGMSG1("Unable to connect with database 2\n");
return;
}
rc = SQLDriverConnect(hDBC,NULL,CONSTR,CONLEN,
szConStr,sizeof(szConStr), &cbConLen,SQL_DRIVER_NOPROMPT);
if( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
PrintDBSError();
DEBUGMSG1("Unable to connect with database 3\n");
return;
}*/
/*Step 1 定義句柄和變量 */
// 分配環(huán)境句柄
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
if (retcode != SQL_SUCCESS)
{
printf("SQLAllocHandle error!");
return -1;
}
// 設置環(huán)境句柄
retcode = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
if (retcode != SQL_SUCCESS)
{
printf("SQLSetEnvAttr error!");
return -2;
}
// 分配連接句柄
retcode = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDBC);
if (retcode != SQL_SUCCESS)
{
printf("SQLAllocHandle error!");
return -3;
}
/*之上的程序代碼讀者直接粘貼即可,無限修改;至于具體語句或函數(shù)的功能,沒有必要深入了解,只要清楚每一步的作用(注釋給出)即可*/
/* 連接ODBC數(shù)據(jù)庫,主要函數(shù)中第二個參數(shù)test為操作的數(shù)據(jù)源的名稱;第四個參數(shù)是操作數(shù)據(jù)庫的用戶名;第六個參數(shù)是操作數(shù)據(jù)庫的密碼*/
retcode = SQLConnect(hDBC, (SQLCHAR *)"videodetectodbc", SQL_NTS, (SQLCHAR *)"root",
SQL_NTS, (SQLCHAR *)"root", SQL_NTS);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
printf("SQLConnect error!");
return -4;
}
DEBUGMSG1("Successfully Connected........\n");
}/* End of InitAndConnectToDBS */
/**************************************************************************
* Fucntion Name: CloseConnectionToDBS()
*
*Args: Nothing
*
*Returns: Nothing
*
*Task: Closes connection with database server .
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
void CloseConnectionToDBS(void)
{
if (hDBC)SQLDisconnect(hDBC);
if (hDBC)SQLFreeConnect(hDBC);
if (hEnv)SQLFreeEnv(hEnv);
}/* End of CloseConnectionToDBS */
/**************************************************************************
*Function Name: GetFieldValuesFromDBS()
*
*Args: 1. SQL query string(IN).
* 2. Number of columns(IN).
* 3. Length of each columns(OUT).
*
*Returns: Column values.
*
*Task: Retrives all column values from database for the given
* SQL select query string.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
CHAR** GetFieldValuesFromDBS(CHAR* queryStr, INT32 noOfCols, INT32 len, U_LONG **resultPtrLen)
{
INT32 i;
CHAR **resultPtr;
LONG *lengths;
RETCODE rc;
resultPtr = (CHAR**)__Malloc(sizeof(CHAR*)*noOfCols);
if (resultPtr == NULL)
{
DEBUGMSG1("Memory allocation failed\n");
return NULL;
}
lengths = (LONG *)__Malloc(sizeof(LONG)*noOfCols);
if (lengths == NULL)
{
DEBUGMSG1("Memory allocation failed\n");
__Free(resultPtr);
return NULL;
}
*resultPtrLen = (U_LONG*)__Malloc(sizeof(U_LONG)*noOfCols);
if (*resultPtrLen == NULL)
{
DEBUGMSG1("Memory allocation failed\n");
return NULL;
}
rc = SQLAllocStmt(hDBC, &hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return NULL;
}
for (i = 0; i
DEBUGMSG2("%c", queryStr[i]);
DEBUGMSG1("\n");
rc = SQLPrepare(hStmt, queryStr, __Strlen(queryStr));
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return NULL;
}
for (i = 0; i < noOfCols; i++)
{
resultPtr[i] = (CHAR *)__Malloc(255);
if (resultPtr[i] == NULL)
{
DEBUGMSG1("Memory allocation failed\n");
while (--i >= 0) __Free(resultPtr[i]);
__Free(resultPtr);
__Free(lengths);
return NULL;
}
rc = SQLBindCol(hStmt, i + 1, SQL_C_CHAR, (PTR)resultPtr[i], 255, &lengths[i]);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return NULL;
}
}
rc = SQLExecute(hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return NULL;
}
rc = SQLFetch(hStmt);
if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
{
for (i = 0; i < noOfCols; i++)
{
(*resultPtrLen)[i] = lengths[i];
resultPtr[i][lengths[i]] = '\0';
}
if (hStmt)SQLFreeStmt(hStmt, SQL_DROP);
__Free(lengths);
return resultPtr;
}
else
{
DEBUGMSG1("Error in fetching values......\n");
if (hStmt)SQLFreeStmt(hStmt, SQL_DROP);
__Free(lengths);
return NULL;
}
}/* End of GetFieldValuesFromDBS */
/**************************************************************************
*Function Name: InsertRowIntoDBS()
*
*Args: 1. Table Name (IN).
* 2. Query string(IN).
*
*Returns: SUCCESS/FAILURE.
*
*Task: Adds new row in a given table.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
CHAR InsertRowIntoDBS(CHAR* tName, CHAR* queryStr, INT32 queryStrLen)
{
RETCODE rc;
CHAR szStmt[SQL_QUERY_BUFF_SIZE];
INT32 i;
INT32 tempLen;
sprintf(szStmt, "insert into %s values(", tName);
tempLen = __Strlen(szStmt);
__Memcpy(szStmt + tempLen, queryStr, queryStrLen);
tempLen = tempLen + queryStrLen;
szStmt[tempLen] = '\0';
for (i = 0; i
{
DEBUGMSG2("%c", szStmt[i]);
}
DEBUGMSG1("\n");
rc = SQLAllocStmt(hDBC, &hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
rc = SQLPrepare(hStmt, szStmt, SQL_NTS);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
rc = SQLExecute(hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
if (hStmt)SQLFreeStmt(hStmt, SQL_DROP);
return SUCCESS;
}/* End of InsertRowIntoDBS */
/**************************************************************************
*Function Name: UpdateColumnsInDBS()
*
*Args: 1. Table Name(IN).
* 2. Query string(IN).
*
*Returns: SUCCESS/FAILURE.
*
*Task: Updates a row in a given table.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
CHAR UpdateColumnsInDBS(CHAR* tName, CHAR* queryStr, INT32 queryStrLen)
{
RETCODE rc;
CHAR szStmt[SQL_QUERY_BUFF_SIZE];
INT32 i;
INT32 tempLen;
sprintf(szStmt, "update %s set ", tName);
tempLen = __Strlen(szStmt);
__Memcpy(szStmt + tempLen, queryStr, queryStrLen);
tempLen = tempLen + queryStrLen;
szStmt[tempLen] = '\0';
for (i = 0; i
{
DEBUGMSG2("%c", szStmt[i]);
}
DEBUGMSG1("\n");
rc = SQLAllocStmt(hDBC, &hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
rc = SQLPrepare(hStmt, szStmt, SQL_NTS);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
rc = SQLExecute(hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
if (hStmt)SQLFreeStmt(hStmt, SQL_DROP);
return SUCCESS;
}/* End of UpdateColumnsInDBS */
/**************************************************************************
*Function Name: DeleteRowFromDBS()
*
*Args: 1. Table Name(IN).
* 2. Query string(IN).
*
*Returns: SUCCESS/FAILURE.
*
*Task: Deletes a row in a given table.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
CHAR DeleteRowFromDBS(CHAR* queryStr, INT32 queryStrLen)
{
RETCODE rc;
INT32 i;
for (i = 0; i
DEBUGMSG2("%c", queryStr[i]);
DEBUGMSG1("\n");
rc = SQLAllocStmt(hDBC, &hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
rc = SQLPrepare(hStmt, queryStr, SQL_NTS);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
rc = SQLExecute(hStmt);
if (rc != SQL_SUCCESS)
{
PrintDBSError();
return FAILURE;
}
if (hStmt)SQLFreeStmt(hStmt, SQL_DROP);
return SUCCESS;
}
/**************************************************************************
*Function Name: FreeDBSResultPtr()
*
*Args: 1. References to be freed.
* 2. Number of references to be free.
* 3. References to be freed for length.
*
*Returns: Nothing.
*
*Task: Frees memory.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
void FreeDBSResultPtr(CHAR** ptr, INT32 cnt, U_LONG *ptrLen)
{
INT32 i;
for (i = 0; i
{
__Free(ptr[i]);
}
__Free(ptr);
__Free(ptrLen);
}
/**************************************************************************
*Function Name: PrintDBSError()
*
*Args: Nothing
*
*
*Returns: Nothing.
*
*Task: Prints error message.
*
*See Also:
*
*Docs: Yes.
*
*Bugs:
*****************************************************************************/
void PrintDBSError(void)
{
CHAR szState[6];
CHAR szMsg[255];
INT32 sdwNative;
INT16swMsgLen;
SQLError(hEnv, hDBC, hStmt, szState, &sdwNative,
szMsg, sizeof(szMsg), &swMsgLen);
DEBUGMSG3("%s\n%s\n", szState, szMsg);
}
#ifdef __cplusplus
}
#endif
/**************************************************************************
* End of odbc.c
**************************************************************************/CSDN源碼下載:http://download.csdn.net/detail/davebobo/9521546
總結
以上是生活随笔為你收集整理的mysql odbc c语言_C语言ODBC操作MySQL数据库(示例代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对称矩阵的压缩存储
- 下一篇: c 管理信息系统mysql,输入数据并输