C语言ODBC操作MySQL数据库

 数据库及其编程API来源于不同的背景,开发人员可以从众多的数据库中选择一种,每种数据库都有自己的一套编程API,这就为数据库编程造成了很大的局限性。SQL是标准化数据库编程接口的一种尝试,然而各种数据库所支持的SQL又有所不同。

ODBC的设计目的是允许访问多种数据库,ODBC为数据库供应商提供了一致的ODBC驱动程序标准,遵循这个标准开发的数据库驱动程序,都可以被开发人员通过ODBC
API透明地访问,而不必关心实际的数据库是什么。在这里,ODBC所做的,就是接收开发人员的数据库操作指令,调用相应的ODBC驱动程序,向一个数据库或者向多个数据库发送数据,并可接收来自数据库的数据。

ODBC提供了访问数据库的标准,这使得开发人员将精力集中在应用程序以及用户接口的开发上,而不必考虑与之相连的数据库。为了进一步简化开发工作,ODBC把API层实现为SQL的映射器。通常数据库开发人员将标准的SQL语句发送给ODBC驱动程序,再由ODBC驱动程序将这个SQL语句映射成数据库可以支持的SQL语句。

本章首先对ODBC API的概貌进行简要介绍,然后讲述利用ODBC API进行数据库开发的技巧,最后将通过具体数据库开发实例,详细讲述通过ODBC API开发数据库应用程序的方法和过程。

1了解ODBC API

ODBC是一种使用SQL的程序设计接口。使用ODBC让应用程序的编写者避免了与数据源相联的复杂性。这项技术目前已经得到了大多数DBMS厂商们的广泛支持。ODBC是一种使用SQL 的程序设计接口。使用ODBC让应用程序的编写者避免了与数据源相联的复杂性。这项技术目前已经得到了大多数DBMS厂商们的广泛支持。

Microsoft Developer Studio为大多数标准的数据库格式提供了32位ODBC驱动器。这些标准数据格式包括有:SQL Server,Access,Paradox,dBase,FoxPro,Excel,Oracle 以及Microsoft Text。如果用户希望使用其他数据格式,用户需要相应的ODBC驱动器及DBMS。

ODBC API是一个内容丰富的数据库编程接口,包括60多个函数、SQL数据类型以及常量的声明。ODBC API 是独立于DBMS和操作系统的,而且它与编程语言无关。ODBC API 以X/Open和ISO/IEC中的CLI规范为基础,ODBC 3.0完全实现了这两种规范,并添加了基于视图的数据库应用程序开发人员所需要的共同特性,例如可滚动光标。ODBC API中的函数由特定DBMS驱动程序的开发人员实现,应用程序用这些驱动程序调用函数,以独立于DBMS的方式访问数据。

ODBC API涉及了数据源连接与管理、结果集检索、数据库管理、数据绑定、事务操作等内容,目前的最高版本是3.0。

2  ODBCAPI编程步骤

通常使用ODBC API开发数据库应用程序需要经过如下步骤:

·      连接数据源。

·      分配语句句柄。

·      准备并执行SQL语句。

·      获取结果集。

·      提交事务。

·      断开数据源连接并释放环境句柄。

下面对上述步骤做详细的介绍。

步骤1:连接数据源

为了连接数据源,必须要建立一个数据源连接的环境句柄。通过调用SQLAllocEnv函数实现对环境句柄的分配,在ODBC 3.0里,这个函数已经被SQLAllocHandle取代,但是熟悉ODBC API的开发人员还是习惯用这个函数建立环境句柄,因为VC++开发平台有一个映射服务,这个服务将程序代码对函数SQLAllocEnv的调用转向对函数SQLAllocHandle的调用。

这里有必要对“环境句柄”这个概念进行说明。句柄是指向一个特殊结构的指针,而环境指的是驱动程序管理器需要为该驱动程序存储的有关系统和数据源的一般信息。由于这个时候还没有建立同数据源的连接,驱动程序还并不知道该使用哪一个驱动程序来完成这个任务,所以这个任务只能由驱动程序管理器来完成,利用这个环境句柄保留信息直到被使用。

