Nehmen wir an, ich habe eine Tabelle 'Person' mit den folgenden Spalten: ID, Name, Manager-ID. Dabei ist "id" der Primärschlüssel und "manager_id" der Fremdschlüssel. Da einige Leute jetzt einen Manager haben, darf dieser Wert NULL sein. Dies scheint jedoch Probleme mit dem QSqlRelationalTableMod von Qt zu verursachen.Qt: QSqlRelationalTableModel Verweis auf nicht vorhandene Fremdschlüssel
Hier ist ein minimalistisches Beispiel, das das Problem repliziert: 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;
};
Das Problem ist, dass der zweite Datensatz (dh "Bob") wird nicht angezeigt, da die ID seines Managers ungültig ist (-1).
Die Dokumentation der QSqlRelationalTableModel -Statements: "Wenn eine relationale Tabelle Schlüssel enthält, die auf nicht vorhandene Zeilen in der referenzierten Tabelle verweisen, werden die Zeilen mit den ungültigen Schlüsseln nicht über das Modell verfügbar gemacht ist verantwortlich für die referentielle Integrität. "
Aber gibt es keinen Weg um diese? Es scheint mir, dass dies ein häufiges Problem ist. Vielen Dank.
Eine "dreckige" Lösung, die ich finden könnte, ist das Hinzufügen einer 'Dummy'-Zeile in die Tabelle und dann das Ändern der Werte entsprechend: query.exec ("in person values (1,' ', -1) einfügen ") ;. Aber das scheint ziemlich eklig zu sein. – user1829358