您的当前位置:首页正文

深入QSqlQuery

2023-11-25 来源:步旅网


在上一节中,我们直接调用QSqlQuery:exec()对数据库进行增删改查等简单操作。

在项目开发中,为了实现系统的低耦合,我们就必须封装出一个数据库功能模块。

一、prepare()

首先创建一个头文件\"attend_db.h\"。

初始化数据库操作,包括创建数据库文件、建表、以及添加一些基础数据。最好还要返回数据库操作的一些信息(最重要的是错误信息)。

[cpp] view plaincopyprint?

1. QSqlError db_Init()

2. {

3. QSqlDatabase db = QSqlDatabase::addDatabase(\"QSQLITE\");

4. db.setDatabaseName(\":memory:\"); //使用内存数据库

5. if(!db.open())

6. {

7. //打开失败

8. return db.lastError();

9. }

10. QSqlQuery query;

11. //创建组别表,人员表,考勤记录表

12. if(!query.exec(\"CREATE TABLE table_group(group_id INTEGER PRIMARY KEY, group_name VARCHAR)\"))

13. {

14. return query.lastError();

15. }

16. if(!query.exec(\"CREATE TABLE table_user(user_id VARCHAR PRIMARY KEY, group_id INTEGER)\"))

17. {

18. return query.lastError();

19. }

20. if(!query.exec(\"CREATE TABLE table_record(user_id VARCHAR, datetime VARCHAR)\"))

21. {

22. return query.lastError();

23. }

24. //添加组别数据

25. if(!query.prepare(\"INSERT INTO table_group(group_id, group_name) VALUES(:gourp_id, :group_name)\"))

26. {

27. return query.lastError();

28. }

29. db_AddGroup(query, 1, \"student\");

30. db_AddGroup(query, 2, \"teacher\");

31. //添加人员数据

32. if(!query.prepare(\"INSERT INTO table_user(user_id, group_id) VALUES(:user_id, :group_id)\"))

33. {

34. return query.lastError();

35. }

36. db_AddUser(query, \"T0001\

37. qdb_AddUser(query, \"T0002\

38. db_AddUser(query, \"S111201\

39. //添加考勤记录数据

40. if(!query.prepare(\"INSERT INTO table_record(user_id, datetime) VALUES(:user_id, :datetime)\"))

41. {

42. return query.lastError();

43. }

44. db_AddRecord(query, \"T0001\ 45. db_AddRecord(query, \"T0002\ 46. db_AddRecord(query, \"S111201\ 47. return QSqlError(); 48. } QSqlError db_Init(){ QSqlDatabase db = QSqlDatabas db.setDatabaseName(\":memory:\"这里对表的添加数据不再简单的使用QSqlQuery:exec()直接执行语句了。为了模块化,我们还要封装出对表数据的操作函数(包括增删改查)。 提供对外的接口供上层应用使用。形参最好就仅仅是表的参量,这样清晰明了。 Qt提供了bool prepare(const QString& query)接口。(SQLite也提供了该API函数) [cpp] view plaincopyprint? 1. query.prepare(\"INSERT INTO table_group(group_id, group_name) VALUES(:gourp_id, :group_name)\")

query.prepare(\"INSERT INTO tabl我们先使用了prepare()函数,在其中利用了“:group_id”和“:group_name”来代替具体的数据,之后就可以利用bindValue()函数给group_id和group_name两个属性赋值,这称为绑定操作。 例: [cpp] view plaincopyprint? 1. query.bindValue(0, 1); 2. query.bindValue(1, 'student'); query.bindValue(0, 1); query.bindValue(1, 'student'); 其中编号0和1分别代表“:group_id”和“:group_name”,就是说按照prepare()函数中出现的属性从左到右编号,最左边是0 。这里的“:group_id”和“:group_name”,叫做占位符,这是ODBC数据库的表示方法,还有一种Oracle的表示方法就是全部用“?”号。 [cpp] view plaincopyprint? 1. query.prepare(\"INSERT INTO table_group(group_id, group_name)

VALUES(?, ?)\") query.prepare(\"INSERT INTO tabl 这是对单条记录的绑定,当然绑定完还是要调用exec()的,否则语句不会被执行。 当用ODBC的表示方法时,我们也可以将编号用实际的占位符代替。这里就不具体介绍了。 我们也可以进行批量处理 [cpp] view plaincopyprint? 1. void addBindValue(const QVariant& val, QSql::ParamType type = QSql::In); void addBindValue(const QVaria通过调用addBindValue()增加值val值列表。 [cpp] view plaincopyprint? 1. QVariantList GroupIDs; 2. GroupIDs << 1 << 2;

3. QVariantList GroupNames; 4. GroupNames << \"student\" << \"teacher\"; 5. query.addBindValue(GroupIDs); 6. query.addBindValue(GroupNames); 7. query.execBatch(); QVariantList GroupIDs; GroupIDs << 1 << 2; QVariantList GroupNames; GroupNames << \"student\" << \"查看下ececBatch()的文档。 /* Executes a previously prepared SQL query in a batch. All the bound parameters have to be lists of variants. If the database doesn't support batch executions, the driver will simulate it using conventional exec() calls. */ 如果数据库不支持批量处理,则用exec()来代替。 二、执行SQL语句后返回的结果集

/*下文不是原创、存属转载*/

结果集其实就是查询到的所有记录的集合,而在QSqlQuery类中提供了多个函数来操作这个集合,需要注意这个集合中的记录是从0开始编号的。最常用的有:

seek(int n) :query指向结果集的第n条记录。

first() :query指向结果集的第一条记录。

last() :query指向结果集的最后一条记录。

next() :query指向下一条记录,每执行一次该函数,便指向相邻的下一条记录。

previous() :query指向上一条记录,每执行一次该函数,便指向相邻的上一条记录。

record() :获得现在指向的记录。

value(int n) :获得属性的值。其中n表示你查询的第n个属性,比方我们使用“select * from student”就相当于“select id, name from student”,那么value(0)返回id属性的值,value(1)返回name属性的值。该函数返回QVariant类型的数据,关于该类型与其他类型的对应关系,可以在帮助中查看QVariant。

at() :获得现在query指向的记录在结果集中的编号。

需要说明,当刚执行完query.exec(“select * from student”);这行代码时,query是指向结果集以外的,我们可以利用query.next(),当第一次执行这句代码时,query便

指向了结果集的第一条记录。当然我们也可以利用seek(0)函数或者first()函数使query指向结果集的第一条记录。但是为了节省内存开销,推荐的方法是,在query.exec(“select * from student”);这行代码前加上query.setForwardOnly(true);这条代码,此后只能使用next()和seek()函数。

因篇幅问题不能全部显示,请点此查看更多更全内容