使用函数SQLAllocEnv创建环境句柄的语法如下:

HENV  henv;

RETCODE rcode;

rcode = ::SQLAllocEnv(SQL_HANDLE_ENV, SQL_NULL,& henv);

if(rcode == SQL_SUCCESS)   // 环境句柄创建成功

{

// 执行其它操作

…………

}

完成了环境句柄的创建以后,还要建立一个连接句柄。连接句柄的创建函数是SQLAllocConnect,其调用语法如下:

HDBC   hdbc;

retcode = ::SQLAllocConnect( m_henv, & hdbc);

if(rcode == SQL_SUCCESS)   // 连接句柄创建成功

{

// 执行其它操作

…………

}

完成了环境句柄和连接句柄的创建以后,就可以进行实际的数据源连接了。完成数据源连接的函数是SQLConnect,其调用语法如下:

m_retcode = :: SQLConnect( m_hdbc,

(PUCHAR)pszSourceName,SQL_NTS,

(PUCHAR)pszUserId,wLengthUID,

(PUCHAR)pszPassword,wLengthPSW );

if(rcode == SQL_SUCCESS)   // 数据源连接成功

{

// 执行其它操作

…………

}

到此,应用程序同数据源的连接已经完成。

有些时候,ODBC数据源并不是事先在用户的计算机里安装好了的,这时就需要应用程序能够动态创建ODBC数据源。ODBC API提供了动态创建数据源的函数SQLConfigDataSource。该函数的语法如下:

BOOL SQLConfigDataSource(HWND  hwndParent,

WORD  fRequest,

LPCSTR  lpszDriver,

LPCSTR  lpszAttributes);

参数hwndParent用于指定父窗口句柄,在不需要显示创建数据源对话框时,可以将该参数指定为NULL;参数fRequest用于指定函数的操作内容,函数SQLConfigDataSource能够实现的操作内容由参数fRequest制定,参数fRequest取值如下:

ODBC_ADD_DSN:创建数据源;

ODBC_CONFIG_DSN:配置或者修改已经存在的数据源;

ODBC_REMOVE_DSN:删除已经存在的数据源;

ODBC_ADD_SYS_DSN:创建系统数据源;

ODBC_CONFIG_SYS_DSN:配置或者修改已经存在的系统数据源;

ODBC_REMOVE_SYS_DSN:删除已经存在的系统数据源;

ODBC_REMOVE_DEFAULT_DSN:删除缺省的数据源。

参数lpszDriver用于指定ODBC数据源的驱动程序类别,例如,为了指定Access数据源,该参数应赋以字符串“MicrosoftAccess Driver (*.mdb)\0”。 参数lpszAttributes用于指定ODBC数据源属性,例如:

“DSN=MYDB\0DBQ=D:\\Database\\Friends.mdb\0DEFAULTDIR=D:\\DATABASE\0\0”

该字符串指定数据源名称(DSN)为MYDB,数据库文件(DBQ)为D:\Database\Friends.mdb,缺省数据库文件路径(DEFAULTDIR)为D:\DATABASE。

通过调用如下代码可以通过应用程序动态创建数据源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<mlen; i++){

if(szDesc[i] == ‘:‘)         szDesc[i] = ‘\0‘;

}

if (FALSE ==SQLConfigDataSource(NULL,ODBC_ADD_DSN,

"MicrosoftAccess Driver (*.mdb)\0",

(LPCSTR)szDesc))

returnFALSE; // 创建数据源失败。

else

returnTRUE; // 创建数据源成功。

}

步骤2:分配语句句柄

通常将ODBC中的语句看作SQL语句。前面已经提到,ODBC同数据库的SQL接口通信,驱动程序将ODBC的SQL映射到驱动程序的SQL。但是ODBC的SQL还携带了一些属性信息,用于定义数据源连接的上下文,有些语句要求特殊的参数以便能够执行,因此,每个语句都有一个指向定义语句所有属性结构的句柄。

