现在的位置: 首页 > 综合 > 正文

【C语言】使用ODBC连接Microsoft SQL server数据库

2013年01月31日 ⁄ 综合 ⁄ 共 8310字 ⁄ 字号 评论关闭

因为最近要用C对SQL Server进行连接,但发现网上关于这方面的资料不多,就把这两天查到的资料和心得归拢了下,留着以后自己看。

使用C语言通过ODBC(开放式数据库互连)对SQL Server进行连接,分为两步操作:1.配置本地ODBC环境;2.码代码...=_=

【首先配置本地环境】
1.启动SQLSERVER服务,例如:HNHJ,开始菜单 ->运行 ->net start mssqlserver


2.更改SQL server登录方式为SQL Server身份验证登陆。

步骤:进入你的数据库->在服务器上右键->属性->安全性->SQL Server和Windows身份验证模式->点确定。


3.打开企业管理器,建立数据库,并在数据库中建立一张表。

我的数据库名字是CCCS,创建city表

4.建立系统DSN,开始菜单 ->运行 ->odbcad32

点击添加->SQL Server->数据源名称(自己起个名字记住,一会有用,我的是CCCS)->选择SQL Server服务器(选取本机名称,不要选local)->使用用户使用登录ID和密码的SQL Server验证->登录ID:sa,密码:(为空)->更改默认的数据库为:CCCS->测试数据源,测试成功,即DNS添加成功。

【C语言 关键函数】

1.SQLBindCol()函数具有六个参数,分别是

SQLRETURN SQLBindCol(
SQLHSTMT            StatementHandle,
SQLUSMALLINT     ColumnNumber,
SQLSMALLINT       TargetType,
SQLPOINTER        TargetValuePtr,
SQLINTEGER        BufferLength,
SQLLEN *              StrLen_or_Ind);

其中第一个参数是句柄,第二个参数是目标表中的列数(unsigned short),第三个是目标类型,第四个是储存数据库反馈信息(城市,纬度等)的字符串变量,第五个是第四个参数的长度(推荐使用strlen(string)测长度),第六个是啥玩意的缓冲区,为0即可。

2.SQLExecDirect()函数具有三个参数,分别是

SQLRETURN SQLExecDirect(
     SQLHSTMT     StatementHandle,
     SQLCHAR *    StatementText,
     SQLINTEGER   TextLength);

其中第一个参数是句柄,第二个参数是储存送给数据库的SQL语句的字符串变量,第三个函数是第二个参数的长度(推荐使用strlen(string)测长度)。

【源代码】

头文件functions.h附在主代码CCCS-insert.cpp和CCCS-select.cpp之后

【CCCS-insert.cpp】

#include "functions.h"

SQLHENV henv = SQL_NULL_HENV;     
SQLHDBC hdbc1 = SQL_NULL_HDBC;     
SQLHSTMT hstmt1 = SQL_NULL_HSTMT; 

