SQLite“在删除CASCADE上”未在Qt中级联

时间:2018-11-25 12:08:49

标签: c++ qt sqlite

我在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
);

表部件中的类型是外键,是指表子组中的列子。 表子组中的main是外键,指的是表主组中的列组名。 我的问题是,当我在数据库浏览器中尝试(delete from maingroup WHERE groupName= 'dd';)时,它同时删除了父级和子级。 但是在QT中,此命令(myQuery.exec("delete from maingroup WHERE groupName= 'dd'");)仅删除主组表中的父字段,而不删除子组和零件表中的子字段,并且子组表中的主列引用主组表中不存在的字段。 这是怎么了?我该怎么办?

2 个答案:

答案 0 :(得分:2)

您需要通过在DELETE语句之前执行另一条语句来打开外键编译指示。

QSqlQuery q;
q.exec("PRAGMA foreign_keys = ON");
q.exec("DELETE FROM ...");

这能够级联删除操作,也应该足以解决其他与外键有关的问题。

获得this forum.qt.io帖子的赠送金额。

答案 1 :(得分:0)

除了@TrebledJ正确且非常有用的答案外,值得一提的是有关外键编译指示的两个附加特征(与Qt关联):

1。编译指示也可以通过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 ...