C++通过ODBC方式连接数据库SQLServer及增删查改操作【图书借阅系统为例】

C++通过ODBC方式连接数据库SQLServer及增删查改操作【图书借阅系统为例】

文章目录

前言

一、ODBC如何配置

二、SQL Server如何设置账号密码

三、C++连接数据库以及增删查改操作的代码实现

四、源代码

前言

​ 大二学习了《数据库原理及应用》,期末做课程设计。因为大一学的C++,所以决定用C++写。这里以《图书借阅系统》为例,该系统做的并不是很完整,但已经能够体现C++如何对数据库SQL Server进行增删查改操作。以下是本人的学习心得,仅供学习参考。

一、ODBC如何配置

ODBC如何配置

二、SQL Server如何设置账号密码

SQL Server如何设置账号密码

三、C++连接数据库以及增删查改操作的代码实现

1.编程环境:Visual Studio 2019

2.基本原理

想必大家都做过C++的课程设计吧,C++课程设计的数据一般都是以文件的方式存储的。而数据库的课程设计则是以数据库的方式来存储数据的。用C++代码实现对数据库的操作,其实就是在C++环境(visual studio)中输入一段SQL代码(用字符串方式存放),然后调用特定的函数来执行该SQL代码,最后再将结果返回到visual studio中,具体步骤如下:

1、第一步:申请句柄。

ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);

2、第二步:定义、拼接想要执行的SQL语句(以插入操作代码为例)。如果有需要手动输入的地方,则单独定义出来,最后再拼接成一句完整的SQL语句,最后才能执行。比如我想插入一本图书,但是图书的编号、名称、数量都需要我自己手动输入,那么就需要单独定义、cin图书的编号、名称、数量字符串。最后拼接成完整的一句SQL语句:insert into Books values (‘001’,‘计算机网络’,10)。

    string str1 = "use JYXT";//第一句要执行的SQL语句
    string str2 = "insert into Books values ('";//第二句要执行的SQL语句
    cout << "请依次输入图书编号、图书名称、图书数量" << endl;
    string Bno, Bname, Bsum;
    cin >> Bno >> Bname >> Bsum;
    string str3=str2 + Bno + "','" + Bname + "'," + Bsum + ")";

3、第三步:调用函数执行SQL语句(以插入操作代码为例)。如果ret返回0或1则说明该语句执行成功,否则执行失败。失败原因可能是,你的SQL语句错误(记得先执行use[数据库]这句哦)。这里建议你先在SQL Server执行好,再到visual studio中拼接,注意是英文符号!!!

    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);//执行str1这句SQL语句use JYXT
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);//执行str3这句SQL语句insert into Books values ('Bno','Bname',Bsum)
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        cout << "书籍上架成功!" << endl;
    }
    else {
        cout << "书籍上架失败!" << endl;
    }

4.第四步:将SQL语句执行后的结果返回(以查询操作代码为例)。比如你想查询一本图书的基本信息,在调用完SQL语句后,你就需要将数据存放下来,然后再打印在黑框中,具体细节都在代码注释里啦(注意规律队形哦)。

if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
    {
        SQLCHAR str1[10], str2[12], str3[10];//用来存放从数据库获取的列信息,你有几列就定义几个变量
        SQLINTEGER len_str1, len_str2, len_str3;//字符串对应长度,你有几列就定义几个变量
        //printf("%s\t%s\t%s\n", "书籍编号", "书籍名称", "数量");
        cout << "编号" << "    " << "书籍名称" << "       " << "书籍数量" << endl;
        while (SQLFetch(hstmt) != SQL_NO_DATA)
        {
            //你有几列就调用几次SQLGetData函数,注意找规律哦
            SQLGetData(hstmt, 1, SQL_C_CHAR, str1, 10, &len_str1);   //获取第一列数据
            SQLGetData(hstmt, 2, SQL_C_CHAR, str2, 12, &len_str2);   //获取第二列数据
            SQLGetData(hstmt, 3, SQL_C_CHAR, str3, 10, &len_str3);   //获取第三列数据
            printf("%s\t%s\t%s\n", str1,str2, str3);
        }
    }

