catalog
overview
QT SQL子產品提供了一個【與平台無關】【與資料庫無關】的通路SQL資料庫的接口
/ QT都是通過一個【子產品】來提供對某種【功能】的支援,比如對于資料庫功能 就對應SQL子產品
/ 所謂子產品,即QT在他裡面寫了很多的類
/ 引入一個子產品, 在項目檔案.pro裡 添加【QT += sql】
驅動層
驅動層是為【資料庫】與【SQL接口層】提供了橋梁
QT的SQL子產品是獨立于資料庫的,是以所有的資料庫代碼都在【資料庫驅動程式】中
/ SQL子產品中屬于驅動層的類有: QSqlDriver、QSqlResult
QSqlDatabase::drivers() 得到所有的資料庫驅動程式
SQl接口層
SQL接口層提供了對資料庫的通路
有:QSqlDatabase,QSqlQuery,QSqlError,QSqlField,QSqlIndex,QSqlRecord
' QSqlDatabase建立資料庫的連接配接,這個連接配接通過【資料庫驅動程式QSqlDriver】來通路資料庫 '
QSqlDatabase對象
xx.db檔案 -> ("xx_conn1"連接配接名)-> xx_db_1
-> xx_db_2
注意,xx_db_1 和 xx_db_2 都是通過"xx_conn1"這個連接配接名,連接配接到的資料庫xx.db檔案!!
QSqlQuery query1(xx_db_1), query2(xx_db_2);
/ 即2個SqlQuery,通過同一個“xx_conn1"連接配接名, 來操作xx.db檔案
/ 雖然,xx_db_1 和 xx_db_2 是兩個不同的對象,但因為他倆的連接配接名一樣
/ 即他倆都是addDatabase("SQLITE", "xx_conn1"), 連接配接名一樣
'重點: QSqlDatabase這個對象 根本沒用!! xx_db_1和xx_db_2根本沒差別 '
' 關鍵是你要看,他的<連接配接名>是否相同!!! xx_db_1.connectionName()可以得到"xx_conn1"這個連接配接名'
' 如果連接配接名相同,那麼這兩個對象就是完全相同的 '
第1步: query1.exec("SELECT"); 'query1的資料是:[1, 2, 3]'
第2步: query2.exec("DELECT"); '此時,資料庫是空的!!'
第3步: 此時不要執行query1.exec("SELECT");
讓query1還用'第1步'的結果,
query1.seek(0);
do{ 拿出query1裡的所有資料; }while(query1.next());
'query1的資料,還是[1,2,3]!!!!'
'即,QSqlQuery 他不會實時的去監測 去xx.db檔案裡監測!!!'
' 他是靜态的!!! '
/ 也就是說,你query.exec("SELECT"),其實是得到了[1, 2, 3]這些資料 占用資源
/ 如果你的query不再使用, 要麼把這個對象給釋放掉 要麼調用query.clear()
/ query.clear()後,他的資源就釋放了。 但這個query還是可以使用的,需要調用exec來繼續使用
QSqlDatabase對象
xx.db檔案 -> ("xx_conn1"連接配接名)-> xx_db_1
-> ("xx_conn2"連接配接名)-> xx_db_2
QSqlQuery query1(xx_db_1), query2(xx_db_2);
/ 即,他倆是通過 '不同的資料庫連接配接名',連接配接同一個xx.db檔案
第1步: query1.exec("SELECT"); 'query1的資料是:[1, 2, 3]'
第2步: query2.exec("DELECT"); '此時,資料庫是空的!!'
第3步: '此時,query1結果仍然是[1,2,3],他不會實時的 監測資料庫'
'一般,如果隻有1個資料庫檔案xx.db, 那麼 不需要設定 >=2個 資料庫連接配接名 '
' 對于xx.db這個檔案, 就使用 "xx_conn"這個連接配接名即可。 '
'資料庫連接配接名,是針對不同的資料庫檔案的; 有幾個資料庫檔案,就設定幾個連接配接名'
實際開發:
A類: 通過"xx_conn"擷取資料庫連接配接,并得到query1, query2
B類: 通過"xx_conn"擷取資料庫連接配接,并得到query3, query4
'注意, query3修改後, query1和query2 需要執行.exec("SELECT")來更新!!
SQLite
QSqlDatabase db_conn1;
if(QSqlDatabase::contains("db_conn1")){
db_conn1 = QSqlDatabase::database("db_conn1", true);
/ db_conn1為一個資料庫連接配接名,至于他連向 1.db,還是2.db,不知道
/ true也是預設值,表示: 如果db_conn1 沒有打開,就打開資料庫連接配接
}else{
db_conn1 = QSqlDatabase::addDatabase("QSQLITE", "db_conn1");
/ 設定資料庫連接配接名為 db_conn1
db_conn1.setDatabaseName(QCoreApplication::applicationDirPath() + "//database1.db");
/ 對應你..\build_desktop-debug\目錄下: 如果有該檔案 則連接配接該檔案,否則【建立出來】
}
if(!db_conn1.open()){ QMessageBox::critical(this, "錯誤", "db_conn1.open()"); }
修改資料庫操作
除了select操作,其他操作 增、删、改, 執行後 你立刻關機,是更新不到資料庫的!!!
1,需要等7秒左右,才會更新到資料庫
2,你執行兩次,那麼第一次操作會更新到資料庫,第二次操作不會更新
-----------------------------------------------
比如: 1.db裡有兩個表t1 和 t2
我們對t1表 和 t2表的 增/删/改操作之後,立刻執行一個:
單獨對t1/t2表的 增/删/改操作 (且,必須必須實際修改資料庫!!)
update 't1' set val='xx' where id = '1';
這個id=1,這個id必須是存在的
(雖然,即使id=1不存在,query.exec是不會報錯的)
這隻要query.exec成功了(且你的t1表裡,确實有id=1這個資料)
那麼,你前一個操作,才會成功
' 即,我們對一個資料庫的 寫操作之後, 再執行一次 寫操作,前一次才會成功 '
SqlQuery
/ 如果不設定連接配接名,這個database的連接配接名為“qt_sql_default_connection"
database = QSqlDatabase::addDatabase("QSQLITE");
database.setDatabaseName("sqlite_db.db"); / xx.dat 和 xx.db 都可以
if(!database.open()){ DE(database.lastError().text()); }
else{ DE("open database succ"); }
QSqlQuery query;
/ 必須在database已經成功連接配接到資料庫後,再定義QSqlQuery query;
/ 這個定義query,不可以放在全局 或放在database.open的前面!!!
/ 這一點,一定要切記!!!
/ 如果非要放到全局裡, 則需要 QSqlQuery* query;
/ 然後等到連接配接到資料庫後,再讓query = new QSqlQuery();
/ '你的QSqlQuery query,必須要保證,有名為"qt_sql_default_connection"的資料庫連接配接名!!
/ 假設,你的資料庫連接配接名 都是你自定義的,必須要通過query(my_db_conn)的方式建立!!
query.exec("CREATE TABLE 'user' ('name' VARCHAR(30), 'sex' VARCHAR(30) ); ");
/ Insert
que.prepare("INSERT INTO 'user' VALUES (:arg1, :arg2); ");
for(User user : users){
que.bindValue(":arg1", user.name);
que.bindValue(":arg2", user.sex);
que.exec();
/ 這個que.prepare,隻是提供了一個“規範”,他究竟會que.exec多少次 是未知的
/ 要取決你的代碼邏輯,你想exec多少次 都可以
}
/ Select Seek
if(que.exec("SELECT * FROM 'user'; ")){
int siz = 0;
while(que.next()){
++ siz; / que.size() 會得到 -1 ....-,-
}
for(int i=0; i<10; ++i){
que.seek(i);
/ 隻有你query.exec執行的是"SELECT"語句,你才可以使用seek函數!!
DE(que.value(0).toString());
}
}
/ Delete
QSqlQuery sql;
if(!sql.exec("DELETE FROM 'user'; ")){ _WC; }