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中级联的主要内容,如果未能解决你的问题,请参考以下文章

sql中级联删除,级联更新是怎么理解的?

sqlite 数据库 相关知识

在 MFC MDI 应用程序中级联特定窗口

首先在实体框架数据库中级联删除

使用 UNION 在 VIEW 中级联 WHERE 子句

在SQL / Oracle中级联