3.头文件及全局变量的定义

#undef UNICODE
#undef _UNICODE
#include<Windows.h>
#include <sql.h> 
#include <sqlext.h> 
#include<sqltypes.h>
#include <iostream>
#include<string>
#include <iomanip>
using namespace std;

//定义全局变量
SQLRETURN ret = NULL;//返回信息
SQLHENV henv = NULL;//环境句柄
SQLHDBC hdbc = NULL;//连接句柄
SQLHSTMT hstmt = NULL;//语句句柄

4.数据库连接函数

具体代码实现如下:

void connect()//数据库连接函数
{
    SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);//申请环境
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);//设置环境
    SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);//申请数据库连接
    ret = SQLConnect(hdbc, (SQLTCHAR*)("SQL SERVER"), SQL_NTS, (SQLTCHAR*)("sa"), SQL_NTS, (SQLTCHAR*)("72580."), SQL_NTS);
    if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO))
    {
        cout << "数据库连接成功!" << endl;
    }
    else
    {
        cout << "数据库连接失败!" << endl;
    }
}

你们要把SQLConnect函数的几个参数修改一下:

1.“SQL SERVER”,要改成你所设置的ODBC数据源名称,如果不知道ODBC数据源名称是什么,具体可看我配置ODBC的文章。

2."sa"改成你SQL Server 的登录名。

3."72580."改成你SQL Server的登录密码。

5.插入操作(insert)

这里以上架书籍为例,即在表Books中插入一条记录,具体实现代码如下:

void insert_book()
{
    // sql语句:insert into Books values ('001','计算机网络',10)
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";//第一句要执行的SQL语句
    string str2 = "insert into Books values ('";//第二句要执行的SQL语句
    cout << "请依次输入图书编号、图书名称、图书数量" << endl;
    string Bno, Bname, Bsum;
    cin >> Bno >> Bname >> Bsum;
    string str3=str2 + Bno + "','" + Bname + "'," + Bsum + ")";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        cout << "书籍上架成功!" << endl;
    }
    else {
        cout << "书籍上架失败!" << endl;
    }
    free();
}

6.删除操作(delete)

这里以下架书籍为例,即删除表Books中的一条记录,具体实现代码如下:

void delete_book()
{
    //sql语句:delete Books where Bname='计算机网络'
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "delete Books where Bname='";
    cout << "请下输入架书籍名称" << endl;
    string Bname;
    cin >> Bname;
    string str3 = str2 + Bname + "'";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        cout << "书籍下架成功!" << endl;
    }
    else {
        cout << "书籍下架失败!" << endl;
    }
    free();
}

7.修改操作(update)

这里以借书为例,具体借书函数代码实现如下:

void borrow_book()
{
    cout << "请输入你的学号" << endl;
    string Sno;
    cin >> Sno;
    cout << "请输入你想借的书籍名称" << endl;
    string Bname;
    cin >> Bname;
    if (getbsum(Bname) > 0)//为了判断是否能借书,这里自定义了一个能够获取图书数量bsum的函数getbsum(string bname)
    {
        ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
        string str1 = "use JYXT";
        string str2 = "update Books set Bsum-=1 where Bname='";
        string str3 = str2 + Bname + "'";
        string str4 = "declare @a char(6) select @a=Bno from Books where Bname= '";
        string str5 = str4 + Bname + "' insert into Record values ('" + Sno + "','借书',getdate(),@a)";
        ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
        ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
        ret = SQLExecDirect(hstmt, (SQLCHAR*)str5.c_str(), SQL_NTS);
        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            cout << "借书成功!" << endl;
        else
            cout << "借书失败!" << endl;
    }
    else
        cout << "此书库存不足,无法借阅" << endl;
    free();
}

8.查询操作(select)

这里以查找书籍信息为例,具体实现代码如下:

