QT自带的QSqlite数据库中实现id主键自增长
QSqlite是QT自带的轻量级数据库,使用起来非常方便,对系统环境也没有任何的环境要求,可移植性非常好,适合数据量不是太大,要求不是太高的程序。本文中,就介绍一点,怎么实现在QSqlite中的数据表实现id自增长,方法很简单。
一、创建数据表时,主键设置为id,并且数据类型设置为integer。设置成integer的主键,默认自增长。
create table m_table (id integer primary key,m_equip varchar(10),m_place varchar(10))
二、使用插入命令的时候,要注意对应关系。
QString(insert into %1 (Name,Place) value(’%2’,’%3’)").arg(“computer”).arg(“office”);
Name和Place是我生成的表的列名,后面是数值。一开始我为了图省事,省略了列名,如下
QString(insert into %1 value(’%2’,’%3’)").arg(“computer”).arg(“office”);//错误示范
因此一直无法实现自增长插入。
SQLite设置主键自动增长及插入语法
SQLite中,一个自增长字段定义为INTEGER PRIMARY KEY AUTOINCREMENT,那么在插入一个新数据时,只需要将这个字段的值指定为NULL,即可由引擎自动设定其值,引擎会设定为最大的rowid+1。如果表為空,那麼將會插入1。
比如,有一張表ID為自增:
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name NVARCHAR(100) NOT NULL
)
那麼,插入的SQL就是:
INSERT INTO Product VALUES(NULL, '產品名稱')
GO
SQLite中不支持关键字top
select top 1 oid from orderinfo order by oid desc ; (×)
select oid from orderinfo order by oid desc limit 0,1;(√)
网上查到资料说,从 SQLite 的 2.3.4 版本开始,如果将一个表中的一个字段声明为 INTEGER PRIMARY KEY,那么只需向该表的该字段插入一个 NULL 值,这个 NULL 值将自动被更换为比表中该字段所有行的最大值大 1 的整数;如果表为空,那么将被更换为 1。
CREATE TABLE "ProcessList"([Id] integer(4) PRIMARY KEY,[Type] varchar(20),[Name] varchar(30),[IsUse] int ) 执行insert into processlistvalues(null,'a','b',1) 在逻辑意义上等价于:insert into processlist VALUES((SELECT max(Id) FROM processlist)+1, 'a','b',1);
insert into processlistvalues(null,'aa','bb',1) 执行两条插入语句后再查询表中数据:select * from processlist 结果如下:
Id Type Name IsUse1 a b 1 2 aa bb 1 一个新的API函数 sqlite3_last_insert_rowid() 返回最近的插入操作的整形键.注意这个整型键始终比之前插入表中的最后一个键大1。新键相对于表中的已有键来说是唯一的, 但它可能与之前从表中删除的键值重叠。要始终得到在整个表中唯一的键,在INTEGER PRIMARY KEY的声明之前加关键词AUTOINCREMENT.这样被选的键将总是比表中已存在的最大键大1。若可能的最大键已存在于表中,INSERT操作将失败并返回一个SQLITE_FULL错误码
创建数据表格,设置主键自增
创建数据库时,启用主键自增加特性
Create table testTable (id INTEGER PRIMARY KEY AUTOINCREMENT,。。。。
注意事项:设置主键自增时(AUTOINCREMENT),主键类型必须是INTEGER,不能使用INT,否则会报错。
插入数据后,获取自增的主键值
QSqlQuery::exec(“SELECT last_insert_rowid()”);
QSqlQuery::next();
int id = QSqlQuery::value(0).toInt(&ok);
或者使用
QSqlQuery::lastInsertId()).toInt();
//*************************************************************sqlite操作概念2
QT & sqlite3:
先说一下QT自带数据库sqlite3和另外用sqlite3插件的区别,他们的功能是一样的,但是代码就不一样了。QT对数据库具有完善的支持,不需要加任何其他插件就可以直接使用,但是如果你要是加了sqlite3插件,调用数据库就跟直接调用一个驱动一样,直接调用接口函数:open、close、……,换言之QT自带的数据库语言就用不上了。
一、使用Qt自带的数据库sqlite3
Qt自带了很多常用的数据库驱动,使用起来非常方便如下图所示:
使用Qt自带数据库SQLite3的代码实例:
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 );
//创建连接
QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE" );//第二个参数可以设置连接名字,这里为default
db.setDatabaseName( "./testdatabase.db" );// 设置数据库名与路径, 此时是放在上一个目录
//打开连接
if( !db.open() )
{
qDebug() << db.lastError();
qFatal( "Failed to connect." );
}
qDebug( "Connected!" );
//各种操作
QSqlQuery qry;
//创建table
qry.prepare( "CREATE TABLE IF NOT EXISTS names (id INTEGER UNIQUE PRIMARY KEY, firstname VARCHAR(30), lastname VARCHAR(30))" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug() << "Table created!";
//增
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (1, 'John', 'Doe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (2, 'Jane', 'Doe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (3, 'James', 'Doe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (4, 'Judy', 'Doe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (5, 'Richard', 'Roe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (6, 'Jane', 'Roe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (7, 'John', 'Noakes')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (8, 'Donna', 'Doe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Inserted!" );
qry.prepare( "INSERT INTO names (id, firstname, lastname) VALUES (9, 'Ralph', 'Roe')" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "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();
else
qDebug( "Updated!" );
qry.prepare( "UPDATE names SET lastname = 'Johnson' WHERE firstname = 'Jane'" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Updated!" );
//删除
qry.prepare( "DELETE FROM names WHERE id = 7" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Deleted!" );
qry.prepare( "DELETE FROM names WHERE lastname = 'Johnson'" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
qDebug( "Deleted!" );
db.close();
return 0;
}
二、Qt中使用sqlite3插件
1、安装sqlite3插件
从官方网站http://www.sqlite.org下载完整版本。
2、安装sqlite3
网上可以看到很多修改下载之后的源代码的论坛,我估计那些帖子比较老一点,最新版的代码已经不存在那些bug了,可以直接编译
*注意复制粘贴库函数的时候有的动态链接库如果单独复制会丢失之间的链接关系,所以需要一块复制
cp -arf libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 。。。
3、移植sqlite3
在QTE的include文件中建立新文件夹sqlite3,将头文件放到里面;把库文件放到QTE的lib文件中
4、编程代码实例:
(1) QT生成的.pro文件中添加库指令: LIBS += -lsqlite3
(2) 在调用数据库的文件的头文件里添加头文件和变量
#include "sqlite3/sqlite3.h"
sqlite3 *db; //数据库
char *zErrMsg; //出错信息
char **resultp; //调用时的保存位置
int nrow; //列数
int ncolumn; //行数
char *errmsg; //出错信息
(3)新建或打开数据库
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 是指定主键,每个数据库只能有一个,主键的值不能重复,比方说你设定name为主键,则相同名字的人只能保存第一个,其他的忽略不计。若想避免这种情况,则去掉主键或者设定id号为主键(id号一直加一,不会重复)。
(5)往表格里写入信息
a.直接添加数据
sqlite3_exec(db, "insert into person values('张翼', 30)", NULL, NULL, &zErrMsg);
sqlite3_exec(db, "insert into person values('hongdy', 28)", NULL, NULL, &zErrMsg);
b.添加数字变量
int data=10;
char sql2[100]; //必须写明大小,划分内存,如果只写一个 char *sql2,会出现段错误
sprintf(sql2,"insert into person values('张翼',%d);",data);
sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);
*sprintf的作用是字串格式化命令,主要功能是把格式化的数据写入某个字符串中
c.添加字符串变量
char data[]="张翼";
char sql2[100];
sprintf(sql2,"insert into person values('%s',10);",data);
sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);
* %s需要用单引号注释
d.添加text中的变量到数据库中
这里需要汉字编码的问题,Windows下默认GBK或GB2312编码,Linux下默认UTF-8编码,所以如果没有设置好会出现乱码
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 转char*
sprintf(sql2,"insert into person values('%s',%d);",abc,data);
sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);
*在调试的时候如果用串口超级终端调试的话,在ARM上显示正常,但是在串口是乱码,不要被迷惑
(6)查询、调用数据库
a. 查询全部
sqlite3_get_table(db, "select * from person", &resultp, &nrow, &ncolumn, &errmsg);
*resultp保存数据库信息,nrow返回列数,ncolumn返回列数
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);
*查询时使用变量的方法和添加时一样
(7)关闭数据库
sqlite3_close(db);
三、VS+QT使用SQL驱动
//1.添加SQL库:"Qt project setting"-->"Qt Modules",在SQL library复选框前打勾.或者在vs项目属性--》连接器--》输入里加入Qt5Sqllib
//2.添加头文件
//#include<QtSql>//这样写会报Cannot open include file: 'QtSql': No such file or directory,奇葩错误,因为QtSql只是一个文件夹
#include <QtSql/QSqlDatabase>//这样写可以
#include <QtSql/QSqlTableModel>
#include<QtSql/QSqlError>
//3.创建连接
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());
return
false
;
}
//4.查询数据
QSqlQuery query;
query.exec(
"select * from mytable"
);
while
(query.next())
{
.........
}
//***********************C++对数据库sqlite3的增、删、查、改基本操作
1、头文件定义
在头文件中声明以下变量和函数:
-
// 实现
-
public:
-
void initSqlite(); //初始化数据库
-
void initWindowShow();
-
void refreshList(); //刷新列表
-
public:
-
CString m_NameString; //姓名
-
CString m_ChineseString;
-
CString m_MathString;
-
CString m_EnglishString;
-
protected:
-
HICON m_hIcon;
-
// 生成的消息映射函数
-
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、初始化数据库
-
void CSqlite3Dlg::initSqlite()
-
{
-
//打开数据库
-
const string studentDB = "student.db";
-
//创建表格
-
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("数据库表格创建失败!");
-
}
-
}
3、插入操作
-
//插入数据
-
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);
-
//将当前插入的数据显示到列表控件中
-
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、删除数据
-
//删除数据
-
void CSqlite3Dlg::OnBnClickedDeleteBtn()
-
{
-
// TODO: 在此添加控件通知处理程序代码
-
if (m_NameString.IsEmpty())
-
{
-
MessageBox("请选择要删除的选项!");
-
return;
-
}
-
string selectName = m_NameString.GetBuffer();
-
string sql = "delete from " + student_table + " where Name=" + "'" + selectName + "'";
-
CSDDb::GetInstance().DeleteData(sql);
-
refreshList(); //重新刷新列表
-
}
5、修改数据
-
//修改数据
-
void CSqlite3Dlg::OnBnClickedModifyBtn()
-
{
-
// TODO: 在此添加控件通知处理程序代码
-
if (m_NameString.IsEmpty())
-
{
-
MessageBox("请选择要更新的选项!");
-
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)是一款开源轻量级的数据库软件,不需要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给出限制,就会删除所有内容。
来源:oschina
链接:https://my.oschina.net/u/4373527/blog/4517031