您好,登錄后才能下訂單哦!
這篇文章主要介紹“SQLite3數據庫如何使用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“SQLite3數據庫如何使用”文章能幫助大家解決問題。
SQLite是一種用C語言實現的的SQL數據庫
它的特點有:輕量級、快速、獨立、高可靠性、跨平臺
它廣泛應用在全世界范圍內的手機電腦應用的內建數據庫
SQLite因為其采用文件存儲,且容易移植。在嵌入式中應用非常廣泛,可以說是嵌入式業務開發的必學庫
這次先講一下怎么獲取源碼和使用
在官網找到sqlite-autoconf-3410200.tar.gz
文件下載,如下
wget https://www.sqlite.org/2023/sqlite-autoconf-3410200.tar.gz tar -zxvf sqlite-autoconf-3410200
下載后解壓,會發現里面很多其他的文件。其中,tea目錄是(Tcl Extension Architecture)可以不用管
主要看里面的c文件和h文件,所以我們把源代碼放到另一個目錄
在工程目錄創建一個目錄lib/sqlite3,然后刪除解壓后的源碼目錄
cp sqlite-autoconf-3410200/*.c lib/sqlite3/ cp sqlite-autoconf-3410200/*.h lib/sqlite3/ rm -r sqlite-autoconf-3410200
將需要的頭文件和源文件拷貝進去
有點強的是sqlite3.c文件的大小居然有8.3M
完成后目錄樹大概應該是這個樣子的
├── build ├── CMakeLists.txt ├── main.cpp └── lib └── sqlite3 ├── shell.c ├── sqlite3.c ├── sqlite3ext.h ├── sqlite3.h └── sqlite3rc.h
其中shell.c是對應的命令行文件,我們可以不用添加。
所以CMakeLists.txt我們可以這么寫
cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(useSQLite LANGUAGES C CXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread") add_executable(useSQLite main.cpp) # lib sqlite3 include_directories(lib/sqlite3) add_library(sqlite3 STATIC lib/sqlite3/sqlite3.c) target_link_libraries(sqlite3 dl) # target_link_libraries(useSQLite sqlite3) # sqlite3-cli add_executable(SQLite3-cli lib/sqlite3/shell.c) target_link_libraries(SQLite3-cli sqlite3)
添加main.cpp
文件如下
#include <iostream> #include <stdio.h> #include <sqlite3.h> static int callback(void *NotUsed, int argc, char **argv, char **azColName) { int i; for (i = 0; i < argc; i++) { printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); } printf("\n"); return 0; } int main(int argc, char **argv) { sqlite3 *db; char *zErrMsg = 0; int rc; if (argc != 3) { fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]); return(1); } rc = sqlite3_open(argv[1], &db); if (rc) { fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); return(1); } rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg); if (rc!=SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } sqlite3_close(db); return 0; }
簡單講一下這個源碼,其實就是打開一個數據庫文件執行一條指令
看上面的Usage: %s DATABASE SQL-STATEMENT\n就知道,參數是帶引號的SQL語句
里面調用了三個庫函數sqlite3_open()
、sqlite3_exec()
和sqlite3_close()
分別是打開SQLite數據庫文件,執行第二個參數給的命令,關閉SQLite數據庫文件
因為SQLite是本地文件存儲和讀寫的,所以使用起來還是比較簡單的,不用考慮太多網絡的問題。
mkdir build && cd build cmake .. && make
編譯出來有兩個可執行文件,一個是useSQLite一個是SQLite3-cli。
useSQLite就是我們上面說的main.cpp的內容。
SQLite3-cli是官方給的一個命令行執行SQL的程序,可以用它去查一些數據什么的
但是不是很建議用這個,建議用Ubuntu安裝的SQLite3去做查表操作,回退(刪除)比這個方便些(下面一節介紹怎么安裝)
那么都叫SQLite了,肯定是支持SQL語句的,所以使用SQLite,肯定要懂一些SQL。
這里需要注意的是SQLite中的SQL和其他數據庫的SQL有所區別,使用的時候需要小心。本文只講SQLite的SQL
不過也并不用太擔心,差異不是很大
那么這里簡單講兩個SQL語句
因為只是簡單的介紹文,所以不會說的很詳細
我們為了方便練習,可以直接在Ubuntu下安裝一個SQLite3程序
sudo apt install sqlite3
那么簡單創建一個數據庫可以這樣
sqlite3 mydatabase.db
mydatabase.db是數據庫的名字,這樣打開之后,就可以執行后面的SQL語句了
不過也可以拿到shell.c編譯出來的SQLite3-cli(這個比較難用,不過也夠用)
首先,數據庫,數據庫有關系型數據庫(SQL)和非關系型(NoSQL),那么SQLite是屬于 關系型的數據庫
關系型的數據庫呢,一個特點就是它比較的結構化。結構化存儲,就是里面存放東西都是相同結構的,那么相同結構的東西呢就放在一個表里面。
類似于書架上的書籍,整理的時候會將同一類型的書籍放到一個書架上面
那么先建立一個書架,咳咳,建表
CREATE TABLE IF NOT EXISTS mytable (id integer primary key,name text);
上面語句可以建表,建表前會判斷表是不是已經存在,也可以不去判斷,如下
CREATE TABLE yourtable (id integer primary key, name text, age integer);
primary key表示將該字段設置成主鍵
注意:語句結束需要由;(分號)進行結尾,表示這一句SQL結束了,SQLite可以執行了
那么新建的這張表有兩個字段,一個是id,一個是name。id字段的類型是integer整形,就是整數類型,就是0、1、2這些
name字段是text類型,就是文本類型,例如,"zhangsan"或者 "張三"就是文字類型
除了設置主鍵約束,還可以設置唯一約束。SQLite里面設置唯一只需要在字段后面加上一個unique即可
例如在上面name text 改成name text unique
類比我們往書架上放一本書
數據庫,就是存放數據的一個地方。數據倉庫。
現在庫已經有了(已經建好表了),那么就可以存入結構化的數據了。
在一張表中插入一行數據的操作很簡單,只需要
INSERT INTO mytable (id,name) values (1000, "zhangsan");
注意上面這個zhangsan要用引號括起來,表示這是一個字符串(前面的1000因為是數字所以不用括號)
INSERT INTO表示插入到,mytable指定對應的表,所以上面語句表示向mytable這張表插入一行數據,數據內容就是
id是1000,name是"zhangsan"的一行數據
非常容易理解
重復值:如果我們想嘗試往里面插入相同的id的行,就是報錯,因為id是主鍵,主鍵是不允許重復的。但是插入相同的非主鍵的值是被允許的。
INSERT INTO mytable (id, name) values (1000, "lisi"); Runtime error: UNIQUE constraint failed: mytable.id (19)
可以類比我們從書架上挑選感興趣的書,例如找兩本比較厚的書
如果我們想查找一張表里面的所有數據,如下
SELECT * FROM mytable;
*表示匹配所有項,FROM表示從mytable中,SELECT表示選擇
所以就是:從mytable表中選擇所有項
過濾結果
但是如果我們想從表中獲取特定的項呢,我們可以搭配WHERE,例如,我們想提取id大于1000的數據,可以這么寫
SELECT * FROM mytable WHERE id > 1000;
例如我們的表數據內容如下
1000|zhangsan 1001|lisi 1002|wangwu
可以獲取這樣的結果
1001|lisi 1002|wangwu
可以類比我們從書架上拿下一本書,這本書不存放到這個書架了
DELETE就是刪除,那么刪除一條數據就是要指定是哪個表的那條數據,可以這么寫
DELETE FROM mytable WHERE id=1001;
就可以刪除id為1001的數據了,WHERE就是用來指定條件的,一般我們DELETE都是需要搭配WHERE使用,因為通常是要刪除一條或幾條數據。
那么如果不加WHERE,就是刪除表上的所有數據(注意,只是刪除表里面的所有記錄,表還是在的)
DELETE FROM mytable;
多條件
有時候我們需要刪除符合多個條件的數據,我們可以用AND將兩個語句連接起來
例如說,需要刪除age字段大于35的并且id字段小于1000的,可以這么寫
DELETE FROM yourtable WHERE id<1000 AND age>35;
如果我們想修改一項數據,例如想將id為1000的"zhangsan"修改成"zhansang"
我們可以刪除id為1000的數據然后插入id為1000但是name字段為"zhansang"的數據,但是我們可以不必這么做,我們可以更新值
這個不好類比書架了,可以類比于拿下一本書換了一本上去吧
更新字段的值,首先要知道是那個字段,所以一定有WHERE語句,然后更新是UPDATE,所以更新字段的語句就是
UPDATE mytable SET name="zhansang" WHERE name="zhangsan";
當然條件的字段和SET的字段不一定要同一個字段,例如條件可以是id<1000,SET后面可以name="zhansang"類似這樣,就可以將所有id小于1000的name都更新成"zhansang"了
SQL數據庫的應用非常廣泛,包括數據采集、數據分析、單純的存取數據。
SQL是非常好用的數據庫查詢語言,并且它不復雜,比較容易懂。而且專業做SQL的人工資也不低(前提是就是靠這個吃飯的哈)。
學好SQL無論是對實用性還是經濟性來說都是非常好的,寫SQL有點像搭積木,想要什么就搭建成什么樣。
在前面編譯CMake工程中其實就有編譯出使用SQLite進行C語言編程的源碼
里面main.cpp里面主要用到3個Sqlite3里面的函數,分別是sqlite3_open、sqlite3_exec和sqlite3_close
非常簡單,三個函數分別是
sqlite3_open表示打開一個數據庫文件,一般為xxx.db
sqlite3_exec表示執行一條SQL語句
sqlite3_close表示關閉數據庫文件
首先,先編寫如下代碼
int opendatabase(sqlite3** db, const char* dbfilename) { char *zErrMsg = 0; int rc; rc = sqlite3_open(dbfilename, db); if(SQLITE_OK != rc) { fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(*db)); sqlite3_close(*db); return -1; } return 0; }
上面打開一個名為mydatabase.db
的數據庫,db為該數據庫的句柄
然后判斷有沒有錯誤(一般在指定文件不是一個數據庫文件會報錯),如果沒有指定的數據庫文件會自動創建。
關閉一個數據庫文件可以直接調用sqlite3_close(sqlite3* db);也可以自己封裝一個函數,如下
int clsoedb(sqlite3** db) { if(NULL != *db) { sqlite3_close(*db); return 0; } return -1; }
因為可以執行的語句特別多,而且上面章節也講過有關SQLite語句的一些介紹,所以這里主要講sqlite3_exec這個C語言接口
先看一下源碼實現
SQLITE_API int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){
第一個參數是數據庫的句柄,用于操作數據庫用的。
第二個參數是傳遞給SQLite執行的SQL語句
第三個參數是執行后的回調函數
第四個參數是回調函數的第一個參
第五個參數是如果執行語句錯誤,用于返回錯誤信息的字符串指針
那么第三個參數和第四個參數可以根據需要置為空或者給一個函數指針和一片內存(通常第四個參數用來返回執行后的結果)
不需要回調的示例,參考如下代碼
//創建表 int create_table(sqlite3 *pdb) { char *sql = NULL; char *errmsg = NULL; int ret; sql = (char*)"create table if not exists mytable (id integer primary key,name text);"; ret = sqlite3_exec(pdb, sql, NULL, NULL, &errmsg); if(SQLITE_OK != ret) { printf("create table error! %s\n", errmsg); return -1; } else { return 0; } }
上面的sql的值就是建表的一個操作,可以參考上面SQL語句的相關介紹。因為建表操作我們只需要知道建表成功了還是失敗了,所以我們不需要填充xCallback和pArg參數,自然填NULL的時候不會調用到回調
需要調用回調的示例,參考如下代碼
// callback int show_row(void *return_, int column, char* result[], char** column_name) { for(int i = 0; i < column; i++) { printf("%s\t", result[i]); } printf("\n"); return 0; } // 查詢和顯示所有mytable的數據 int query_all_and_show(sqlite3* pdb) { char sql[24] = {0}; char *errmsg = NULL; int ret; strncpy(sql, "select * from mytable;", 22); // 數據庫,語句字符串,回調函數,用戶輸入的參數,最終傳給回調函數使用,錯誤信息 ret = sqlite3_exec(pdb, sql, show_row, NULL, &errmsg); if(SQLITE_OK != ret) { printf("select exec error: %s\n", errmsg); return -1; } return 0; }
上述代碼查詢了當前mytable表里面的所有行的數據,上面的會調函數當有多行的時候會調用多次。每一次都可以將一行的數據打印出來
如果需要將表返回到主函數,可以在pArg參數那里填充一個結構體鏈表指針(或者vector),然后每次創建一項就可以返回整張表的內容。
除了sqlite3_exec()函數,SQLite3還提供了一個函數可以執行語句,并且可以在同一個函數中處理返回的數據,像上述的查表的操作其實用這個函數會更好一點
SQLITE_API int sqlite3_get_table( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ char ***pazResult, /* Write the result table here */ int *pnRow, /* Write the number of rows in the result here */ int *pnColumn, /* Write the number of columns of result here */ char **pzErrMsg /* Write error messages here */ ){
同樣的,我們看下參數,第一個參數是數據庫句柄,第二個參數是需要執行的SQL語句
第三個參數是返回的結果的表
第四個參數是一共有多少行
第五個參數是一共有多少列
第六個參數是產生錯誤時的錯誤信息返回
這里不講具體的寫法了,輸出行列值可以參考以下寫法
for(int i = 0; i < Col; i++) { for(int j = 0; j < Row; j++) { printf("%s\t", azResult[i*Row+j]); } printf("\n"); }
SQLiteC++是一個簡潔易用的C++封裝庫
正常我們用C語言去編程,可以像上面章節說的,自己去封裝相關的操作。如果你的項目用上了C++,那么我推薦用C++封裝的庫去寫,會比較方便一點。
上面C語言編程的章節,介紹了相關操作數據庫的流程,這里不再重復介紹
我們看下使用SQLiteC++最簡單的示例是怎么樣的
我們可以創建一個工程,然后獲取SQLiteC++的源碼
mkdir useSQLiteCpp && cd useSQLiteCpp git clone https://github.com/SRombauts/SQLiteCpp.git cd SQLiteCpp git submodule init git submodule update
在examples/example2/src路徑下有一個示例的main.cpp,我們可以通過觀察這個文件學習SQLiteC++庫的相關操作,在useSQLiteCpp目錄創建main.cpp,內容如下
#include <iostream> #include "SQLiteCpp/SQLiteCpp.h" // https://www.cnblogs.com/nbtech/p/use_sqlite_library.html int main() { try { // Open a database file in create/write mode(用寫模式打開一個數據庫文件) SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE); std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n"; // Create a new table with an explicit "id" column aliasing the underlying rowid(創建一個表,id設置為主鍵) db.exec("DROP TABLE IF EXISTS test"); db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"); // first row(插入一行,id是NULL就是不指定,不指定會從1開始分配,value是test) int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")"); std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl; // second row(插入第二行,id是2,根據上一條記錄加一,value是second) nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")"); std::cout << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb << std::endl; // update the second row(將id為2的行的value值更新為second-updated) nb = db.exec("UPDATE test SET value=\"second-updated\" WHERE id='2'"); std::cout << "UPDATE test SET value=\"second-updated\" WHERE id='2', returned " << nb << std::endl; // Check the results : expect two row of result(讀取結果,應該會有兩行數據。其實就是查表) SQLite::Statement query(db, "SELECT * FROM test"); std::cout << "SELECT * FROM test :\n"; while (query.executeStep()) { std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\")\n"; } db.exec("DROP TABLE test"); // 刪除test這個表 } catch (std::exception& e) { // 異常處理 std::cout << "SQLite exception: " << e.what() << std::endl; return EXIT_FAILURE; // unexpected error : exit the example program } // remove("test.db3"); // 刪除文件 return 0; }
上面的幾個操作總結就是:
1、聲明一個db文件,以什么形式打開SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
2、通過exec方法執行各種SQL語句,db.exec(const char* );
3、定義查詢語句,并獲取結果SQLite::Statement query(db, "SELECT * FROM test");
4、異常處理
根據上面的注釋內容可以知道這個main.cpp做了哪些事情
編寫CMake工程也比較簡單,SQLiteC++是通過CMake管理的,所以添加為子項目即可
cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(useSQLiteCpp LANGUAGES CXX) add_executable(useSQLiteCpp main.cpp) # SQLiteCpp include_directories(SQLiteCpp/include) option(SQLITECPP_RUN_CPPLINT "Not Run cpplint.py tool for Google C++ StyleGuide." OFF) add_subdirectory(SQLiteCpp lib) target_link_libraries(useSQLiteCpp SQLiteCpp)
關于“SQLite3數據庫如何使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。