void query_book()
{
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "select *from Books where Bname='";
    cout << "请输入书名" << endl;
    string Bname;
    cin >> Bname;
    string str3 = str2 + Bname + "'";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
    {
        SQLCHAR str1[10], str2[12], str3[10];//用来存放从数据库获取的列信息,你有几列就定义几个变量
        SQLINTEGER len_str1, len_str2, len_str3;//字符串对应长度,你有几列就定义几个变量
        //printf("%s\t%s\t%s\n", "书籍编号", "书籍名称", "数量");
        cout << "编号" << "    " << "书籍名称" << "       " << "书籍数量" << endl;
        while (SQLFetch(hstmt) != SQL_NO_DATA)
        {
            //你有几列就调用几次SQLGetData函数,注意找规律哦
            SQLGetData(hstmt, 1, SQL_C_CHAR, str1, 10, &len_str1);   //获取第一列数据
            SQLGetData(hstmt, 2, SQL_C_CHAR, str2, 12, &len_str2);   //获取第二列数据
            SQLGetData(hstmt, 3, SQL_C_CHAR, str3, 10, &len_str3);   //获取第三列数据
            printf("%s\t%s\t%s\n", str1,str2, str3);
        }
    }
    free();
}

四、 源代码

#undef UNICODE
#undef _UNICODE
#include<Windows.h>
#include <sql.h> 
#include <sqlext.h> 
#include<sqltypes.h>
#include <iostream>
#include<string>
#include <iomanip>
using namespace std;

//定义全局变量
SQLRETURN ret = NULL;//返回信息
SQLHENV henv = NULL;//环境句柄
SQLHDBC hdbc = NULL;//连接句柄
SQLHSTMT hstmt = NULL;//语句句柄

//释放空间
void free()
{
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);//释放语句
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);//释放连接
    SQLFreeHandle(SQL_HANDLE_ENV, henv);//释放环境
}

//连接数据库
void connect()//数据库连接函数
{
    SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);//申请环境
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);//设置环境
    SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);//申请数据库连接
    ret = SQLConnect(hdbc, (SQLTCHAR*)("SQL SERVER"), SQL_NTS, (SQLTCHAR*)("sa"), SQL_NTS, (SQLTCHAR*)("72580."), SQL_NTS);
    if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO))
    {
        cout << "数据库连接成功!" << endl;
    }
    else
    {
        cout << "数据库连接失败!" << endl;
    }
}

//获取书籍数量
int getbsum(string bname)
{
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string sql = "use JYXT";
    string sql2 = "select bsum from Books where Bname='";
    string str = sql2 + bname + "'";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
    {
        int a=0;
        string str1;
        SQLINTEGER len_str1;
        while (SQLFetch(hstmt) != SQL_NO_DATA)
        {
            SQLGetData(hstmt, 1, SQL_C_CHAR, (SQLCHAR*)str1.c_str(), 10, &len_str1);   //获取第一列数据
            a = atoi(str1.c_str());
        }
        free();
        return a;
    }
}

//借书(删除)
void borrow_book()
{
    cout << "请输入你的学号" << endl;
    string Sno;
    cin >> Sno;
    cout << "请输入你想借的书籍名称" << endl;
    string Bname;
    cin >> Bname;
    if (getbsum(Bname) > 0)
    {
        ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
        string str1 = "use JYXT";
        string str2 = "update Books set Bsum-=1 where Bname='";
        string str3 = str2 + Bname + "'";
        string str4 = "declare @a char(6) select @a=Bno from Books where Bname= '";
        string str5 = str4 + Bname + "' insert into Record values ('" + Sno + "','借书',getdate(),@a)";
        ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
        ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
        ret = SQLExecDirect(hstmt, (SQLCHAR*)str5.c_str(), SQL_NTS);
        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            cout << "借书成功!" << endl;
        else
            cout << "借书失败!" << endl;
    }
    else
        cout << "此书库存不足,无法借阅" << endl;
    free();
}

