创建数据源有两种方法,一种用数据源ODBC管理器创建,一种用函数SQLConfigDataSource创建,先来说一下ODBC管理器创建,了解一些概念,首先用Access创建一个数据库(mdb文件),然后打开ODBC管理器,选择开始->设置->控制面板->管理工具->数据源(ODBC)。
程序窗口如下:
点“添加”按钮,添加一个数据源,到时候就可以用SQLConnect连接你所创建的数据源了。点“添加”按钮,弹出的窗口如下:
因为要连接的数据库文件是Access创建的,所以驱动程序选择Misrosoft Access Driver (*.mdb),点完成
(如果连接的是Sql server数据库,驱动程序选择“SQL Server")。
。给数据源取一个名称,描述信息,如下:
记住数据源的名称,SQLConnect函数的第二个参数填的就是数据源名称。填完上面信息后,点击“选择”按钮,选择数据库文件。如下图:
一路点确定,完成,就可以了,创建了数据源我们就用SQLConnect函数来连接它吧。
SQLConnect函数定义:
SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle,//数据源连接需要的连接变量,可用SQLAllocEnv创建
SQLCHAR *ServerName, //数据源名称
SQLSMALLINT NameLength1,//ServerName参数的长度,取SQL_NTS就行了。
SQLCHAR *UserName, //用户名,没有为NULL
SQLSMALLINT NameLength2,//用户名字符串长度,可取SQL_NTS。没有为0
SQLCHAR *Authentication, //用户密码
SQLSMALLINT NameLength3);//用户密码字符串长度
连接数据源的例子:
#include<windows.h>
#include<sqlext.h>//SQLConnect函数头文件
#include<iostream.h>
int main()
{
HENV henv;//数据据源连接需要的环境变量
HDBC hdbc;//数据源连接需要的连接变量
RETCODE rcode;
//创建环境句柄
SQLAllocEnv(&henv);
//创建连接句柄
SQLAllocConnect(henv,&hdbc);
//上面的语句是固定的,记住就行了。
//连接数据源
rcode=::SQLConnect(hdbc,(PUCHAR)"MyODBC",SQL_NTS,NULL,0,NULL,0);
if(rcode==SQL_SUCCESS)
{
cout<<"连接数据源成功!"<<endl;
}
else
{
cout<<"连接失败!"<<endl;
}
return 0;
}
连接数据库,也并非得通过连接数据源的方法实现,像SQLDriverConnect函数不使用 ODBC 数据源进行连接的,以后会介绍这个函数。
第二百二十一个SQLExecDirect执行SQL语句 (ODBC API)
函数定义:
SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle,//语句句柄,SQLAllocStmt函数可分配
SQLCHAR *StatementText,//SQL语句
SQLINTEGER TextLength);//SQL语句字符串长度,可为SQL_NTS
一个执行SQL语句的例子:
#include<windows.h>
#include<sqlext.h>//SQLConnect函数头文件
#include<iostream.h>
int main()
{
HENV henv;//数据据源连接需要的环境变量
HDBC hdbc;//数据源连接需要的连接变量
HSTMT hstmt;//语句变量
RETCODE rcode;
//创建环境句柄
SQLAllocEnv(&henv);
//创建连接句柄
SQLAllocConnect(henv,&hdbc);
//上面的语句是固定的,记住就行了。
//连接数据源
rcode=::SQLConnect(hdbc,(PUCHAR)"MyODBC",SQL_NTS,NULL,0,NULL,0);
if(rcode==SQL_SUCCESS)
{
cout<<"连接数据源成功!"<<endl;
}
else
{
cout<<"连接失败!"<<endl;
return 0;
}
//分配句柄
::SQLAllocStmt(hdbc,&hstmt);
LPSTR pszSQL=new char[52];
//假设数据库里表名为BookInfo,里面有BookPrice和BookName列。
strcpy(pszSQL,"Update BookInfo set BookPrice=1000 where BookName='VC++'");
//执行SQL语句
rcode=::SQLExecDirect(hstmt,(UCHAR *)pszSQL,SQL_NTS);
if(rcode==SQL_SUCCESS)
{
cout<<"执行SQL语句成功!"<<endl;
}
else
{
cout<<"执行失败!"<<endl;
}
::SQLDisconnect(hdbc);//解除连接
return 0;
}
第一百二十二个SQLConfigDataSource配置数据源
函数定义:
BOOL SQLConfigDataSource(
HWND hwndParent,//创建数据源的父窗口句柄,为NULL不显示创建数据源对话框。
WORD fRequest,//指明对数据源进行什么操作,创建、修改、删除等。
LPCSTR lpszDriver,//驱动程序名,对应上面创建新数据源对话框里的驱动程序名称。
LPCSTR lpszAttributes);//此字符串以双'\0'结尾,包含数据各项属性,如用户ID,数据库文件路径,数据源名称等,项属性以'\0'间隔
fRequest参数的可选值信息如下:
ODBC_ADD_DSN:创建数据源;
ODBC_CONFIG_DSN:配置或者修改已经存在的数据源;
ODBC_REMOVE_DSN:删除已经存在的数据源;
//删除数据源的代码:
SQLConfigDataSource(NULL,ODBC_REMOVE_DSN,"Microsoft Access Driver (*.mdb)","DSN=MyODBC\0\0");
ODBC_ADD_SYS_DSN:创建系统数据源;
ODBC_CONFIG_SYS_DSN:配置或者修改已经存在的系统数据源;
ODBC_REMOVE_SYS_DSN:删除已经存在的系统数据源;
ODBC_REMOVE_DEFAULT_DSN:删除缺省的数据源。
lpszAttributes参数,各属性名如下:
DSN:数据源的名称
DBQ:数据库路径
DEFAULTDIR:数据库缺省路径,也就是DBQ只填一个文件名,那么系统要到哪个目录去找这个文件
DESCRIPTION:说明,可随便赋值,就是上面的那个“This is my ODBC"
SERVER:服务器名称 (SQL Server)
DATABASE:数据库名称,如master,model
一个创建数据源的例子:
#include<windows.h>
#include<sqlext.h>//SQLConnect函数头文件
#include<iostream.h>
#include <odbcinst.h>//SQLConfigDataSource函数头文件
int main()
{
BOOL Result;
Result=SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)",
"DSN=DsAccess\0DBQ=d:\\book.mdb\0\0");
if(Result==TRUE)
{
cout<<"数据源创建成功!"<<endl;
}
else
{
cout<<"创建失败!"<<endl;
}
return 0;
}
可以到ODBC 数据源管理器去查看,看看有没有DsAccess这个数据源当然上面也有提示了。。。。
再举一个例子,SQL Server的:
先在SQL Server里创建一个数据库,名为MyDatabase,在其下新建一个表BookInfo,字段BookName,BookPrice,跟上面的Access表一样,创建好后,添加一行数据吧,BookName:VC++,BookPrice:87,关闭,保存。
然后添加Sql Server数据源,这里给出关键几步的截图。
数据源名称,服务器名如下:
服务器名是20110304-1717,这个根据自己的Sql Server服务器名来填。看下面,Sql Server截图。
知道是什么了吧。。那么用SQLConfigDataSource创建数据源的时候,最后一个参数的SERVER项填的就是这个名称。
上面有两个选项,第一项不需要用户填用户ID和密码,就可以登陆,使用默认。这里我选择第二个,那么我在调用SQLConnect连接数据源时候,就要填入ID和密码,而选择第一项的话,则不需要。
更改默认的数据库为MyDatabase,这个对应SQLConfigDataSource函数最后一个参数的DATABASE
之后,设置保持默认不变,一直点下一步,然后测试一下数据,点完成。。就可以了。。创建好了数据源,我们就用代码来测试一下。
如下:
#include<windows.h>
#include<sqlext.h>//SQLConnect函数头文件
#include<iostream.h>
#include <odbcinst.h>//SQLConfigDataSource函数头文件
int main()
{
/*
//这个是使用SQLConfigDataSource函数创建SQL Server数据源的代码
BOOL Result;
Result=SQLConfigDataSource(NULL,ODBC_ADD_DSN,"SQL Server",
"DSN=MySqlServer\0SERVER=20110304-1717\0DATABASE=MyDatabase\0\0");
if(Result==TRUE)
{
cout<<"数据源创建成功!"<<endl;
}
else
{
cout<<"创建失败!"<<endl;
}*/
HENV henv;//数据据源连接需要的环境变量
HDBC hdbc;//数据源连接需要的连接变量
HSTMT hstmt;//语句变量
RETCODE rcode;
//创建环境句柄
SQLAllocEnv(&henv);
//创建连接句柄
SQLAllocConnect(henv,&hdbc);
//如果配置数据源的时候,指定了使用用户输入ID和密码方式验证,那么连接的时候,
//也必需提供正确的密码,反之则不需要
rcode=::SQLConnect(hdbc,(PUCHAR)"MySqlServer",SQL_NTS,(PUCHAR)"sa",SQL_NTS,
(PUCHAR)"123456",SQL_NTS);
if(rcode==SQL_SUCCESS||rcode==SQL_SUCCESS_WITH_INFO)
{
cout<<"连接数据源成功!"<<endl;
}
else
{
cout<<"连接失败!"<<endl;
}
::SQLAllocStmt(hdbc,&hstmt);
LPSTR pszSQL=new char[52];
//假设数据库里表名为BookInfo,里面有BookPrice和BookName列。
strcpy(pszSQL,"Update BookInfo set BookPrice=1000 where BookName='VC++'");
//执行SQL语句
rcode=::SQLExecDirect(hstmt,(UCHAR *)pszSQL,SQL_NTS);
if(rcode==SQL_SUCCESS)
{
cout<<"执行SQL语句成功!"<<endl;
}
else
{
cout<<"执行失败!"<<endl;
}
::SQLDisconnect(hdbc);//解除连接
return 0;
}
第一百二十三个SQLDescribeCol获取结果集一列的信息,如列名,列的数据类型等
在接触SQLDescribeCol之前先提一个函数:SQLNumResultCols,这个函数获取结果集列的个数(就是一张表有几列)
这个函数只有两个参数,最后一个参数存储列数。
SQLDescribeCol函数定义:
SQLRETURN SQLDescribeCol(
SQLHSTMT StatementHandle,//htstmt句柄
SQLUSMALLINT ColumnNumber,//列索引,获取哪一列的信息,从1开始
SQLCHAR * ColumnName,//存储列名
SQLSMALLINT BufferLength,//参数ColumnName的大小(指向的内存)以字节为单位
SQLSMALLINT * NameLengthPtr,//存储列名实际获得的长度
SQLSMALLINT * DataTypePtr,//列的数据类型,如SQL_CHAR,SQL_FLOAT
SQLULEN * ColumnSizePtr,//数据的长度,数据所占的字节,如int型默认4,char(10),就是10
SQLSMALLINT * DecimalDigitsPtr,//小数点位数
SQLSMALLINT * NullablePtr);//列属性,数据是否可以为空,SQL_NO_NULLS列不允许空值,SQL_NULLABLE可以为空
例子:获取一张表里的所有列名。假设有一张Student表
#include<windows.h>
#include<sqlext.h>//SQLConnect函数头文件
#include<iostream.h>
#include <odbcinst.h>//SQLConfigDataSource函数头文件
int main()
{
HENV henv;//数据据源连接需要的环境变量
HDBC hdbc;//数据源连接需要的连接变量
HSTMT hstmt;//语句变量
RETCODE rcode;
//创建环境句柄
SQLAllocEnv(&henv);
//创建连接句柄
SQLAllocConnect(henv,&hdbc);
rcode=::SQLConnect(hdbc,(PUCHAR)"MySqlServer",SQL_NTS,NULL,0,
NULL,0);
if(rcode==SQL_SUCCESS||rcode==SQL_SUCCESS_WITH_INFO)
{
cout<<"连接数据源成功!"<<endl;
}
else
{
cout<<"连接失败!"<<endl;
}
::SQLAllocStmt(hdbc,&hstmt);
LPSTR pszSQL=new char[52];
//假设数据库里表名为Student
strcpy(pszSQL,"Select * from Student");
//执行SQL语句
rcode=::SQLExecDirect(hstmt,(UCHAR *)pszSQL,SQL_NTS);
if(rcode==SQL_SUCCESS)
{
cout<<"执行SQL语句成功!"<<endl;
short ColumnCount;//列数
SQLNumResultCols(hstmt,&ColumnCount);
cout<<"列数:"<<ColumnCount<<endl;
LPSTR pszName=new char[256];//列名
UWORD ColumnIndex;//列的索引
short BufferLength;//列名的长度
SWORD ColumnType;//列的数据类型
UDWORD ColumnSize;//数据的长度
SWORD DecimalDigits;//小数点位数
SWORD Nullable;//值是否可以为NULL
cout<<"列名:"<<endl;
//读取每一列的信息,从索引1开始
for(ColumnIndex=1;ColumnIndex<=ColumnCount;ColumnIndex++)
{
SQLDescribeCol(hstmt,ColumnIndex,(UCHAR *)pszName,256,&BufferLength,
&ColumnType,&ColumnSize,&DecimalDigits,&Nullable);
//输出列名
cout<<pszName<<" ";
}
cout<<endl;
}
else
{
cout<<"执行失败!"<<endl;
}
::SQLDisconnect(hdbc);//解除连接
return 0;
}
运行效果如下图:
第一百二十四个SQLBindCol绑定变量到一个列
绑定变量到一个列,就可以获得对应列任何一行的内容,比如StuName列,我定义一个字符串指针变量pName,并分配内存,把pName跟
StuName列绑定后,调用SQLFetch函数,就可以获得StuName列一行内容,默认是第一行,也就是第一行StuName列的数据,再次调用SQLFetch的话,pName存储的就是第二行StuName列的内容,依次递增。
SQLBindCol函数定义:
SQLRETURN SQLBindCol(
SQLHSTMT StatementHandle,//hstmt句柄
SQLUSMALLINT ColumnNumber,//获取哪一列的内容,列索引
SQLSMALLINT TargetType,//数据类型
SQLPOINTER TargetValuePtr,//绑定的变量
SQLLEN BufferLength,//存储数据缓存区大小,也就是TargetValuePtr的大小
SQLLEN * StrLen_or_Ind);//实际获取数据大小(相对于BufferLength)。每次绑定变量的数据改变,这个参数值也跟着改变,指明数据大小
这里得说一下第三个参数TargetType数据类型,这个参数对应SQLDescribeCol函数第六个参数DataTypePtr,它们的解释是一样的。
另外,即使函数填的数据类型和列实际类型不匹配,也可以,可以自动转换,当然这里有一个前提,它们得可以转换,比如字符串"12345"转换成整型12345是没有问题的,但字符串"1abc"显然不可以转换成整型。不过,读取的时候,不想去了解这其中关系的,数据类型填SQL_C_CHAR就行了,也就是SQL_CHAR,这个表示字符串。
试想,不管是整型,浮点型,还是日期类型都可以以字符串的形式来显示。而且你也可以调用相关的函数来转化类型,用这个就可以了。
如果愿望花时间去了解数据类型的区别,可以到MSDN去查,地址:(看那张表就行了)
http://msdn.microsoft.com/en-us/library/ms714556(v=VS.85).aspx
例子:读取第一列,和第二列所有行数据。
#include<windows.h>
#include<sqlext.h>//SQLConnect函数头文件
#include<iostream.h>
#include <odbcinst.h>//SQLConfigDataSource函数头文件
int main()
{
HENV henv;//数据据源连接需要的环境变量
HDBC hdbc;//数据源连接需要的连接变量
HSTMT hstmt;//语句变量
RETCODE rcode;
//创建环境句柄
SQLAllocEnv(&henv);
//创建连接句柄
SQLAllocConnect(henv,&hdbc);
rcode=::SQLConnect(hdbc,(PUCHAR)"MySqlServer",SQL_NTS,NULL,0,
NULL,0);
if(rcode==SQL_SUCCESS||rcode==SQL_SUCCESS_WITH_INFO)
{
cout<<"连接数据源成功!"<<endl;
}
else
{
cout<<"连接失败!"<<endl;
}
::SQLAllocStmt(hdbc,&hstmt);
LPSTR pszSQL=new char[52];
//假设数据库里表名为Student
strcpy(pszSQL,"Select * from Student");
//执行SQL语句
rcode=::SQLExecDirect(hstmt,(UCHAR *)pszSQL,SQL_NTS);
if(rcode==SQL_SUCCESS)
{
cout<<"执行SQL语句成功!"<<endl;
short ColumnCount;//列数
SQLNumResultCols(hstmt,&ColumnCount);
cout<<"列数:"<<ColumnCount<<endl;
LPSTR pszName=new char[256];//列名
UWORD ColumnIndex;//列的索引
short BufferLength;//列名的长度
SWORD ColumnType;//列的数据类型
UDWORD ColumnSize;//数据的长度
SWORD DecimalDigits;//小数点位数
SWORD Nullable;//值是否可以为NULL
cout<<"列名:"<<endl;
//读取每一列的信息,从索引1开始
for(ColumnIndex=1;ColumnIndex<=ColumnCount;ColumnIndex++)
{
SQLDescribeCol(hstmt,ColumnIndex,(UCHAR *)pszName,256,&BufferLength,
&ColumnType,&ColumnSize,&DecimalDigits,&Nullable);
//输出列名
cout<<pszName<<" ";
}
cout<<endl;
char *pStuNo=new char[256];//绑定的变量,学号
char *pStuName =new char[256];//绑定的变量,学生姓名
long StuNolen;//实际获取数据的大小
long StuNamelen;
//绑定变量
SQLBindCol(hstmt,1,SQL_C_CHAR,pStuNo,256,&StuNolen);//第一列
SQLBindCol(hstmt,2,SQL_C_CHAR,pStuName,256,&StuNamelen);//第二列
rcode=SQLFetch(hstmt);//获取内容
while(rcode==SQL_ROW_SUCCESS||rcode==SQL_ROW_SUCCESS_WITH_INFO)
{
cout<<pStuNo<<" "<<pStuName<<endl;
rcode=SQLFetch(hstmt);//获取下一行内容
}
SQLCancel(hstmt);
}
else
{
cout<<"执行失败!"<<endl;
}
::SQLDisconnect(hdbc);//解除连接
return 0;
}
运行效果截图: