天天看點

QT_資料庫、QSqlDatabase、QSqlQuery、SqliteoverviewSQLiteSqlQuery

catalog

  • overview
    • 驅動層
    • SQl接口層
  • SQLite
    • 修改資料庫操作
  • SqlQuery

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; }