テーブル '人物'には、次の列があります。 id、name、manager_id。 'id'は主キーで、 'manager_id'は外部キーです。管理者がいる人もいるので、この値はNULLにすることができます。しかし、これはQtのQSqlRelationalTableModelに問題を引き起こすようです。ここで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;
};
問題は、第二のレコード(すなわち、 "ボブ" ということですマネージャのIDが無効(-1)なので表示されません。
QSqlRelationalTableModelのドキュメントには、 が記載されています。「リレーショナル表には、参照先表の存在しない行を参照するキーが含まれていると、無効なキーを含む行はモデルを通じて公開されません。参照整合性を維持する責任があります。
しかし、これを回避する手段はありませんか?これは共通の問題だと私には思われます。ありがとう。
私が思いつくことができる "汚い"解決策は、テーブルに「ダミー」行を追加し、それに応じて値を変更することです。query.exec(「人の値(1、 ''、-1) ");しかし、これはかなり厄介なようです。 – user1829358