前言
SQLite(sql)是一款開源輕量級的數據庫軟件,不需要server,可以集成在其他軟件中,非常適合嵌入式系統。
Qt5以上版本可以直接使用SQLite(Qt自帶驅動)。
用法
1 准備
- 引入SQL模塊
在Qt項目文件(.pro文件)中,加入SQL模塊:
QT += sql
- 引用頭文件
在需要使用SQL的類定義中,引用相關頭文件。例如:
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
2 使用
1. 建立數據庫
檢查連接、添加數據庫驅動、設置數據庫名稱、數據庫登錄用戶名、密碼。
QSqlDatabase database;
if (QSqlDatabase::contains("qt_sql_default_connection"))
{
database = QSqlDatabase::database("qt_sql_default_connection");
}
else
{
database = QSqlDatabase::addDatabase("QSQLITE");
database.setDatabaseName("MyDataBase.db");
database.setUserName("XingYeZhiXia");
database.setPassword("123456");
}
上述代碼解釋:
(1)第一行中,建立了一個QSqlDatabase
對象,后續的操作要使用這個對象。
(2)if
語句用來檢查指定的連接(connection)是否存在。這里指定的連接名稱(connection name)是qt_sql_default_connection
,這是Qt默認連接名稱。實際使用時,這個名稱可以任意取。如果判斷此連接已經存在,那么QSqlDatabase::contains()
函數返回true。此時,進入第一個分支,QSqlDatabase::database()
返回這個連接。
(3)如果這個連接不存在,則進入else
分支,需要創建連接,並添加數據庫。在else
分支第一行,addDatabase()
的參數QSQLITE
是SQLite對應的驅動名,不能改。而且需要注意的是,addDatabase()
的第二個參數被省略了,第二個參數的默認參數就是上面提到的Qt默認連接名稱qt_sql_default_connection
。如果需要使用自定義的連接名稱(如果程序需要處理多個數據庫文件的話就會這樣),則應該加入第二個參數,例如
database = QSqlDatabase::addDatabase("QSQLITE", "my_sql_connection);
這個時候,如果在另一個地方需要判斷my_sql_connection
連接是否存在,就應該使用if (QSqlDatabase::contains("my_sql_connection"))
。
(4)else
分支第二行中,setDatabaseName()
的參數是數據庫文件名。如果這個數據庫不存在,則會在后續操作時自動創建;如果已經存在,則后續的操作會在已有的數據庫上進行。
(5)else
分支后面兩行,設置用戶名和密碼。用戶名,密碼都可以隨便取,也可以省略。
2. 打開數據庫
使用open()
打開數據庫,並判斷是否成功。注意,在第一步檢查連接是否存在時,如果連接存在,則在返回這個連接的時候,會默認將數據庫打開。
if (!database.open())
{
qDebug() << "Error: Failed to connect database." << database.lastError();
}
else
{
// do something
}
如果打開成功,則進入else分支。對數據庫的操作都需要在else分支中進行。
3. 關閉數據庫
數據庫操作完成后,最好關閉。
database.close();
4. 操作數據庫
對數據庫進行操作需要用到QSqlQuery類,操作前必須定義一個對象。下面舉例說明操作方法。操作需要使用SQLite語句,本文中的幾個例子會使用幾個常用的語句,關於SQLite語句的具體信息請參考SQLite相關資料。
例1:創建表格
創建一個名為student的表格,表格包含三列,第一列是id,第二列是名字,第三列是年齡。
QSqlQuery sql_query;
QString create_sql = "create table student (id int primary key, name varchar(30), age int)";
sql_query.prepare(create_sql);
if(!sql_query.exec())
{
qDebug() << "Error: Fail to create table." << sql_query.lastError();
}
else
{
qDebug() << "Table created!";
}
代碼解釋:
(1)第一行定義一個QSqlQuery
對象。
(2)第二行是一個QString
,其中的內容是SQLite語句。對數據庫的操作,都是用SQLite的語句完成的,把這些指令以QString類型,通過prepare
函數,保存在QSqlQuery對象中。也可將指令,以QString形式直接寫在exec()
函數的參數中,例如:
sql_query.exec("create table student (id int primary key, name varchar(30), age int)");
創建表格語句:create table <table_name> (f1 type1, f2 type2,…);
create table
是創建表格的語句,也可用大寫CREATE TABLE
;student是表格的名稱,可以任意取;括號中是表格的格式,上述指令表明,表格中有三列,第一列的名稱(表頭)是id,這一列儲存的數據類型是int,第二列名稱是name,數據類型是字符數組,最多有30個字符(和char(30)的區別在於,varchar的實際長度是變化的,而char的長度始終是給定的值),第三列的名稱是age,數據類型是int。
如果sql_query.exec()
執行成功,則創建表格成功。
例2:插入數據
在剛才創建的表格中,插入一行數據。
QString insert_sql = "insert into student values (?, ?, ?)";
sql_query.prepare(insert_sql);
sql_query.addBindValue(max_id+1);
sql_query.addBindValue("Wang");
sql_query.addBindValue(25);
if(!sql_query.exec())
{
qDebug() << sql_query.lastError();
}
else
{
qDebug() << "inserted Wang!";
}
if(!sql_query.exec("INSERT INTO student VALUES(3, \"Li\", 23)"))
{
qDebug() << sql_query.lastError();
}
else
{
qDebug() << "inserted Li!";
}
插入語句:insert into <table_name> values (value1, value2,…);
insert into
是插入語句,student是表格名稱,values()是要插入的數據。這里,我們插入了2組數據。插入第一組數據的時候,用addBindValue
來替代語句中的?
,替代的順序與addBindValue
調用的順序相同。插入第二組數據的時候,則是直接寫出完整語句。
例3:更新數據(修改數據)
QString update_sql = "update student set name = :name where id = :id";
sql_query.prepare(update_sql);
sql_query.bindValue(":name", "Qt");
sql_query.bindValue(":id", 1);
if(!sql_query.exec())
{
qDebug() << sql_query.lastError();
}
else
{
qDebug() << "updated!";
}
語句:update <table_name> set <f1=value1>, <f2=value2>… where <expression>;
更新(修改)的語句是update...set...
,其中student是表格名稱,name是表頭名稱(即第二列),:name是待定的變量,where用於確定是哪一組數據,:id也是待定變量。
bindValue(" ", " ")
函數用來把語句中的待定變量換成確定值。
例4:查詢數據
(1)查詢部分數據
QString select_sql = "select id, name from student";
if(!sql_query.exec(select_sql))
{
qDebug()<<sql_query.lastError();
}
else
{
while(sql_query.next())
{
int id = sql_query.value(0).toInt();
QString name = sql_query.value(1).toString();
qDebug()<<QString("id:%1 name:%2").arg(id).arg(name);
}
}
語句select <f1>, <f2>, ... from <table_name>;
select是查詢指令;<f1>
等等是要查詢的變量(即表頭),中間用逗號隔開;from ...指定表格。
上述語句是說查詢student表中的 id 和 name 。執行查詢之后,用sql_query.value(int)
來獲得數據。同樣地,value(0)
表示第一個數據,即 id,value(1)
表示name。注意:value()
函數的返回值類型是QVariant
,因此要用toInt()
等函數轉換成特定的類型。
(2)查詢全部數據
QString select_all_sql = "select * from student";
sql_query.prepare(select_all_sql);
if(!sql_query.exec())
{
qDebug()<<sql_query.lastError();
}
else
{
while(sql_query.next())
{
int id = sql_query.value(0).toInt();
QString name = sql_query.value(1).toString();
int age = sql_query.value(2).toInt();
qDebug()<<QString("id:%1 name:%2 age:%3").arg(id).arg(name).arg(age);
}
}
語句select * from <table_name>;
查詢所有數據用 * 表示。用while(sql_query.next())
用來遍歷所有行。同樣用value()
獲得數據。
(3)查詢最大id
QString select_max_sql = "select max(id) from student";
int max_id = 0;
sql_query.prepare(select_max_sql);
if(!sql_query.exec())
{
qDebug() << sql_query.lastError();
}
else
{
while(sql_query.next())
{
max_id = sql_query.value(0).toInt();
qDebug() << QString("max id:%1").arg(max_id);
}
}
這個就是在語句中用max
來獲取最大值。
例5:刪除與清空
(1)刪除一條數據
QString delete_sql = "delete from student where id = ?";
sql_query.prepare(delete_sql);
sql_query.addBindValue(0);
if(!sql_query.exec())
{
qDebug()<<sql_query.lastError();
}
else
{
qDebug()<<"deleted!";
}
語句delete from <table_name> where <f1> = <value>
delete用於刪除條目,用where給出限定條件。例如此處是刪除 id = 0的條目。
(2)清空表格(刪除所有)
QString clear_sql = "delete from student";
sql_query.prepare(clear_sql);
if(!sql_query.exec())
{
qDebug() << sql_query.lastError();
}
else
{
qDebug() << "table cleared";
}
這里沒有用where給出限制,就會刪除所有內容。