语句句柄的分配同环境句柄的分配相似,通过函数SQLAllocStmt实现,该函数的调用语法如下:

HSTMT    hstmt;

RETCODE rcode;

m_retcode = :: SQLAllocStmt(hdbc,  &hstmt );

if(rcode == SQL_SUCCESS)   // 连接句柄创建成功

{

// 执行其它操作

…………

}

步骤3:准备并执行SQL语句

对于不同的应用程序需求,要准备的SQL语句也一定不一样。通常的SQL语句包括SELECT、INSERT、UPDATA、DELETE、DROP等。

准备和执行一个SQL语句的方法有两种,第一种是使用SQLExecDirect函数,可以一次执行一个SQL语句。很多请求都可以使用这个方法。调用SQLExecDirect函数的语法如下:

LPCSTR pszSQL;

strcpy(pszSQL, “SELECT * FROM EMPLOYEES”);

retcode = ::SQLExecDirect(hstmt,  (UCHAR*)pszSQL,  SQL_NTS );

if(rcode == SQL_SUCCESS)   // SQL语句执行成功

{

// 执行其它操作

…………

}

但是有些请求需要多次执行同一条语句,为此,ODBC提供了SQLPrepare函数和SQLExecute函数。调用的时候,只需要调用一次SQLPrepare函数,然后调用若干次SQLExecute函数。实际上,函数SQLExecDirect将SQLPrepare和SQLExecute的功能集中到了一起,多次调用SQLExecDirect显然比调用一次SQLPrepare再调用若干次SQLExecute效率高。调用SQLPrepare和SQLExecute函数的语法如下:

LPCSTR pszSQL;

strcpy(pszSQL, “SELECT * FROM EMPLOYEES”);

m_retcode = ::SQLPrepare( hstmt,  (UCHAR*)pszSQL,  SQL_NTS );

if(rcode == SQL_SUCCESS)   // SQL语句准备成功

{

// 执行其它操作

…………

}

retcode = :: SQLExecute (hstmt,  (UCHAR*)pszSQL,  SQL_NTS );

if(rcode == SQL_SUCCESS)   // SQL语句执行成功

{

// 执行其它操作

…………

}

步骤4:获取结果集

SQL语句执行成功以后,应用程序必须准备接收数据,应用程序需要把SQL语句执行结果绑定到一个本地缓存变量里。但是SQL执行语句执行的结果并不是直接传送给应用程序,而是在应用程序准备接收数据的时候通知驱动程序其已经准备好接收数据,应用程序通过调用SQLFetch函数返回结果集的一行数据。

由于返回的数据是存放在列中的,因此应用程序必须调用SQLBindCol函数绑定这些列。通常接收结果集时需要依次进行以下操作:

·      返回列的个数,执行SQLNumResultCols函数。

·      给出列中数据的有关信息,例如列的名称、数据类型和精度等,执行SQLDescribeCol函数。

·      把列绑定到应用程序的变量里,执行SQLBindCol函数。

·      获取数据,执行SQLFetch函数。

·      获取长数据,执行SQLGetData函数。

应用程序首先调用SQLNumResultCols函数,获知每个记录里有多少列,调用SQLDescribeCol函数取得每列的属性,然后调用SQLBindCol函数将列数据绑定到指定的变量里,最后调用SQLFetch函数或者SQLGetData函数获取数据。

对于其它的SQL语句,应用程序重复这个过程。这个过程代码如下:

retcode = ::SQLNumResultCols( m_hstmt,&wColumnCount );

if( m_retcode != SQL_SUCCESS ) // 列举结果集列的个数不成功

{

// 释放操作

…………

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,    // 存放列名称的缓冲区大小

& nRealLength,  // 实际得到列名称的长度

&wColumnType,  // 列的数据类型

&dwPrecision,  // 精度

&wScale, // 小数点位数

&wNullable );  // 是否允许空值

if(retcode != SQL_SUCCESS ) // 执行不成功

{

// 释放操作

…………

return;

}