/* 
cpp文件功能说明: 
1.数据库操作中的添加,修改,删除,主要体现在SQL语句上 
2.采用直接执行方式和参数预编译执行方式两种 
*/  
int main(){     
	RETCODE retcode;     
	UCHAR   szDSN[SQL_MAX_DSN_LENGTH+1]   =   "CCCS";     			//数据库名
	UCHAR	szUID[MAXNAME]   =   "sa";					//用户名
	UCHAR	szAuthStr[MAXNAME]   =   "";           				//密码
	char	sql[60] = "\0";                        				//插入时是用的sql语句的存放变量 
	char	sqlh1[26] = "insert into city values('"; 			//拼合字符串
	char	sqlh2[4] = "','";
	char	sqlh3[3] = "')";
	//UCHAR   pre_sql[31] = "insert into city values(?,?,?)";			 //预编译SQL语句  
	CityMsg * citymsg;		//城市信息

	//SQL语句  
	//1.连接数据源  
	//1.环境句柄  
	retcode   =   SQLAllocHandle   (SQL_HANDLE_ENV,   NULL,   &henv);     
	retcode   =   SQLSetEnvAttr(henv,   SQL_ATTR_ODBC_VERSION,     
		(SQLPOINTER)SQL_OV_ODBC3,     
		SQL_IS_INTEGER);     
	//2.连接句柄    
	retcode   =   SQLAllocHandle(SQL_HANDLE_DBC,   henv,   &hdbc1);     
	retcode   =   SQLConnect(hdbc1,   szDSN,   4,   szUID,   2,   szAuthStr,   0);  

	//判断连接是否成功  
	if ( (retcode   !=   SQL_SUCCESS)   &&   (retcode   !=   SQL_SUCCESS_WITH_INFO)   )   {       
		printf("连接失败!\n");  
	}   else   {     
		//2.创建并执行一条或多条SQL语句  
		/* 
		1.分配一个语句句柄(statement handle) 
		2.创建SQL语句 
		3.执行语句 
		4.销毁语句 
		*/  
		retcode   =   SQLAllocHandle(SQL_HANDLE_STMT,   hdbc1,   &hstmt1);     
		//第一种方式  
		//直接执行  
		//添加操作

		//打开文件
		citymsg = getCityMsg();
		citymsg = citymsg->next;
		while(citymsg->next != NULL){
			//拼合字符串
			strcpy(sql,sqlh1);
			strcat(sql,citymsg->city);
			strcat(sql,sqlh2);
			strcat(sql,citymsg->lat);
			strcat(sql,sqlh2);
			strcat(sql,citymsg->lon);
			strcat(sql,sqlh3);
			//执行sql语句
			//SQLExecDirect (hstmt1,(UCHAR *)sql,50); 
			//测试
			switch( SQLExecDirect (hstmt1,(UCHAR *)sql,strlen(sql))) { 
			case SQL_SUCCESS_WITH_INFO: { 
				printf("SQL_SUCCESS_WITH_INFO\n");
				break;
										} 
			case SQL_SUCCESS: { 
				printf("SQL_SUCCESS\n"); 
				break; 
							  }  
			case SQL_ERROR: {
				printf("SQL_ERROR\n"); 
				break; 
				} 
			default: 
				printf("else Return\n"); 

			} 
			//测试结束
			printf("%s\n",sql);//test
			//重新初始化sql语句存放变量
			strcpy(sql,sqlh1);
			//链表指向下一节点
			citymsg = citymsg->next;
		}

		//第二种方式  
		//绑定参数方式  
		/*char a[200]="bbb";  
		char b[200]="200";  
		char c[200]="200";
		SQLINTEGER   p   =   SQL_NTS;  
		//1预编译  
		SQLPrepare(hstmt1,pre_sql,31); //第三个参数与数组大小相同,而不是数据库列相同  
		//2绑定参数值  
		SQLBindParameter(hstmt1,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,200,0,&a,0,&p);  
		SQLBindParameter(hstmt1,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,200,0,&b,0,&p);  
		SQLBindParameter(hstmt1,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,200,0,&c,0,&p); 
		//3 执行  
		SQLExecute(hstmt1);*/  

		printf("操作成功!");  
		//释放语句句柄  
		SQLCloseCursor (hstmt1);  
		SQLFreeHandle (SQL_HANDLE_STMT, hstmt1);  

	}     
	//3.断开数据源  
	/* 
	1.断开与数据源的连接. 
	2.释放连接句柄. 
	3.释放环境句柄 (如果不再需要在这个环境中作更多连接) 
	*/  
	SQLDisconnect(hdbc1);      
	SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);     
	SQLFreeHandle(SQL_HANDLE_ENV, henv);     
	getchar();
	return 0;     
}     

【CCCS-select.cpp】

/*
China City Coord System

	SELECT
*/

#include "functions.h"

//定义查询方式宏
#define		SELECT_ALL		0
#define		SELECT_CITY		Still_Unsigned_Yet>_<|||
#define		SELECT_LAT_EXACT		1
#define		SELECT_LAT_SCOPE		2


SQLHENV henv = SQL_NULL_HENV;   
SQLHDBC hdbc1 = SQL_NULL_HDBC;   
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;   

/******************************************************

				全 部 查 询
					 
*******************************************************/
void selectAll(
	RETCODE retcode,
	char * sql,
	char * sqlh1,
	char * initialize)

