我们说我有一张桌子'使用以下列: 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;
然而,这是否有办法解决?在我看来,这是一个常见的问题。感谢。
答案 0 :(得分:1)
根据您对数据的描述,“没有经理”是允许值,因此将其称为无效是没有意义的。
您的示例中的真正问题是name
列有几个重叠的目标。它应该是一个单独的names
表,然后可以有一个空字符串的行来表示“没有经理”。
person
表只包含names
表中的ID。