//还书(增加)
void return_book()
{
    cout << "请输入你的学号" << endl;
    string Sno;
    cin >> Sno;
    cout << "请输入你要还的书籍名称" << endl;
    string Bname;
    cin >> Bname;
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "update Books set Bsum+=1 where Bname='";
    string str3 = str2 + Bname + "'";
    string str4 = "declare @a char(6) select @a=Bno from Books where Bname= '";
    string str5 = str4 + Bname + "' insert into Record values ('" + Sno + "','还书',getdate(),@a)";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str5.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
        cout << "还书成功!" << endl;
    else
        cout << "还书失败!" << endl;
    free();
}

//查询学生借阅信息(查找)
void print_br()
{
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "SELECT*FROM Record where Sno='";
    cout << "请输入学号" << endl;
    string Sno;
    cin >> Sno;
    string str3 = str2 + Sno + "'";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
    {
        SQLCHAR str1[10], str2[12], str3[20], str4[20];
        SQLINTEGER len_str1, len_str2, len_str3, len_str4;
        //printf("%s\t%s\t%s\n", "书籍编号", "书籍名称", "数量");
        cout << "学号" << "    " << "操作" << "    " << "操作时间" << "                图书编号"<<endl;
        while (SQLFetch(hstmt) != SQL_NO_DATA)
        {
            SQLGetData(hstmt, 1, SQL_C_CHAR, str1, 10, &len_str1);   //获取第一列数据
            SQLGetData(hstmt, 2, SQL_C_CHAR, str2, 12, &len_str2);
            SQLGetData(hstmt, 3, SQL_C_CHAR, str3, 20, &len_str3);
            SQLGetData(hstmt, 4, SQL_C_CHAR, str4, 20, &len_str4);
            printf("%s\t%s\t%s\t%s\n", str1, str2, str3, str4);
        }
    }
    free();
}

//查询书籍信息(查找)
void query_book()
{
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "select *from Books where Bname='";
    cout << "请输入书名" << endl;
    string Bname;
    cin >> Bname;
    string str3 = str2 + Bname + "'";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
    {
        SQLCHAR str1[10], str2[12], str3[10];
        SQLINTEGER len_str1, len_str2, len_str3;
        //printf("%s\t%s\t%s\n", "书籍编号", "书籍名称", "数量");
        cout << "编号" << "    " << "书籍名称" << "       " << "书籍数量" << endl;
        while (SQLFetch(hstmt) != SQL_NO_DATA)
        {
            SQLGetData(hstmt, 1, SQL_C_CHAR, str1, 10, &len_str1);   //获取第一列数据
            SQLGetData(hstmt, 2, SQL_C_CHAR, str2, 12, &len_str2);
            SQLGetData(hstmt, 3, SQL_C_CHAR, str3, 10, &len_str3);

            printf("%s\t%s\t%s\n", str1,str2, str3);
        }
    }
    free();
}

//上架书籍
void insert_book()
{
    //insert into Books values ('006','计算机网络',10)
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "insert into Books values ('";
    cout << "请依次输入图书编号、图书名称、图书数量" << endl;
    string Bno, Bname, Bsum;
    cin >> Bno >> Bname >> Bsum;
    string str3=str2 + Bno + "','" + Bname + "'," + Bsum + ")";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        cout << "书籍上架成功!" << endl;
    }
    else {
        cout << "书籍上架失败!" << endl;
    }
    free();
}

//下架书籍
void delete_book()
{
    //delete Books where Bname='计算机网络'
    ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄
    string str1 = "use JYXT";
    string str2 = "delete Books where Bname='";
    cout << "请下输入架书籍名称" << endl;
    string Bname;
    cin >> Bname;
    string str3 = str2 + Bname + "'";
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str1.c_str(), SQL_NTS);
    ret = SQLExecDirect(hstmt, (SQLCHAR*)str3.c_str(), SQL_NTS);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        cout << "书籍下架成功!" << endl;
    }
    else {
        cout << "书籍下架失败!" << endl;
    }
    free();
}

int main()
{
    return 0;
}
  • 5
    点赞
  • 5
    评论
  • 18
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页

打赏作者

一只平平无奇

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值