{
	/*
	1.确认一个结果集是否可用。
	2.将结果集的列绑定在适当的变量上。
	3.取得行
	*/
	CityMsg citymsg;

	getchar();//储存在choose界面的回车字符,防止第一次翻页之前输出两倍的行数
	strcpy(sql,sqlh1);//拼合sql语句字符串
	SQLExecDirect (hstmt1,(UCHAR *)sql,strlen(sql));//对数据库发送select all语句
	//SQLBindCol(hstmt1, 1, SQL_C_CHAR, list, 5, 0);	//该函数对数据库发送语句
	SQLBindCol(hstmt1, 1, SQL_C_CHAR, citymsg.city, 10, 0);//该函数是数据库的反馈信息函数
	SQLBindCol(hstmt1, 2, SQL_C_CHAR, citymsg.lon, 11, 0);//第二个参数是目标表中的列号
	SQLBindCol(hstmt1, 3, SQL_C_CHAR, citymsg.lat, 11, 0);//第五个参数是传回的字符串长度
	do{
		retcode = SQLFetch(hstmt1);
		if(retcode == SQL_NO_DATA){
			break;
			}
		printf("%s		%s		%s\n",citymsg.city, citymsg.lon, citymsg.lat);
		static int n=1;//翻页计数器
		n++;
		if(n%20 == 0)	//每页20行
		{
			printf("\n【第%d页】",n/20);//页码
			getchar();	//按回车换页
		}
	}while(1);
	strcpy(sql,initialize);	//重新初始化字符串
	
	getchar();//结束标志,按一下回车
}


/******************************************************

				纬 度 精 确 查 询
					 
*******************************************************/
void selectByLat(
		char * sqlh1,
		char * sql,
		char * initialize)
{
	
	char sqlh5[10]="\0";
	CityMsg citymsg;

	getchar();
	printf("输入要查询的纬度:\n");
	printf("	例如:34.17\n");
	printf("北纬");
	gets(sqlh5);

	strcpy(sql,sqlh1);
	strcat(sql,"where latitude='北纬");
	strcat(sql,sqlh5);
	strcat(sql,"'");

	puts(sql);		//显示向数据库发送的sql语句
	SQLExecDirect (hstmt1,(UCHAR *)sql,strlen(sql));
	SQLBindCol(hstmt1, 1, SQL_C_CHAR, citymsg.city, 10, 0);//该函数是数据库的反馈信息函数
	SQLBindCol(hstmt1, 2, SQL_C_CHAR, citymsg.lon, 11, 0);//第二个参数是目标表中的列号
	SQLBindCol(hstmt1, 3, SQL_C_CHAR, citymsg.lat, 11, 0);//第五个参数是传回的字符串长度
	SQLFetch(hstmt1);
	printf("%s		%s		%s\n",citymsg.city, citymsg.lon, citymsg.lat);
	strcpy(sql,initialize);//重新初始化字符串
	
	getchar();//结束标志,按一下回车
}