retcode = ::SQLBindCol( m_hstmt,

uCounter, // 列索引

wColumnType, // 列数据类型

FieldValue, // 绑定的变量

dwBufferSize, // 变量内存大小

&BytesInBuffer); // 存放将来返回数据的大小的变量

if(retcode != SQL_SUCCESS ) // 执行不成功

{

// 释放操作

…………

return;

}

::SQLFetch( m_hstmt );

// 此后可以从绑定的变量里读取列的值。

…………

步骤5:提交事务

当所有的SQL语句都被执行并接收了所有的数据以后,应用程序需要调用SQLEndTran提交或者回退事务。如果提交方式为手工(应用程序设置)方式,则需要应用程序执行这个语句以提交或者回退事务,如果是自动方式,当SQL语句执行后,该命令自动执行。

事务是为了维护数据的一致性和完整性而设计的概念,事务要求:要么提交,将事务里包含的更新操作都提交到数据库里;要么回退,数据库恢复到事务前的状态,不会影响数据库的一致性和完整性。通常情况下,检索类SQL语句不涉及数据的更新,不会对数据的一致性和完整性产生影响,因此通常将检索类SQL语句设置提交方式为自动,而将更新类SQL语句的提交方式设置为手工方式,便于通过代码在事务处理中执行事务的提交或者回退,以维护数据库的一致性和完整性。在大型的商业应用中,这个设置非常有用。

调用SQLEndTran函数的语法如下:

:: SQLEndTran(SQL_HANDLE_DBC , hdbc,  SQL_COMMIT); // 提交事务

:: SQLEndTran(SQL_HANDLE_DBC , hdbc,  SQL_ROLLBACK); // 回退事务

步骤6:断开数据源连接并释放环境句柄

当应用程序使用完ODBC以后,需要使用SQLFreeHandle函数释放所有语句句柄、连接句柄、环境句柄。这里需要注意操作的顺序,应该是先释放所有语句句柄,调用SQLDisconnect函数解除与数据源的连接,然后释放所有连接句柄,最后释放环境句柄,使应用程序同ODBC管理器的连接彻底解除。

一个封装好的C语言odbc操作mysql的源码分享给大家,这里需要注意的是我们的工程需要选择使用多字节字符集

odbc.h

typedef char CHAR;
typedef signed int INT32;
typedef	unsigned long U_LONG;
#define		SUCCESS		1
#define		FAILURE		0
#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 <stdio.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#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 定义句柄和变量 */
	// 分配环境句柄
	retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
	if (retcode != SQL_SUCCESS)
	{
		printf("SQLAllocHandle error!");
		return -1;
	}

	// 设置环境句柄
	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;
	}

	/*之上的程序代码读者直接粘贴即可,无限修改;至于具体语句或函数的功能,没有必要深入了解,只要清楚每一步的作用(注释给出)即可*/
	/* 连接ODBC数据库,主要函数中第二个参数test为操作的数据源的名称;第四个参数是操作数据库的用户名;第六个参数是操作数据库的密码*/
	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<len; 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<tempLen; 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<tempLen; 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<queryStrLen; 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<cnt; 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;
	INT16	swMsgLen;
	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

 

时间: 2024-11-12 21:47:41

C语言ODBC操作MySQL数据库的相关文章

c语言操作mysql数据库

c语言操作Mysql数据库,主要就是为了实现对数据库的增.删.改.查等操作,操作之前,得先连接数据库啊,而连接数据库主要有两种方法.一.使用mysql本身提供的API,在mysql的安装目录中可可以看到大量的头文件.lib文件.dll文件,这说明mysql原生就支持了c语言,操作起来相当简单.二.使用win32 api(这里只探讨windows平台),主要是ODBC. ODBC API 接口是(Open Database Connectivity)开放式数据库接口,它建立了一组规范,并提供了一组

Go语言中使用MySql数据库

Go语言中使用MySql数据库 1.MySQL驱动 Go中支持MySQL的驱动目前比较多,有如下几种,有些是支持database/sql标准,而有些是采用了自己的实现接口,常用的有如下几种: https://github.com/Go-SQL-Driver/MySQL 支持database/sql,全部采用go写. https://github.com/ziutek/mymysql 支持database/sql,也支持自定义的接口,全部采用go写. https://github.com/Phil

