Qt:QSqlRelationalTableModel引用不存在的外键

时间:2016-11-01 16:03:29

标签: c++ qt sqlite pyqt qt5

我们说我有一张桌子'使用以下列: id,name,manager_id。在哪里' id'是主键,' manager_id'是外键。由于某些人现在可能拥有管理员,因此允许该值为NULL。但是,这似乎给Qt的QSqlRelationalTableModel带来了问题。

这是一个复制问题的简约示例: window.cpp:

Window::Window(QWidget *parent) : QWidget(parent)
{
// setup database
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
db.open();

// create database
QSqlQuery query;
query.exec("create table 'person' (id INTEGER NOT NULL PRIMARY KEY, "
           "name varchar(20), manager_id INTEGER NULL)");
query.exec("insert into person values(1, 'Alice', 2)");
query.exec("insert into person values(2, 'Bob', -1)"); // invalid manager_id
//query.exec("insert into person values(2, 'Bob', 1)"); // valid example

// setup model
model = new QSqlRelationalTableModel(this);
model->setTable("person");
model->setEditStrategy(QSqlTableModel::OnRowChange);

// setup foreign key
int typeIndex = model->fieldIndex("manager_id");
model->setRelation(typeIndex, QSqlRelation("person", "id", "name"));
model->select();

// setup UI
auto nameLabel = new QLabel(tr("Name:")); auto nameEdit = new QLineEdit();
auto typeLabel = new QLabel(tr("Manager:")); auto typeComboBox = new QComboBox();
auto nextButton = new QPushButton(tr("Next"));
auto previousButton = new QPushButton(tr("Previous"));
QSqlTableModel *relModel = model->relationModel(typeIndex);
typeComboBox->setModel(relModel);
typeComboBox->setModelColumn(relModel->fieldIndex("name"));
QGridLayout *layout = new QGridLayout();
layout->addWidget(nameLabel, 0, 0, 1, 1);
layout->addWidget(nameEdit, 0, 1, 1, 1);
layout->addWidget(previousButton, 0, 2, 1, 1);
layout->addWidget(nextButton, 1, 2, 1, 1);
layout->addWidget(typeLabel, 2, 0, 1, 1);
layout->addWidget(typeComboBox, 2, 1, 1, 1);
setLayout(layout);

// setup mapper
mapper = new QDataWidgetMapper(this);
mapper->setModel(model);
mapper->setItemDelegate(new QSqlRelationalDelegate(this));
mapper->addMapping(nameEdit, model->fieldIndex("name"));
mapper->addMapping(typeComboBox, typeIndex);
mapper->toFirst();

connect(previousButton, SIGNAL(clicked()), mapper, SLOT(toPrevious()));
connect(nextButton, SIGNAL(clicked()), mapper, SLOT(toNext()));
}

window.h中:

#include <QWidget>
class QDataWidgetMapper;
class QSqlRelationalTableModel;
class Window : public QWidget
{
    Q_OBJECT
public:
    Window(QWidget *parent = 0);
private slots:
private:
    QDataWidgetMapper *mapper;
    QSqlRelationalTableModel *model;
};

问题是第二条记录(即&#34; Bob&#34;)将不会显示,因为他的经理的身份无效(-1)。

QSqlRelationalTableModel的文档说明: &#34;如果关系表包含引用引用表中不存在的行的键,则包含无效键的行将不会通过模型公开。用户或数据库负责保持参照完整性。&#34;

然而,这是否有办法解决?在我看来,这是一个常见的问题。感谢。

1 个答案:

答案 0 :(得分:1)

根据您对数据的描述,“没有经理”是允许值,因此将其称为无效是没有意义的。

您的示例中的真正问题是name列有几个重叠的目标。它应该是一个单独的names表,然后可以有一个空字符串的行来表示“没有经理”。

person表只包含names表中的ID。