• 数据库程序(图书管理)


    大二上学期结束了。哎真是快的很啊,这学期感觉没学到啥东西也就一直没有写博客。

    《UML》学的迷迷糊糊,《计算机网络》也一般般,《数据库》考的贼撇。

    唉真是个垃圾还没有自知自明。

    我知道你根本不会在意我写的作业,看也不会看一眼。随便吧,我做我该做的。

    顺便就将上次布置的图书管理系统修改一下连上数据库吧。学完数据库还在抱怨啥也没学到,不知道怎么写数据库程序,

    刚开始做作业时一头雾水完全不知道怎么开始,怎么连接数据库。觉得太难了自己不可能完成,然后网上到处搜,

    慢慢的试,最终做出来后却又觉得 没什么意思也就那么回事自己还是个垃圾。

    进入正题

    1、创建数据库

      sql sever创建数据库 library,建表library

      

    2、导入数据

      建好表过后可以直接从excel表中导入到数据库中我们建的表里面。

      步骤:单击数据库右键->任务->导入数据.....然后按正常逻辑操作OK了

      导出表到excel也是一样的。

      

     然后查询一下:select * from library

    3、创建用户

      创建用户分配赋予权限。一般用户normal user只拥有读的权限,管理员拥有读和写的权限。

      我这里创建了普通用户 normaluser,密码111111.

      管理员用户名 cjw ,密码就不放出来了。

     

    4、配置ODBC数据源

      数据库建好了,用户角色权限分配好了,就可以配置数据源了。打开ODBC数据源管理程序。

     

     

     

     然后就默认下一步。。。

     测试一下数据源

     测试成功了。可以返回看一下我的library已经有了。

    5、连接数据库

    一、使用ODBC API建立数据库连接分为3部分:
      1.申请环境句柄,
      2.使用环境句柄申请连接句柄
      3.使用连接句柄连接数据库

    //1.申请环境句柄  
        SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
        SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
            (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
        //2.使用环境句柄申请连接句柄  
        SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
        //3.使用连接句柄连接数据库
        SQLRETURN SOL_RET = SQLConnect(hdbc, szDSN, SQL_NTS, szUID, SQL_NTS, szAuthStr, SQL_NTS);
    
        if ((SOL_RET != SQL_SUCCESS) && (SOL_RET != SQL_SUCCESS_WITH_INFO))
        {
            printf("连接失败!");
            exit(0);
        }

    6、执行SQL语句

    二、创建并执行一条或多条SQL语句
    1.分配一个语句句柄(statement handle)
    2.创建SQL语句
    3.执行语句
    4.销毁语句

        SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//每次循环分配一个句柄

    7、断开数据源

    三、断开数据源
    1.断开与数据源的连接.
    2.释放连接句柄.
    3.释放环境句柄 (如果不再需要在这个环境中作更多连接)

        SQLDisconnect(hdbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
        SQLFreeHandle(SQL_HANDLE_ENV, henv);

    8、检查SQL语句

    字符串拼接SQL语句时检查SQLstate状态,分析错误码。

    SQL State值 ->https://blog.csdn.net/qq_28289405/article/details/8113244

    通过SQLGetDiagRec和SQLGetDiagField检索诊断信息。

    用法详见->https://docs.microsoft.com/zh-cn/sql/odbc/reference/develop-app/using-sqlgetdiagrec-and-sqlgetdiagfield?view=sql-server-ver15

    //检查错误
    Status Check(char* sql,char* initialize)
    {
        SQLCHAR       SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
        SQLINTEGER    NativeError;
        SQLSMALLINT   i, MsgLen;
        SQLRETURN     rc1, rc2;
    
        // 执行SQL 
        rc1 = SQLExecDirect(hstmt, (UCHAR*)sql, SQL_NTS);
    
        //检查错误
        if ((rc1 == SQL_SUCCESS_WITH_INFO) || (rc1 == SQL_ERROR)) {
            SQLLEN numRecs = 0;
            SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
    
            // 获取SqlState
            i = 1;
            while (i <= numRecs && (rc2 = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,
                Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
                cout << Msg << endl;
                i++;
            }
            cout << "执行错误!" << endl;
            return FAIL;
        }
        else
            cout << "执行成功!" << endl << endl;
    
        strcpy(sql, initialize);        //重新初始化sql语句存放变量    
        return OK;
    }

    9、程序功能(增删改查.....)

    连接数据库,执行sql语句都可以了,就剩下正常的程序逻辑部分。这就不多说了。直接上代码。

    library.h

    #pragma once
    //autuor wen
    //2020.02.05
    #include <iostream>
    #include <iomanip>
    #include <stdio.h>
    #include <string> 
    #include <windows.h>     
    #include <sql.h>     
    #include <sqlext.h>     
    #include <sqltypes.h>     
    #include <odbcss.h> 
    
    using namespace std;
    
    
    /************************************************************************/
    /*   宏定义                                                             */
    /************************************************************************/
    
    
    //定义查询方式宏
    #define        ADD_INSERT                1
    #define        SELECT_ALL                2
    #define        SELECT_key              3
    #define     UPDATE                    4
    #define        DELETE                  5
    #define     COUNT                    6
    #define     ORDER                    7
    #define        EXIT                    0    
    
    #define Status  int
    #define OK 1
    #define FAIL 0
    
    
    /************************************************************************/
    /* 数据库变量                                                           */
    /************************************************************************/
    SQLHENV henv = SQL_NULL_HENV;         //数据库环境句柄 属于老大级别的
    SQLHDBC hdbc = SQL_NULL_HDBC;        //数据库连接句柄,老大以后就是他了,有了他数据库就连接上了
    SQLHSTMT hstmt = SQL_NULL_HSTMT;    //执行语句句柄,最终执行SQL于句的句柄
    
    
    
    typedef struct Book
    {
        char    ISBN[30]{' '};//初始化为空格
        char    bookname[20]{' '};
        char    author[10]{ ' ' };
        char    press[25]{ ' ' };//出版社
         
        char    price[10]{ ' ' };
        char    date[30]{ ' ' };
        int     num;//库存
    
        /*符号重载*/
        friend istream & operator >> (istream& i, Book& b)
        {
            cout << "请输入书号ISBN:"; i >> b.ISBN;
            cout << "请输入书名:"; i >> b.bookname;
            cout << "请输入作者:"; i >> b.author;
            cout << "请输入出版社:"; i >> b.press;
            cout << "请输入出版时间:"; i >> b.date;
            cout << "请输入价格:"; i >> b.price;
            cout << "请输入数量:"; i >> b.num;
            cout << "
    ";
            return i;
        }
    }Book;
    
    /************************************************************************/
    /* 函数声明                                                             */
    /************************************************************************/
    
    void insertBook(char* sql);
    void selectAll(char* sql);
    void selectBook(char* sql);
    void deleteBook(char* sql);    
    void updateBook(char* sql);
    void countBook(char* sql);
    void order(char* sql);
    Status Check(char* sql, char* initialize);//执行并检查sql语句
    
    /************************************************************************/
    /* 函数定义                                                            */
    /************************************************************************/
    
    char    initialize[2] = "";//初始化
    
    //检查错误
    Status Check(char* sql,char* initialize)
    {
        SQLCHAR       SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
        SQLINTEGER    NativeError;
        SQLSMALLINT   i, MsgLen;
        SQLRETURN     rc1, rc2;
    
        // 执行SQL 
        rc1 = SQLExecDirect(hstmt, (UCHAR*)sql, SQL_NTS);
    
        //检查错误
        if ((rc1 == SQL_SUCCESS_WITH_INFO) || (rc1 == SQL_ERROR)) {
            SQLLEN numRecs = 0;
            SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
    
            // 获取SqlState
            i = 1;
            while (i <= numRecs && (rc2 = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,
                Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
                cout << Msg << endl;
                i++;
            }
            cout << "执行错误!" << endl;
            return FAIL;
        }
        else
            cout << "执行成功!" << endl << endl;
    
        strcpy(sql, initialize);        //重新初始化sql语句存放变量    
        return OK;
    }
    
    //添加书籍
    void insertBook(char* sql)
    {
        char    sql_1[29] = "insert into library values('";         //拼合字符串所需的元素
        char    sql_2[4] = "','";
        char    sql_3[3] = "')";
    
        Book book;
    
        cout << "输入书籍信息:" << endl;
        cin >> book;
    
        //构造数据库语句  insert into library values(......)
        strcpy(sql, sql_1);        
        strcat(sql, book.ISBN);
        strcat(sql, sql_2);
        strcat(sql, book.bookname);
        strcat(sql, sql_2);
        strcat(sql, book.author);
        strcat(sql, sql_2);
        strcat(sql, book.press);
        strcat(sql, sql_2);
        strcat(sql, book.date);
        strcat(sql, sql_2);
        strcat(sql, book.price);
        strcat(sql, sql_2);
    
        //int 转化为 char*
        char num[10];
        _itoa(book.num, num, 10);//10表示十进制
    
        strcat(sql,num);
        strcat(sql, sql_3);    //insert into library values(......)
    
    
        Check(sql, initialize);//执行并检查
    }
    
    //全 部 查 询
    void selectAll(char* sql)
    {
        char* sql_1 = "select * from library ";                //拼合字符串
    
        Book book;
    
        strcpy(sql, sql_1);            /*构造数据库语句*/
    
    
        if (Check(sql, initialize) == 1) {//执行并检查
    
            cout << "ISBN" << setfill(' ') << setw(20) << "书名" << setfill(' ') << setw(19) << "作者" << setfill(' ') << setw(12)
                << "出版社" << setfill(' ') << setw(25) << "出版日期" << setfill(' ') << setw(11) << "价格" << setfill(' ') << setw(8)
                << "库存" << endl;
            while (SQLFetch(hstmt) != SQL_NO_DATA)
            {
                SQLGetData(hstmt, 1, SQL_C_CHAR, book.ISBN, 30, 0);//该函数是数据库的反馈信息函数
                SQLGetData(hstmt, 2, SQL_C_CHAR, book.bookname, 20, 0);//第五个参数是传回的字符串长度
                SQLGetData(hstmt, 3, SQL_C_CHAR, book.author, 10, 0);//第二个参数是目标表中的列号
                SQLGetData(hstmt, 4, SQL_C_CHAR, book.press, 25, 0);//SQL_CHAR
                SQLGetData(hstmt, 5, SQL_C_CHAR, book.date, 30, 0);
                SQLGetData(hstmt, 6, SQL_C_CHAR, book.price, 10, 0);
                SQLGetData(hstmt, 7, SQL_C_SLONG, &book.num, 30, 0);//SQL_INTEGER
    
                cout << book.ISBN << book.bookname << book.author << "  " << book.press << book.date
                    << "      " << book.price << " " << book.num << endl;
            }
    
        }
    }
    
    //关键字查询
    void selectBook(char* sql)
    {
        char* sql_1 = "select * from library ";                //拼合字符串
        char    sql_2[20] = "";
    
        Book book;
        cout << "1.按作者查询   2.按书名查询   3.按出版社查询  0.返回 " << endl;
        char oper;
        cin >> oper;
        if (oper == '1') {
            cout << "请输入作者姓名:" << endl;
            cin >> (sql_2);
    
            strcpy(sql, sql_1);//构造数据库语句
            strcat(sql, "where 作者='");
            strcat(sql, sql_2);
            strcat(sql, "'");
        }
        else if (oper == '2') {
            cout << "请输入书名:" << endl;
            cin >> (sql_2);
    
            strcpy(sql, sql_1);//构造数据库语句
            strcat(sql, "where 书名='");
            strcat(sql, sql_2);
            strcat(sql, "'");
        }
        else if (oper == '3') {
            cout << "请输入出版社:" << endl;
            cin >> (sql_2);
    
            strcpy(sql, sql_1);//构造数据库语句
            strcat(sql, "where 出版社='");
            strcat(sql, sql_2);
            strcat(sql, "'");
        }
        else if (oper == '0')//返回菜单
        {
            //刷新屏幕
            system("cls");
        }
    
        if (Check(sql, initialize) == 1) {//执行并检查
    
            cout << "ISBN" << setfill(' ') << setw(20) << "书名" << setfill(' ') << setw(19) << "作者" << setfill(' ') << setw(12)
                << "出版社" << setfill(' ') << setw(25) << "出版时间" << setfill(' ') << setw(11) << "价格" << setfill(' ') << setw(8)
                << "库存" << endl;
    
            while (SQLFetch(hstmt) != SQL_NO_DATA)
            {
                SQLGetData(hstmt, 1, SQL_C_CHAR, book.ISBN, 30, 0);//该函数是数据库的反馈信息函数
                SQLGetData(hstmt, 2, SQL_C_CHAR, book.bookname, 20, 0);//第五个参数是传回的字符串长度
                SQLGetData(hstmt, 3, SQL_C_CHAR, book.author, 10, 0);//第二个参数是目标表中的列号
                SQLGetData(hstmt, 4, SQL_C_CHAR, book.press, 25, 0);//SQL_CHAR
                SQLGetData(hstmt, 5, SQL_C_CHAR, book.date, 30, 0);
                SQLGetData(hstmt, 6, SQL_C_CHAR, book.price, 10, 0);
                SQLGetData(hstmt, 7, SQL_C_SLONG, &book.num, 30, 0);//SQL_INTEGER
    
                cout << book.ISBN << book.bookname << book.author << "  " << book.press << book.date
                    << "      " << book.price << " " << book.num << endl;
            }
        }
    }
    
    //删除书籍
    void deleteBook(char* sql)
    {
        char* sql_1 = "delete from library ";                //拼合字符串
        char    sql_2[20] = "";
    
        Book book;
    
        printf("输入删除的书名:
    ");
        cin >> sql_2;
    
        strcpy(sql, sql_1);//构造数据库语句
        strcat(sql, "where 书名='");
        strcat(sql, sql_2);
        strcat(sql, "'");
    
        Check(sql, initialize);//执行并检查
    
    }
    
    //更新书籍
    void updateBook(char* sql)
    {
        char* sql_1 = "update library set ";
        char sql_ISBN[20] = "";
        cout << "请输入需更新信息书籍的ISBN:" << endl;
        cin >> sql_ISBN;
        char* sql_2 = "='";
        cout << "请输入需要修改的属性: 例如 价格" << endl;
        char sql_key[20] = "";
        cin >> sql_key;
        cout << "请输入新的数据信息:";
        char sql_new[20] = "";
        cin >> sql_new;
        char* sql_3 = "' where ISBN='";
        char* sql_4 = "'";
    
        strcat(sql, sql_1);
        strcat(sql, sql_key);
        strcat(sql, sql_2);
        strcat(sql, sql_new);
        strcat(sql, sql_3);
        strcat(sql, sql_ISBN);
        strcat(sql, sql_4);
    
        Check(sql, initialize);//执行并检查
    
        strcpy(sql, initialize);//重新初始化字符串
    
    }
    
    //统计
    void countBook(char* sql)
    {
        char* sql_1 = "select ";
        char sql_2[20] = "";
        cout << "按关键字统计. 例如 作者" << endl ;
        cin >> sql_2;
        cout << endl;
        char* sql_3 = ",count(ISBN) 数量 from library group by ";
        
        strcat(sql, sql_1);
        strcat(sql, sql_2);
        strcat(sql, sql_3);
        strcat(sql, sql_2);
    
        if (Check(sql, initialize) == 1) {//执行并检查
    
            int num;
            char key[20] = "";
            cout << sql_2 << setfill(' ') << setw(15) << "数量" << endl;
            while (SQLFetch(hstmt) != SQL_NO_DATA)
            {
                SQLGetData(hstmt, 1, SQL_C_CHAR, key, 20, 0);//该函数是数据库的反馈信息函数
                SQLGetData(hstmt, 2, SQL_C_SLONG, &num, 10, 0);//SQL_INTEGER
                cout << key << num << endl;
            }
        }
    
    }
    
    //排序
    void order(char* sql)
    {
        char* sql_1 = "select * from library order by ";                //拼合字符串
        char    sql_2[20] = "";
    
        cout << "请输入排序关键字. 例如:价格" << endl;
        cin >> sql_2;
    
        strcat(sql, sql_1);
        strcat(sql, sql_2);
    
        Book book;
    
        if (Check(sql, initialize) == 1) {//执行并检查
    
            cout << "ISBN" << setfill(' ') << setw(20) << "书名" << setfill(' ') << setw(19) << "作者" << setfill(' ') << setw(12)
                << "出版社" << setfill(' ') << setw(25) << "出版时间" << setfill(' ') << setw(11) << "价格" << setfill(' ') << setw(8)
                << "库存" << endl;
            while (SQLFetch(hstmt) != SQL_NO_DATA)
            {
                SQLGetData(hstmt, 1, SQL_C_CHAR, book.ISBN, 30, 0);//该函数是数据库的反馈信息函数
                SQLGetData(hstmt, 2, SQL_C_CHAR, book.bookname, 20, 0);//第五个参数是传回的字符串长度
                SQLGetData(hstmt, 3, SQL_C_CHAR, book.author, 10, 0);//第二个参数是目标表中的列号
                SQLGetData(hstmt, 4, SQL_C_CHAR, book.press, 25, 0);//SQL_CHAR
                SQLGetData(hstmt, 5, SQL_C_CHAR, book.date, 30, 0);
                SQLGetData(hstmt, 6, SQL_C_CHAR, book.price, 10, 0);
                SQLGetData(hstmt, 7, SQL_C_SLONG, &book.num, 10, 0);//SQL_INTEGER
    
                cout << book.ISBN << book.bookname << book.author << "  " << book.press << book.date
                    << "      " << book.price << " " << book.num << endl;
            }
    
        }
    }
    View Code

    library.cpp

    //autuor wen
    //2020.02.05
    
    #include "library.h"
    
    
    
    int main()
    {
    
    
        /*
            一、使用ODBC API建立数据库连接分为3部分:
            1.申请环境句柄,
            2.使用环境句柄申请连接句柄
            3.使用连接句柄连接数据库
        */
    
        int login ;
        cout << "1.普通用户   2.管理员   0.退出" << endl;
        cin >> login;
        if (login == 1) {
            cout << "************************" << endl;
            cout << "*普通用户只拥有 读 权限*" << endl;
            cout << "************************" << endl;
            cout << "默认用户名:normaluser" << endl;
            cout << "密码:111111" << endl;
        }
        else if (login == 0)
            exit(0);
        UCHAR   szDSN[SQL_MAX_DSN_LENGTH + 1] = "library";         //数据库名
        UCHAR    szUID[MAXNAME];                             //用户名
        UCHAR    szAuthStr[MAXNAME];                 //密码
    
        cout << "输入用户名:";
        cin >> szUID;
        cout << "输入密码:";
        cin >> szAuthStr;
    
        cout << "正在登录....";
    
        //1.申请环境句柄  
        SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
        SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
            (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
        //2.使用环境句柄申请连接句柄  
        SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
        //3.使用连接句柄连接数据库
        SQLRETURN SOL_RET = SQLConnect(hdbc, szDSN, SQL_NTS, szUID, SQL_NTS, szAuthStr, SQL_NTS);
    
        if ((SOL_RET != SQL_SUCCESS) && (SOL_RET != SQL_SUCCESS_WITH_INFO))
        {
            printf("连接失败!");
            exit(0);
        }
    
    
        char    sql[61] = "";                                    //插入时是用的sql语句的存放变量     
    
    
        /*
            二、创建并执行一条或多条SQL语句
            1.分配一个语句句柄(statement handle)
            2.创建SQL语句
            3.执行语句
            4.销毁语句
        */
        cout << "登陆成功!" << endl;
    
        system("pause");
        system("cls");
    
        int choose;    //用户选择序号的储存变量
    
        while (1)
        {
            printf("图书管理系统:
    ");
            printf("    1.添加书籍
    ");
            printf("    2.全部查询
    ");
            printf("    3.关键字查询
    ");
            printf("    4.更新书籍
    ");
            printf("    5.删除书籍
    ");
            printf("    6.统计
    ");
            printf("    7.排序
    ");
            printf("    0.退出系统
    ");
            printf("
    ");
            cin >> choose;
    
            SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//每次循环分配一个句柄
    
            switch (choose)
            {
            case ADD_INSERT:
            {    //添加书籍
                insertBook(sql);
                system("pause");
                system("cls");
                break;
            }
            case SELECT_ALL:
            {
                //全部输出
                selectAll(sql);
                system("pause");
                system("cls");
                break;
            }
            case SELECT_key:
            {
                //按照书名、作者、出版社查询
                selectBook(sql);
                system("pause");
                system("cls");
                break;
            }
            case DELETE:
            {
                //删除书籍
                deleteBook(sql);
                system("pause");
                system("cls");
                break;
            }
            case UPDATE:
            {
                //更新数据
                updateBook(sql);
                system("pause");
                system("cls");
                break;
            }
            case COUNT:
            {
                //统计
                countBook(sql);
                system("pause");
                system("cls");
                break;
            }
            case ORDER:
            {
                //排序
                order(sql);
                system("pause");
                system("cls");
                break;
            }
            case EXIT:
            {
                exit(0);
            }
    
            }
            SQLCloseCursor(hstmt);
            SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
        }
    
    
        /*
            三、断开数据源
            1.断开与数据源的连接.
            2.释放连接句柄.
            3.释放环境句柄 (如果不再需要在这个环境中作更多连接)
        */
    
        SQLDisconnect(hdbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
        SQLFreeHandle(SQL_HANDLE_ENV, henv);
    
        system("pause");
    
        return(0);
    }
    View Code

    10、结果

    运行结果就懒得贴上来了。

     

    感谢2019有你!

  • 相关阅读:
    剑指 Offer II 001. 整数除法
    conda中如何恢复默认源
    conda中如何创建、查看、删除虚拟环境
    conda中如何移除指定的源
    conda 中如何移除默认源
    清华anaconda开源镜像下载站
    集群环境中使用sbatch提交命令测试
    第三章 消息摘要算法MD5SHAMAC
    第四章 dubbo源码解析目录
    第二章 Base64与URLBase64
  • 原文地址:https://www.cnblogs.com/cjwen/p/12267317.html
Copyright © 2020-2023  润新知