因为最近要用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; }
相关源码已上传git:Github.com/xusongqi/CCCS
C语言与SQL SERVER数据库
如何更改SQL Server 2008 登陆验证方式
SQLExecDirect Function - SQL Server msdn