大二上学期结束了。哎真是快的很啊,这学期感觉没学到啥东西也就一直没有写博客。
《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检索诊断信息。
//检查错误 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 << "\n"; 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] = "\0";//初始化 //检查错误 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] = "\0"; 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] = "\0"; Book book; printf("输入删除的书名:\n"); 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] = "\0"; cout << "请输入需更新信息书籍的ISBN:" << endl; cin >> sql_ISBN; char* sql_2 = "='"; cout << "请输入需要修改的属性: 例如 价格" << endl; char sql_key[20] = "\0"; cin >> sql_key; cout << "请输入新的数据信息:"; char sql_new[20] = "\0"; 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] = "\0"; 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] = "\0"; 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] = "\0"; 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; } } }
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] = "\0"; //插入时是用的sql语句的存放变量 /* 二、创建并执行一条或多条SQL语句 1.分配一个语句句柄(statement handle) 2.创建SQL语句 3.执行语句 4.销毁语句 */ cout << "登陆成功!" << endl; system("pause"); system("cls"); int choose; //用户选择序号的储存变量 while (1) { printf("图书管理系统:\n"); printf(" 1.添加书籍\n"); printf(" 2.全部查询\n"); printf(" 3.关键字查询\n"); printf(" 4.更新书籍\n"); printf(" 5.删除书籍\n"); printf(" 6.统计\n"); printf(" 7.排序\n"); printf(" 0.退出系统\n"); printf("\n"); 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); }
10、结果
运行结果就懒得贴上来了。
感谢2019有你!