SQLite“在删除级联时”不在Qt中级联
Posted
技术标签:
【中文标题】SQLite“在删除级联时”不在Qt中级联【英文标题】:SQLite "On delete CASCADE" not cascading in Qt 【发布时间】:2018-11-25 12:08:48 【问题描述】:我在 Qt 中有一个数据库。 它有四个表:主组、子组、部件和位置。这是我的数据库:
CREATE TABLE `maingroup` (
`groupName`TEXT NOT NULL UNIQUE,
PRIMARY KEY(`groupName`)
);
CREATE TABLE `subgroup` (
`sub` TEXT NOT NULL UNIQUE,
`main` TEXT NOT NULL,
PRIMARY KEY(`sub`),
FOREIGN KEY(`main`) REFERENCES `maingroup`(`groupName`) ON DELETE CASCADE
);
CREATE TABLE `parts` (
`ID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`Part_Number` TEXT,
`Type` TEXT NOT NULL,
`Value` TEXT,
`Voltage` TEXT,
`Quantity` TEXT,
`Position` TEXT,
`Picture` TEXT,
FOREIGN KEY(`Position`) REFERENCES `Position`(`Poistion`) ON DELETE CASCADE,
FOREIGN KEY(`Type`) REFERENCES `subgroup`(`sub`) ON DELETE CASCADE
);
表部分中的类型是外键是指表子组中的列子。
表子组中的主是外键是指表主组中的列组名。
我的问题是当我在 DB 浏览器中尝试 (delete from maingroup WHERE groupName= 'dd';
) 时,它会删除父级和子级。
但是在 QT 中,这个命令(myQuery.exec("delete from maingroup WHERE groupName= 'dd'");
)只是删除了主组表中的父字段,而不是子组和部分表中的子字段,并且子组表中的主列是指主组表中不存在的字段。
这里有什么问题?我该怎么办?
【问题讨论】:
【参考方案1】:您需要通过在您的 DELETE 语句之前执行另一个语句来打开外键编译指示。
QSqlQuery q;
q.exec("PRAGMA foreign_keys = ON");
q.exec("DELETE FROM ...");
这可以级联删除,也应该足以解决其他与外键相关的问题。
感谢this forum.qt.io 的帖子。
【讨论】:
非常感谢。我认为它足以在 db 浏览器中启用它。【参考方案2】:除了@TrebledJ 正确且非常有帮助的答案之外,值得一提的是关于外键杂注的两个附加特征(与 Qt 相关):
1. pragma 也可以通过 QSqlDatabase 设置。
所以下面的代码和@TrebledJ的例子效果一样:
auto database = QSqlDatabase::database();
database.exec("PRAGMA foreign_keys = ON");
QSqlQuery query(database); // query "inherits" the pragma from database
query.exec("DELETE FROM ...");
2。即使在程序中的不同位置打开和使用数据库时,此行为也适用。
还是一样的效果:
初始化代码中的某处: // 这会隐式调用 database.open(),因为数据库之前没有打开。 自动数据库 = QSqlDatabase::database();
QSqlDatabase::database();
database.exec("PRAGMA foreign_keys = ON");
// make sure database.close() is NOT called!
代码中的其他地方
// you'll get the instance of your initialization code because database is already open (so QSqlDatabase::database() implements a singleton pattern).
// so pragma foreign_keys is still set to "ON"
auto database = QSqlDatabase::database();
QSqlQuery query(database);
query.exec("DELETE FROM ...");
如果您想了解为什么 foreign_keys 编译指示似乎只有时适用于您的项目(有时不适用),了解这一点可能很重要。
我做了什么
所以我得出结论,以确保在我的代码中有一个不同的位置来显式打开数据库(并配置连接):
QString dbConnectionName = "My project database";
auto database = QSqlDatabase::database(dbConnectionName, true);
// configure the pragmas here
在我避免(意外)打开数据库的所有其他地方:
auto database = QSqlDatabase::database(dbConnectionName, false);
// e.g. use the database via queries ...
【讨论】:
以上是关于SQLite“在删除级联时”不在Qt中级联的主要内容,如果未能解决你的问题,请参考以下文章