/*
	查询SQLSERVER数据库,1.条件查询,2.直接查询全部
*/
int main(){       
	RETCODE retcode;     
	UCHAR   szDSN[SQL_MAX_DSN_LENGTH+1]   =   "CCCS";     //数据库名
	UCHAR	szUID[MAXNAME]   =   "sa";					//用户名
	UCHAR	szAuthStr[MAXNAME]   =   "";				//密码
	char	sql[57] = "\0";								//插入时是用的sql语句的存放变量 
	char	initialize[2] = "\0";						//初始化变量
	char	sqlh1[20] = "select * from city ";				//拼合字符串

	retcode   =   SQLAllocHandle   (SQL_HANDLE_ENV,   NULL,   &henv);   
	retcode   =   SQLSetEnvAttr(henv,   SQL_ATTR_ODBC_VERSION,   
				  (SQLPOINTER)SQL_OV_ODBC3,   
				  SQL_IS_INTEGER);    
	retcode   =   SQLAllocHandle(SQL_HANDLE_DBC,   henv,   &hdbc1);   
	//1.连接数据源
	retcode   =   SQLConnect(hdbc1,   szDSN,   4,   szUID,   2,   szAuthStr,   0);    
	if   (   (retcode   !=   SQL_SUCCESS)   &&   (retcode   !=   SQL_SUCCESS_WITH_INFO)   )   {   
		printf("连接失败!");
	}   else   {   
		//2.创建并执行一条或多条SQL语句
		/*
		1.分配一个语句句柄(statement handle)
		2.创建SQL语句
		3.执行语句
		4.销毁语句
		*/
		retcode   =   SQLAllocHandle(SQL_HANDLE_STMT,   hdbc1,   &hstmt1);   
		
		//第一种方式
		/*
		//直接执行
		SQLExecDirect (hstmt1,(UCHAR *)sql,strlen(sql));
		char list[5];
		SQLBindCol(hstmt1, 1, SQL_C_CHAR, list, 5, 0);
		SQLFetch(hstmt1);
		printf("%s\n",list);*/
			
		//第二种方式
		/*
		//绑定参数方式
		char a[200]="aaa";
		SQLINTEGER   p   =   SQL_NTS;
		//1.预编译
		SQLPrepare(hstmt1,sql2,35); //第三个参数与数组大小相同,而不是数据库列相同
		//2.绑定参数值
		SQLBindParameter(hstmt1,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,200,0,&a,0,&p);
		//3.执行
		SQLExecute(hstmt1);
		char list[5];
		SQLBindCol(hstmt1, 1, SQL_C_CHAR, list, 5, 0);
		SQLFetch(hstmt1);
		printf("%s\n",list);
		*/
		
		int choose;	//用户选择序号的储存变量

		while(1){
			printf("输入查询方式:\n");
			printf("	0.全部查询\n");
			printf("	1.纬度精确查询\n");
			printf("	2.纬度区间查询\n");
			printf("\n");
			scanf("%d",&choose);
			
			switch(choose){
				case SELECT_ALL:{
				//全部输出
					selectAll(retcode, sql, sqlh1, initialize);
					break;
				}
				case SELECT_LAT_EXACT:{
					//通过具体纬度查找
					selectByLat(sqlh1,sql,initialize);
					break;
				}
				case SELECT_LAT_SCOPE:{
				//通过纬度区间查找
				
				
				}
			}
		}
		
		//释放语句句柄
		SQLCloseCursor (hstmt1);
		SQLFreeHandle (SQL_HANDLE_STMT, hstmt1);
	
	}   
 
	//4.断开数据源
	/*
         1.断开与数据源的连接.
	 2.释放连接句柄.
	 3.释放环境句柄 (如果不再需要在这个环境中作更多连接)
    */
	SQLDisconnect(hdbc1);    
	SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);   
	SQLFreeHandle(SQL_HANDLE_ENV, henv);   
	getchar();
	getchar();
	return(0);   
}


【头文件functions.h】

#include <stdio.h>     
#include <string.h>     
#include <windows.h>     
#include <sql.h>     
#include <sqlext.h>     
#include <sqltypes.h>     
#include <odbcss.h> 

//存放城市及坐标的结构体
typedef struct CityMsg{
	char	city[50];	//城市	city
	char	lon[50];	//经度	longitude
	char	lat[50];	//纬度	latitude
	struct CityMsg	*next;		//下一节点
}CityMsg;

//函数声明
CityMsg * nextNood(CityMsg * );//构建链表 函数
CityMsg * getCityMsg();		//获取城市及坐标 函数

//构建链表
CityMsg * nextNood(CityMsg * oldCM)
{
	//尾插法
	CityMsg * newCM;
	newCM = (CityMsg *)malloc(sizeof(CityMsg));//为新节点开辟空间
	newCM->next = NULL;	//初始化新节点
	oldCM->next = newCM;
	return newCM;	//返回新节点
}

//获取城市及坐标
CityMsg * getCityMsg()
{
	CityMsg * head,		//头指针 
			* citymsg;	//存放城市及坐标的结构体
	FILE *fp;			//文件指针->存放城市及坐标的文件
	
	head = (CityMsg *)malloc(sizeof(CityMsg));//为头指针开辟空间
	citymsg = (CityMsg *)malloc(sizeof(CityMsg));//为首节点开辟空间
	head->next = citymsg;			//初始化头指针
	citymsg->next = NULL;			//初始化首节点

	fp = fopen("CityCoord.txt","rt");//尝试打开文件
	if(fp == NULL){					//若打不开,反馈信息并退出
		printf("Cannot Open This File,Press Any Key to Exit.\n");
		getchar();
		exit(1);
	}
	while(!feof(fp)){		//循环读取城市及坐标信息,直到文件末尾
		fscanf(fp,"%s %s %s",citymsg->city,citymsg->lon,citymsg->lat);//读入城市及坐标
		citymsg = nextNood(citymsg);								//开辟并指向下一节点
	}
	return head;
}

【参考资料】

C语言与SQL SERVER数据库

如何更改SQL Server 2008 登陆验证方式

SQLExecDirect Function - SQL Server msdn

抱歉!评论已关闭.