数据库程序(图书管理)

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

《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有你!

原文地址:https://www.cnblogs.com/cjwen/p/12267317.html