QT操作sqlite数据库汇总
QT自帶的QSqlite數(shù)據(jù)庫中實(shí)現(xiàn)id主鍵自增長(zhǎng)
QSqlite是QT自帶的輕量級(jí)數(shù)據(jù)庫,使用起來非常方便,對(duì)系統(tǒng)環(huán)境也沒有任何的環(huán)境要求,可移植性非常好,適合數(shù)據(jù)量不是太大,要求不是太高的程序。本文中,就介紹一點(diǎn),怎么實(shí)現(xiàn)在QSqlite中的數(shù)據(jù)表實(shí)現(xiàn)id自增長(zhǎng),方法很簡(jiǎn)單。
一、創(chuàng)建數(shù)據(jù)表時(shí),主鍵設(shè)置為id,并且數(shù)據(jù)類型設(shè)置為integer。設(shè)置成integer的主鍵,默認(rèn)自增長(zhǎng)。
create table m_table (id integer primary key,m_equip varchar(10),m_place varchar(10))
二、使用插入命令的時(shí)候,要注意對(duì)應(yīng)關(guān)系。
QString(insert into %1 (Name,Place) value(’%2’,’%3’)").arg(“computer”).arg(“office”);
Name和Place是我生成的表的列名,后面是數(shù)值。一開始我為了圖省事,省略了列名,如下
QString(insert into %1 value(’%2’,’%3’)").arg(“computer”).arg(“office”);//錯(cuò)誤示范
因此一直無法實(shí)現(xiàn)自增長(zhǎng)插入。
SQLite設(shè)置主鍵自動(dòng)增長(zhǎng)及插入語法
SQLite中,一個(gè)自增長(zhǎng)字段定義為INTEGER PRIMARY KEY AUTOINCREMENT,那么在插入一個(gè)新數(shù)據(jù)時(shí),只需要將這個(gè)字段的值指定為NULL,即可由引擎自動(dòng)設(shè)定其值,引擎會(huì)設(shè)定為最大的rowid+1。如果表為空,那麼將會(huì)插入1。
比如,有一張表ID為自增:
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name NVARCHAR(100) NOT NULL
)
那麼,插入的SQL就是:
INSERT INTO Product VALUES(NULL, '產(chǎn)品名稱')
GO
SQLite中不支持關(guān)鍵字top
select top 1 oid from orderinfo order by oid desc ;?(×)
select oid from orderinfo order by oid desc limit 0,1;(√)
?網(wǎng)上查到資料說,從 SQLite 的 2.3.4 版本開始,如果將一個(gè)表中的一個(gè)字段聲明為 INTEGER PRIMARY KEY,那么只需向該表的該字段插入一個(gè) NULL 值,這個(gè) NULL 值將自動(dòng)被更換為比表中該字段所有行的最大值大 1 的整數(shù);如果表為空,那么將被更換為 1。
CREATE TABLE "ProcessList"([Id] integer(4) PRIMARY KEY,[Type] varchar(20),[Name] varchar(30),[IsUse] int ?) ? ?執(zhí)行insert into processlistvalues(null,'a','b',1) ? ?在邏輯意義上等價(jià)于:insert into processlist VALUES((SELECT max(Id) FROM processlist)+1, 'a','b',1);
insert into processlistvalues(null,'aa','bb',1) ? ?執(zhí)行兩條插入語句后再查詢表中數(shù)據(jù):select * from processlist ? ?結(jié)果如下:
Id Type Name IsUse1 ?a ? ? ? b ? ? ? 1 2 ?aa ? ? bb ? ? 1 ? ? 一個(gè)新的API函數(shù) sqlite3_last_insert_rowid() 返回最近的插入操作的整形鍵.注意這個(gè)整型鍵始終比之前插入表中的最后一個(gè)鍵大1。新鍵相對(duì)于表中的已有鍵來說是唯一的, 但它可能與之前從表中刪除的鍵值重疊。要始終得到在整個(gè)表中唯一的鍵,在INTEGER PRIMARY KEY的聲明之前加關(guān)鍵詞AUTOINCREMENT.這樣被選的鍵將總是比表中已存在的最大鍵大1。若可能的最大鍵已存在于表中,INSERT操作將失敗并返回一個(gè)SQLITE_FULL錯(cuò)誤碼
?
創(chuàng)建數(shù)據(jù)表格,設(shè)置主鍵自增
創(chuàng)建數(shù)據(jù)庫時(shí),啟用主鍵自增加特性
Create table testTable (id INTEGER PRIMARY KEY AUTOINCREMENT,。。。。
注意事項(xiàng):設(shè)置主鍵自增時(shí)(AUTOINCREMENT),主鍵類型必須是INTEGER,不能使用INT,否則會(huì)報(bào)錯(cuò)。
插入數(shù)據(jù)后,獲取自增的主鍵值
QSqlQuery::exec(“SELECT last_insert_rowid()”);
QSqlQuery::next();
int id = QSqlQuery::value(0).toInt(&ok);
或者使用
QSqlQuery::lastInsertId()).toInt();
//*************************************************************sqlite操作概念2
QT & sqlite3:
先說一下QT自帶數(shù)據(jù)庫sqlite3和另外用sqlite3插件的區(qū)別,他們的功能是一樣的,但是代碼就不一樣了。QT對(duì)數(shù)據(jù)庫具有完善的支持,不需要加任何其他插件就可以直接使用,但是如果你要是加了sqlite3插件,調(diào)用數(shù)據(jù)庫就跟直接調(diào)用一個(gè)驅(qū)動(dòng)一樣,直接調(diào)用接口函數(shù):open、close、……,換言之QT自帶的數(shù)據(jù)庫語言就用不上了。
一、使用Qt自帶的數(shù)據(jù)庫sqlite3
Qt自帶了很多常用的數(shù)據(jù)庫驅(qū)動(dòng),使用起來非常方便如下圖所示:
使用Qt自帶數(shù)據(jù)庫SQLite3的代碼實(shí)例:
Connect to Sqlite and do insert, delete, update and select
Foundations of Qt Development\Chapter13\sqltest\sqlite\main.cpp /** Copyright (c) 2006-2007, Johan Thelin* * All rights reserved.* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met:* * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer.* * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution.* * Neither the name of APress nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission.* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.**/#include <QApplication>#include <QtSql> #include <QtDebug>int main( int argc, char **argv ) {QApplication app( argc, argv );//創(chuàng)建連接QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE" );//第二個(gè)參數(shù)可以設(shè)置連接名字,這里為defaultdb.setDatabaseName( "./testdatabase.db" );//?設(shè)置數(shù)據(jù)庫名與路徑,?此時(shí)是放在上一個(gè)目錄//打開連接if( !db.open() ){qDebug() << db.lastError();qFatal( "Failed to connect." );}qDebug( "Connected!" );//各種操作QSqlQuery qry;//創(chuàng)建tableqry.prepare( "CREATE TABLE IF NOT EXISTS names (id INTEGER UNIQUE PRIMARY KEY, firstname VARCHAR(30), lastname VARCHAR(30))" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug() << "Table created!";//增qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (1, 'John', 'Doe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (2, 'Jane', 'Doe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (3, 'James', 'Doe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (4, 'Judy', 'Doe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (5, 'Richard', 'Roe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (6, 'Jane', 'Roe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (7, 'John', 'Noakes')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (8, 'Donna', 'Doe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" );qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (9, 'Ralph', 'Roe')" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Inserted!" ); //查詢qry.prepare( "SELECT * FROM names" );if( !qry.exec() )qDebug() << qry.lastError();else{qDebug( "Selected!" );QSqlRecord rec = qry.record();int cols = rec.count();for( int c=0; c<cols; c++ )qDebug() << QString( "Column %1: %2" ).arg( c ).arg( rec.fieldName(c) );for( int r=0; qry.next(); r++ )for( int c=0; c<cols; c++ )qDebug() << QString( "Row %1, %2: %3" ).arg( r ).arg( rec.fieldName(c) ).arg( qry.value(c).toString() );}qry.prepare( "SELECT firstname, lastname FROM names WHERE lastname = 'Roe'" );if( !qry.exec() )qDebug() << qry.lastError();else{qDebug( "Selected!" );QSqlRecord rec = qry.record();int cols = rec.count();for( int c=0; c<cols; c++ )qDebug() << QString( "Column %1: %2" ).arg( c ).arg( rec.fieldName(c) );for( int r=0; qry.next(); r++ )for( int c=0; c<cols; c++ )qDebug() << QString( "Row %1, %2: %3" ).arg( r ).arg( rec.fieldName(c) ).arg( qry.value(c).toString() );}qry.prepare( "SELECT firstname, lastname FROM names WHERE lastname = 'Roe' ORDER BY firstname" );if( !qry.exec() )qDebug() << qry.lastError();else{qDebug( "Selected!" );QSqlRecord rec = qry.record();int cols = rec.count();for( int c=0; c<cols; c++ )qDebug() << QString( "Column %1: %2" ).arg( c ).arg( rec.fieldName(c) );for( int r=0; qry.next(); r++ )for( int c=0; c<cols; c++ )qDebug() << QString( "Row %1, %2: %3" ).arg( r ).arg( rec.fieldName(c) ).arg( qry.value(c).toString() );}qry.prepare( "SELECT lastname, COUNT(*) as 'members' FROM names GROUP BY lastname ORDER BY lastname" );if( !qry.exec() )qDebug() << qry.lastError();else{qDebug( "Selected!" );QSqlRecord rec = qry.record();int cols = rec.count();for( int c=0; c<cols; c++ )qDebug() << QString( "Column %1: %2" ).arg( c ).arg( rec.fieldName(c) );for( int r=0; qry.next(); r++ )for( int c=0; c<cols; c++ )qDebug() << QString( "Row %1, %2: %3" ).arg( r ).arg( rec.fieldName(c) ).arg( qry.value(c).toString() );}//更新qry.prepare( "UPDATE names SET firstname = 'Nisse', lastname = 'Svensson' WHERE id = 7" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Updated!" );qry.prepare( "UPDATE names SET lastname = 'Johnson' WHERE firstname = 'Jane'" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Updated!" );//刪除qry.prepare( "DELETE FROM names WHERE id = 7" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Deleted!" );qry.prepare( "DELETE FROM names WHERE lastname = 'Johnson'" );if( !qry.exec() )qDebug() << qry.lastError();elseqDebug( "Deleted!" );db.close();return 0; }二、Qt中使用sqlite3插件
1、安裝sqlite3插件
從官方網(wǎng)站http://www.sqlite.org下載完整版本。
2、安裝sqlite3
網(wǎng)上可以看到很多修改下載之后的源代碼的論壇,我估計(jì)那些帖子比較老一點(diǎn),最新版的代碼已經(jīng)不存在那些bug了,可以直接編譯
?*注意復(fù)制粘貼庫函數(shù)的時(shí)候有的動(dòng)態(tài)鏈接庫如果單獨(dú)復(fù)制會(huì)丟失之間的鏈接關(guān)系,所以需要一塊復(fù)制
cp -arf libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6?。。。
3、移植sqlite3
在QTE的include文件中建立新文件夾sqlite3,將頭文件放到里面;把庫文件放到QTE的lib文件中
4、編程代碼實(shí)例:
(1)?QT生成的.pro文件中添加庫指令:?LIBS += -lsqlite3
(2)?在調(diào)用數(shù)據(jù)庫的文件的頭文件里添加頭文件和變量
?#include "sqlite3/sqlite3.h"? ???????? ?
?sqlite3 *db;??????? //數(shù)據(jù)庫
?char *zErrMsg;????? //出錯(cuò)信息
?char? **resultp;??? //調(diào)用時(shí)的保存位置
?int? nrow;????????? //列數(shù)
int? ncolumn;?????? //行數(shù)
?char? *errmsg;????? //出錯(cuò)信息
(3)新建或打開數(shù)據(jù)庫? ? ??
if( (sqlite3_open("people.db", &db)) != 0 ){
qDebug()<<"sqlite3 open is false";
?}
else {
qDebug()<<"sqlite3 open is OK";
?}
(4)?建立表格
sqlite3_exec(db, "create table person(name varchar(30) PRIMARY KEY, age int);", NULL, NULL, &zErrMsg);
*添加?PRIMARY KEY?是指定主鍵,每個(gè)數(shù)據(jù)庫只能有一個(gè),主鍵的值不能重復(fù),比方說你設(shè)定name為主鍵,則相同名字的人只能保存第一個(gè),其他的忽略不計(jì)。若想避免這種情況,則去掉主鍵或者設(shè)定id號(hào)為主鍵(id號(hào)一直加一,不會(huì)重復(fù))。
(5)往表格里寫入信息
?a.直接添加數(shù)據(jù)??
?sqlite3_exec(db, "insert into person values('張翼', 30)", NULL, NULL, &zErrMsg);
?sqlite3_exec(db, "insert into person values('hongdy', 28)", NULL, NULL, &zErrMsg);????????????????? ???
?b.添加數(shù)字變量
?int? data=10;
?char sql2[100];? //必須寫明大小,劃分內(nèi)存,如果只寫一個(gè)?char *sql2,會(huì)出現(xiàn)段錯(cuò)誤
?sprintf(sql2,"insert into person values('張翼',%d);",data);
sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);
*sprintf的作用是字串格式化命令,主要功能是把格式化的數(shù)據(jù)寫入某個(gè)字符串中
?c.添加字符串變量
?char data[]="張翼";
?char sql2[100];
?sprintf(sql2,"insert into person values('%s',10);",data);
sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);
?* %s需要用單引號(hào)注釋?????????????
d.添加text中的變量到數(shù)據(jù)庫中
?這里需要漢字編碼的問題,Windows下默認(rèn)GBK或GB2312編碼,Linux下默認(rèn)UTF-8編碼,所以如果沒有設(shè)置好會(huì)出現(xiàn)亂碼
d1.?在main.cpp中添加以下指令,支持中文顯示?
?#include <QTextCodec>
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
d2.?讀取保存
?char *abc=ui->lineEdit->text().toUtf8().data();?? //QString?轉(zhuǎn)char*
?sprintf(sql2,"insert into person values('%s',%d);",abc,data);
sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);
*在調(diào)試的時(shí)候如果用串口超級(jí)終端調(diào)試的話,在ARM上顯示正常,但是在串口是亂碼,不要被迷惑
(6)查詢、調(diào)用數(shù)據(jù)庫
a.?查詢?nèi)?/p>
sqlite3_get_table(db, "select * from person", &resultp, &nrow, &ncolumn, &errmsg);
*resultp保存數(shù)據(jù)庫信息,nrow返回列數(shù),ncolumn返回列數(shù)
b.?查詢部分信息
sqlite3_get_table(db, "select * from person where name='zhang'", &resultp, &nrow, &ncolumn, &errmsg);
c.?變量查詢查詢
?char data[]="張翼";
?char sql3[100];
?sprintf(sql3,"select * from person where name='zhang';",data);
?sqlite3_get_table(db, sql3, &resultp, &nrow, &ncolumn, &errmsg);
?*查詢時(shí)使用變量的方法和添加時(shí)一樣
(7)關(guān)閉數(shù)據(jù)庫
?sqlite3_close(db);
三、VS+QT使用SQL驅(qū)動(dòng)
//1.添加SQL庫:"Qt project setting"-->"Qt Modules",在SQL library復(fù)選框前打勾.或者在vs項(xiàng)目屬性--》連接器--》輸入里加入Qt5Sqllib
//2.添加頭文件
//#include<QtSql>//這樣寫會(huì)報(bào)Cannot open include file: 'QtSql': No such file or directory,奇葩錯(cuò)誤,因?yàn)镼tSql只是一個(gè)文件夾
#include <QtSql/QSqlDatabase>//這樣寫可以
#include <QtSql/QSqlTableModel>
#include<QtSql/QSqlError>
//3.創(chuàng)建連接
qDebug()<<"available driver:";
?QStringList drivers=QSqlDatabase::drivers();
?foreach(QString driver,drivers)
???qDebug()<<"/t"<<driver;
?QSqlDatabase db=QSqlDatabase::addDatabase("SQLITE");
?qDebug()<<"SQLITE driver?"<<db.isValid();
?QString dsn=QString::fromLocal8Bit("DRIVER={SQL SERVER};SERVER=192.168.0.123;DATABASE=test");????? db.setHostName("192.168.0.123");
?db.setDatabaseName(dsn);
?db.setUserName("sa");
?db.setPassword("111111");
?if(!db.open())
?{
???qDebug()<<db.lastError().text();
????QMessageBox::critical(0,QObject::tr("Database Error"),db.lastError().text());
????returnfalse;
?}
//4.查詢數(shù)據(jù)
QSqlQuery query;
query.exec("select * from mytable");
while(query.next())
{
.........
}
//***********************C++對(duì)數(shù)據(jù)庫sqlite3的增、刪、查、改基本操作
1、頭文件定義
在頭文件中聲明以下變量和函數(shù):
// 實(shí)現(xiàn)
public:
void initSqlite(); //初始化數(shù)據(jù)庫
void initWindowShow();
void refreshList(); //刷新列表
public:
CString m_NameString; //姓名
CString m_ChineseString;
CString m_MathString;
CString m_EnglishString;
protected:
HICON m_hIcon;
// 生成的消息映射函數(shù)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CListCtrl m_ListCtrl;
afx_msg void OnBnClickedInsertBtn();
afx_msg void OnBnClickedDeleteBtn();
afx_msg void OnBnClickedModifyBtn();
CEdit m_sName;
CEdit m_sChinese;
CEdit m_sMath;
CEdit m_sEnglish;
afx_msg void OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult);
2、初始化數(shù)據(jù)庫
void CSqlite3Dlg::initSqlite()
{
//打開數(shù)據(jù)庫
const string studentDB = "student.db";
//創(chuàng)建表格
string create_student_table = "CREATE TABLE " + student_table + "(" +
"Name TEXT," +
"Chinese INTEGER," +
"Math INTEGER," +
"English INTEGER"
");";
CSDDb::GetInstance().SetDBFileName(studentDB);
bool ret = CSDDb::GetInstance().CreateTable(create_student_table, student_table);
if (!ret)
{
MessageBox("數(shù)據(jù)庫表格創(chuàng)建失敗!");
}
}
3、插入操作
//插入數(shù)據(jù)
void CSqlite3Dlg::OnBnClickedInsertBtn()
{
// TODO: 在此添加控件通知處理程序代碼
CString name_str, chinese_str, math_str, english_str, str;
string sql, tmp_str;
m_sName.GetWindowText(name_str);
m_sChinese.GetWindowText(chinese_str);
m_sMath.GetWindowText(math_str);
m_sEnglish.GetWindowText(english_str);
str.Format("Values('%s',%s,%s,%s)", name_str, chinese_str, math_str, english_str);
tmp_str = str.GetBuffer();
sql = "insert into " + student_table + "(Name,Chinese,Math,English) " + tmp_str;
CSDDb::GetInstance().InsertData(sql);
//將當(dāng)前插入的數(shù)據(jù)顯示到列表控件中
m_ListCtrl.InsertItem(0, name_str);
m_ListCtrl.SetItemText(0, 1, chinese_str);
m_ListCtrl.SetItemText(0, 2, math_str);
m_ListCtrl.SetItemText(0, 3, english_str);
m_ListCtrl.SetTextBkColor(RGB(155, 155, 155));
m_ListCtrl.Invalidate(); //刷新列表
}
4、刪除數(shù)據(jù)
//刪除數(shù)據(jù)
void CSqlite3Dlg::OnBnClickedDeleteBtn()
{
// TODO: 在此添加控件通知處理程序代碼
if (m_NameString.IsEmpty())
{
MessageBox("請(qǐng)選擇要?jiǎng)h除的選項(xiàng)!");
return;
}
string selectName = m_NameString.GetBuffer();
string sql = "delete from " + student_table + " where Name=" + "'" + selectName + "'";
CSDDb::GetInstance().DeleteData(sql);
refreshList(); //重新刷新列表
}
5、修改數(shù)據(jù)
//修改數(shù)據(jù)
void CSqlite3Dlg::OnBnClickedModifyBtn()
{
// TODO: 在此添加控件通知處理程序代碼
if (m_NameString.IsEmpty())
{
MessageBox("請(qǐng)選擇要更新的選項(xiàng)!");
return;
}
string name_str, chinese_str, math_str, english_str;
m_sName.GetWindowText(m_NameString);
m_sChinese.GetWindowText(m_ChineseString);
m_sMath.GetWindowText(m_MathString);
m_sEnglish.GetWindowText(m_EnglishString);
name_str = m_NameString.GetBuffer();
chinese_str = m_ChineseString.GetBuffer();
math_str = m_MathString.GetBuffer();
english_str = m_EnglishString.GetBuffer();
string sql = "UPDATE " + student_table + " SET " + "Chinese=" + chinese_str + ", " + "Math=" + math_str + ", " + "English=" + english_str + " WHERE " + "Name=" + "'" + name_str + "'";
CSDDb::GetInstance().UpdataData(sql);
refreshList();
}
6、效果如下圖所示:
//******************************************
前言
SQLite(sql)是一款開源輕量級(jí)的數(shù)據(jù)庫軟件,不需要server,可以集成在其他軟件中,非常適合嵌入式系統(tǒng)。
Qt5以上版本可以直接使用SQLite(Qt自帶驅(qū)動(dòng))。
用法
1 準(zhǔn)備
引入SQL模塊
在Qt項(xiàng)目文件(.pro文件)中,加入SQL模塊:
引用頭文件
在需要使用SQL的類定義中,引用相關(guān)頭文件。例如:
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
2 使用
1. 建立數(shù)據(jù)庫
檢查連接、添加數(shù)據(jù)庫驅(qū)動(dòng)、設(shè)置數(shù)據(jù)庫名稱、數(shù)據(jù)庫登錄用戶名、密碼。
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)第一行中,建立了一個(gè)QSqlDatabase對(duì)象,后續(xù)的操作要使用這個(gè)對(duì)象。
(2)if語句用來檢查指定的連接(connection)是否存在。這里指定的連接名稱(connection name)是qt_sql_default_connection,這是Qt默認(rèn)連接名稱。實(shí)際使用時(shí),這個(gè)名稱可以任意取。如果判斷此連接已經(jīng)存在,那么QSqlDatabase::contains()函數(shù)返回true。此時(shí),進(jìn)入第一個(gè)分支,QSqlDatabase::database()返回這個(gè)連接。
(3)如果這個(gè)連接不存在,則進(jìn)入else分支,需要?jiǎng)?chuàng)建連接,并添加數(shù)據(jù)庫。在else分支第一行,addDatabase()的參數(shù)QSQLITE是SQLite對(duì)應(yīng)的驅(qū)動(dòng)名,不能改。而且需要注意的是,addDatabase()的第二個(gè)參數(shù)被省略了,第二個(gè)參數(shù)的默認(rèn)參數(shù)就是上面提到的Qt默認(rèn)連接名稱qt_sql_default_connection。如果需要使用自定義的連接名稱(如果程序需要處理多個(gè)數(shù)據(jù)庫文件的話就會(huì)這樣),則應(yīng)該加入第二個(gè)參數(shù),例如
這個(gè)時(shí)候,如果在另一個(gè)地方需要判斷my_sql_connection連接是否存在,就應(yīng)該使用if (QSqlDatabase::contains("my_sql_connection"))。
(4)else分支第二行中,setDatabaseName()的參數(shù)是數(shù)據(jù)庫文件名。如果這個(gè)數(shù)據(jù)庫不存在,則會(huì)在后續(xù)操作時(shí)自動(dòng)創(chuàng)建;如果已經(jīng)存在,則后續(xù)的操作會(huì)在已有的數(shù)據(jù)庫上進(jìn)行。
(5)else分支后面兩行,設(shè)置用戶名和密碼。用戶名,密碼都可以隨便取,也可以省略。
2. 打開數(shù)據(jù)庫
使用open()打開數(shù)據(jù)庫,并判斷是否成功。注意,在第一步檢查連接是否存在時(shí),如果連接存在,則在返回這個(gè)連接的時(shí)候,會(huì)默認(rèn)將數(shù)據(jù)庫打開。
if (!database.open())
{
qDebug() << "Error: Failed to connect database." << database.lastError();
}
else
{
// do something
}
如果打開成功,則進(jìn)入else分支。對(duì)數(shù)據(jù)庫的操作都需要在else分支中進(jìn)行。
3. 關(guān)閉數(shù)據(jù)庫
數(shù)據(jù)庫操作完成后,最好關(guān)閉。
database.close();4. 操作數(shù)據(jù)庫
對(duì)數(shù)據(jù)庫進(jìn)行操作需要用到QSqlQuery類,操作前必須定義一個(gè)對(duì)象。下面舉例說明操作方法。操作需要使用SQLite語句,本文中的幾個(gè)例子會(huì)使用幾個(gè)常用的語句,關(guān)于SQLite語句的具體信息請(qǐng)參考SQLite相關(guān)資料。
例1:創(chuàng)建表格
創(chuàng)建一個(gè)名為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)第一行定義一個(gè)QSqlQuery對(duì)象。
(2)第二行是一個(gè)QString,其中的內(nèi)容是SQLite語句。對(duì)數(shù)據(jù)庫的操作,都是用SQLite的語句完成的,把這些指令以QString類型,通過prepare函數(shù),保存在QSqlQuery對(duì)象中。也可將指令,以QString形式直接寫在exec()函數(shù)的參數(shù)中,例如:
創(chuàng)建表格語句:create table <table_name> (f1 type1, f2 type2,…);
create table是創(chuàng)建表格的語句,也可用大寫CREATE TABLE;student是表格的名稱,可以任意取;括號(hào)中是表格的格式,上述指令表明,表格中有三列,第一列的名稱(表頭)是id,這一列儲(chǔ)存的數(shù)據(jù)類型是int,第二列名稱是name,數(shù)據(jù)類型是字符數(shù)組,最多有30個(gè)字符(和char(30)的區(qū)別在于,varchar的實(shí)際長(zhǎng)度是變化的,而char的長(zhǎng)度始終是給定的值),第三列的名稱是age,數(shù)據(jù)類型是int。
如果sql_query.exec()執(zhí)行成功,則創(chuàng)建表格成功。
例2:插入數(shù)據(jù)
在剛才創(chuàng)建的表格中,插入一行數(shù)據(jù)。
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()是要插入的數(shù)據(jù)。這里,我們插入了2組數(shù)據(jù)。插入第一組數(shù)據(jù)的時(shí)候,用addBindValue來替代語句中的?,替代的順序與addBindValue調(diào)用的順序相同。插入第二組數(shù)據(jù)的時(shí)候,則是直接寫出完整語句。
例3:更新數(shù)據(jù)(修改數(shù)據(jù))
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用于確定是哪一組數(shù)據(jù),:id也是待定變量。
bindValue(" ", " ")函數(shù)用來把語句中的待定變量換成確定值。
例4:查詢數(shù)據(jù)
(1)查詢部分?jǐn)?shù)據(jù)
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>?等等是要查詢的變量(即表頭),中間用逗號(hào)隔開;from ...指定表格。
上述語句是說查詢student表中的 id 和 name 。執(zhí)行查詢之后,用sql_query.value(int)來獲得數(shù)據(jù)。同樣地,value(0)表示第一個(gè)數(shù)據(jù),即 id,value(1)表示name。注意:value()函數(shù)的返回值類型是QVariant,因此要用toInt()等函數(shù)轉(zhuǎn)換成特定的類型。
(2)查詢?nèi)繑?shù)據(jù)
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>;
查詢所有數(shù)據(jù)用 * 表示。用while(sql_query.next())用來遍歷所有行。同樣用value()獲得數(shù)據(jù)。
(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);
}
}
這個(gè)就是在語句中用max來獲取最大值。
例5:刪除與清空
(1)刪除一條數(shù)據(jù)
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給出限制,就會(huì)刪除所有內(nèi)容。
?
總結(jié)
以上是生活随笔為你收集整理的QT操作sqlite数据库汇总的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mybatis 中更新方法: updat
- 下一篇: sqlite使用模糊查询数据库数据的三种