PHP操作MySQL数据库的相关函数

首先,要分清SQL语句的类型: SQL语句的分类 (1)DDL:Data Define Language,数据定义语言--定义表的列结构 CREATE.DROP.ALTER.TRUNCATE (2)DML:Data Manipulate Language,数据操作语言--操作表的记录行 INSERT.DELETE.UPDATE (3)DQL:Data Query Language,数据查询语言--不影响表的行和列 SELECT (4)DCL:Data Control Language,数据控制语

[PHP]PHP编程操作Mysql数据库的三种方式

当我开始去接触PHP的时候,真切的感受到其所具有的魅力,本着学习的态度和打破固有的语言和模式的想法,开始了PHP之旅,总的来说,走的还是比较顺利,在其中能够看到C,Java,Perl影子,学习曲线不大,但是做好产品仍然有着一条漫漫长路. 多余的话不说了,慢慢感受和领悟,本文主要讲述PHP操作数据库的三种扩展. 如下图是PHP访问数据库的三种扩展方式: 下面举出三种方式访问数据库并查询数据的实例代码: 1.mysql扩展 <?php //1:获取数据库连接 $connection = @ mysq

php笔记08:数据库编程---使用php的MySQL扩展库操作MySQL数据库

1.使用php的MySQL扩展库操作MySQL数据库: php有3种方式操作MySQL数据库 (1)mysql扩展库 (2)mysqli扩展库 (3)pdo   mysql扩展库与mysql数据库区别 ? php设计者封装了一些方法去操作mysql数据库,这些方法集中起来形成了mysql扩展库.mysql数据库存放数据.     2.使用php的MySQL扩展库操作MySQL数据库案例: (1)环境搭建:启用MySQL数据库,在php.ini文件中配置使用MySQL数据库,          

C#连接操作 MySQL 数据库实例(使用官方驱动)

MySQL 以其免费和足够的性能受到很大的青睐,当然对于国内小公司,甚至是大公司如果对版权看得薄,敢冒险的话,随便装个 SqlServer.DB2.Oracle 都行.对于 SqlServer 数据库,因其与 MS 是一家,自然在 .net 类库中有内建支持,假如 MySQL 就得找第三方的驱动了 - .net 中多讲 Provider.在这里我也是作为一个预研专题,记录下 C# 连接 MySQL 的两种方法,分别使用 MySQL 官方的和 SourceForge 上一个开源的 MySQL 驱动

C#中简单操作Mysql数据库

以C#访问MySQL数据库,执行简单的CRUD. MySql.Data.dll是C#操作MySQL的驱动文件,是C#连接MySQL必要插件,使C#语言更简洁的操作MySQL数据库.可以用NuGet命令安装 PM>Install-Package MySql.Data -Version 8.0.16 项目中添加该组件的引用,在代码页里输入using MySql.Data.MySqlClient;我们就可以顺利的使用该类库的函数建立连接了. 数据库连接字符串写法为:server=服务器ip地址;Use

python操作mysql数据库

连接数据库 输入值 存入数据库 关闭 import string import mysql.connector conn=mysql.connector.connect(user='root',password='test',database='dalian',use_unicode=True) cursor=conn.cursor() a=raw_input('enter an id: ') b=raw_input('enter a name: ') while(a!='quit' or b!

Windows下安装MySQLdb, Python操作MySQL数据库的增删改查

这里的前提是windows上已经安装了MySQL数据库,且配置完毕,能正常建表能操作.在此基础上只需安装MySQL-python-1.2.4b4.win32-py2.7.exe就ok了,只有1M多.这个有点类似jdbc里的那个jar包. 下载链接:http://sourceforge.net/projects/mysql-python/ , 百度云盘 :http://pan.baidu.com/s/1dDgnfpR 密码:7bna 接着import MySQLdb就能使用了,下面给出测试代码: