最近在做软件工程的课程设计,我的题目是做一个windows小程序,需要用到数据库,sqlite很便捷易用(只有1-2m),可以实现大部分的数据库功能,所以我决定使用sqlite。看了很多网上的教程,在写程序的过程中也走了很多的弯路,现在软件已经基本完成,所以写下这篇博客,当是作为备份,以免以后忘记,也是取之于网络,回馈于网络。
一、编译静态链接库sqlite3.lib
方法一:
1. 官网下载 http://www.sqlite.org/download.html
解压得到sqlite3.h和sqlite3.c文件。
2. 打开vs2015 ,新建->项目->Visual C++->Win32->Win32 项目,项目名称输入sqlite3,点击下一步,项目属性->配置属性->常规->静态库(.lib),C/C++ ->预编译头->不使用预编译头。
3. 将sqlite3.c,sqlite3.h两个文件复制到这个工程目录下,在项目中将这两个文件添加到对应的头文件和源文件里,直接build,然后在Debug下就可以得到sqlite3.lib。
但是用这个方法得到的sqlite3.lib用release编译生成exe文件时会出现 "无法识别标识符 "imps_rand_s"的错误,基本找不到解决方案,搞得很头疼。
然后网上找到另一种方案,写得很详细了,生成的sqlite3.lib,没有出现上述问题。现在把学习的网址发出来,存为记录:
https://www.cnblogs.com/imoon/archive/2012/11/30/2796726.html
二、静态链接库sqlite3.lib的使用
1. 将sqlite3.h、sqlite3.lib复制到要使用数据库的工程目录下,项目属性->链接器->输入->附加依赖项->填上"sqlite3.lib".
2. 在项目的头文件中导入工程目录下的sqlite3.h, 在工程下#include "sqlite3.h".
现在已经能够使用sqlite的功能了。但是要实现动态的添加查找还是有些不方便,所以我网上查找了一些资料,结合资料封装了一些适合我这个项目的函数,下面把代码粘贴出来
三、 在使用的过程中发现的一些问题:
1. NOT NULL 约束并没有起作用。
2. 由于sqlite数据库使用的是UTF-8编码方式,使用Unicode编码会导致字符串格式错误,所以会乱码。
结构体:
1 #ifndef _INFO_H_ 2 #define _INFO_H_ 3 4 typedef struct _INFO_ 5 { 6 CString account; 7 CString password; 8 CString rema; 9 }Info; 10 #endif
头文件
1 #include "sqlite3.h" 2 #include "INFO.h" 3 class sqliteHandle 4 { 5 private: 6 sqlite3 *db; 7 public: 8 sqliteHandle(); 9 ~sqliteHandle(); 10 //创建数据库 11 bool sqlite3OpenDb(); 12 //创建数据库表 13 bool sqlite3CreateTable(); 14 //插入数据 15 bool sqlite3InsertData(CString a, CString b, CString c); 16 //删除数据 17 bool sqlite3DeleteData(CString &a); 18 //修改数据 19 bool sqlite3ChangeData(CString &a, CString &b, CString &c); 20 //查询数据 21 bool sqlite3SelectData(CString a, CArray<Info,Info&>& arr); 22 };
源文件
1 #include "stdafx.h" 2 #include "afxdialogex.h" 3 #include "sqlitehandle.h" 4 5 sqliteHandle::sqliteHandle() 6 { 7 db=NULL; 8 } 9 sqliteHandle::~sqliteHandle() 10 { 11 //关闭数据库 12 sqlite3_close(db); 13 } 14 //创建数据库 15 bool sqliteHandle::sqlite3OpenDb() 16 { 17 //打开数据库 18 int result = sqlite3_open("password.db", &db); 19 if (result != SQLITE_OK) 20 { 21 sqlite3_close(db); 22 return false; 23 } 24 return true; 25 } 26 27 //创建数据库表 28 bool sqliteHandle::sqlite3CreateTable() 29 { 30 sqlite3OpenDb(); 31 char *zErrMsg = 0; 32 int rc; 33 34 char* createTableETag = "CREATE TABLE BOOK5(" 35 "ACCOUNT TEXT PRIMARY KEY NOT NULL," \ 36 "PASSWORD TEXT NOT NULL," \ 37 "REMA TEXT ) ;"; 38 39 rc = sqlite3_exec(db, createTableETag, 0, 0, &zErrMsg); 40 if (rc != SQLITE_OK) { 41 sqlite3_free(zErrMsg);//释放存放错误信息的内存空间,sqlite3_errmsg 返回的errmsg必须用此函数释放 42 sqlite3_close(db); 43 return false; 44 } 45 sqlite3_free(zErrMsg); 46 sqlite3_close(db); 47 return true; 48 } 49 50 //插入数据 51 bool sqliteHandle::sqlite3InsertData(CString a,CString b,CString c) 52 { 53 sqlite3OpenDb(); 54 CString insertSQL=_T("INSERT INTO BOOK5(ACCOUNT,PASSWORD,REMA) VALUES("); 55 56 insertSQL += "'"; 57 insertSQL += a; 58 insertSQL += "','"; 59 insertSQL += b; 60 insertSQL += "','"; 61 insertSQL += c; 62 insertSQL += "');" ; 63 64 int len = WideCharToMultiByte(CP_UTF8, 0, insertSQL, insertSQL.GetLength(), NULL, 0, NULL, NULL); 65 char* pa = new char[len + 1]; 66 len = WideCharToMultiByte(CP_UTF8, 0, insertSQL, insertSQL.GetLength(), pa, len + 1, NULL, NULL); 67 pa[len] = 0; 68 69 char* errmsg; 70 int rc; 71 rc = sqlite3_exec(db, pa, NULL, NULL, &errmsg); 72 73 if (rc != SQLITE_OK) 74 { 75 sqlite3_free(errmsg); 76 sqlite3_close(db); 77 return false; 78 } 79 sqlite3_free(errmsg); 80 sqlite3_close(db); 81 return true; 82 } 83 84 85 //删除数据 86 bool sqliteHandle::sqlite3DeleteData(CString &a) 87 { 88 sqlite3OpenDb(); 89 CString deleteSQL =_T( "DELETE FROM BOOK5 WHERE ACCOUNT = '"); 90 91 deleteSQL += a; 92 deleteSQL += "'"; 93 94 int len = WideCharToMultiByte(CP_UTF8, 0, deleteSQL, deleteSQL.GetLength(), NULL, 0, NULL, NULL); 95 char* pa = new char[len + 1]; 96 len = WideCharToMultiByte(CP_UTF8, 0, deleteSQL, deleteSQL.GetLength(), pa, len + 1, NULL, NULL); 97 pa[len] = 0; 98 99 char* errmsg; 100 if (sqlite3_exec(db, pa , NULL, NULL, &errmsg) != SQLITE_OK) 101 { 102 sqlite3_free(errmsg); 103 sqlite3_close(db); 104 return false; 105 } 106 sqlite3_free(errmsg); 107 sqlite3_close(db); 108 return true; 109 } 110 111 //修改数据 112 bool sqliteHandle::sqlite3ChangeData(CString &a, CString &b, CString &c) 113 { 114 sqlite3OpenDb(); 115 116 CString changeSQL = _T("UPDATE BOOK5 SET PASSWORD = '"); 117 118 changeSQL += b; 119 changeSQL += "',REMA='"; 120 changeSQL += c; 121 changeSQL += "' WHERE ACCOUNT='"; 122 changeSQL += a; 123 changeSQL += "'"; 124 125 int len = WideCharToMultiByte(CP_UTF8, 0, changeSQL, changeSQL.GetLength(), NULL, 0, NULL, NULL); 126 char* pa = new char[len + 1]; 127 len = WideCharToMultiByte(CP_UTF8, 0, changeSQL, changeSQL.GetLength(), pa, len + 1, NULL, NULL); 128 pa[len] = 0; 129 130 char* errmsg; 131 if (sqlite3_exec(db, pa, NULL, NULL, &errmsg) != SQLITE_OK) 132 { 133 sqlite3_free(errmsg); 134 sqlite3_close(db); 135 return false; 136 } 137 sqlite3_free(errmsg); 138 sqlite3_close(db); 139 return true; 140 } 141 142 //查询数据 143 bool sqliteHandle::sqlite3SelectData(CString a, CArray<Info, Info&>& arr) 144 { 145 sqlite3OpenDb(); 146 CString selectSQL = _T("SELECT * FROM BOOK5 WHERE ACCOUNT LIKE '"); 147 selectSQL += a; 148 selectSQL += "%';"; 149 150 int len = WideCharToMultiByte(CP_UTF8, 0, selectSQL, selectSQL.GetLength(), NULL, 0, NULL, NULL); 151 char* pa = new char[len + 1]; 152 len = WideCharToMultiByte(CP_UTF8, 0, selectSQL, selectSQL.GetLength(), pa, len + 1, NULL, NULL); 153 pa[len] = 0; 154 155 sqlite3_stmt *stmt; 156 int rc = sqlite3_prepare_v2(db, pa, -1, &stmt, 0); 157 if (rc != SQLITE_OK) 158 { 159 sqlite3_finalize(stmt); 160 sqlite3_close(db); 161 return false; 162 } 163 int rb = sqlite3_step(stmt); 164 while (rb == SQLITE_ROW) 165 { 166 Info info; 167 info.account = sqlite3_column_text(stmt, 0);//取值第一列 168 info.password = sqlite3_column_text(stmt, 1); 169 info.rema = sqlite3_column_text(stmt, 2); 170 arr.Add(info); 171 rb = sqlite3_step(stmt); 172 173 } 174 sqlite3_finalize(stmt); 175 sqlite3_close(db); 176 return true; 177 }