Очень поучительная ситуация возникла с использованием setData в переопределенной модели QSqlRelationalTableModel.

Изначально через setData нормально устанавливались все значения (и возвращалось true) кроме установки через setData значения по умолчанию (у нас 0). При установке 0 возвращалось всегда false. У нас на картинке установка в 0 означает очистить поле (поставщик) :

Все становится понятно , если переопределить setData и потом просто зайти отладчиком внутрь функции :
QSqlRelationalTableModel::setData(item , value , role);
Возврат происходит в указанном ниже условии :
bool QSqlRelationalTableModel::setData(const QModelIndex &index, const QVariant &value,
int role)
{
Q_D(QSqlRelationalTableModel);
if ( role == Qt::EditRole && index.column() > 0 && index.column() < d->relations.count()
&& d->relations.value(index.column()).isValid()) {
QRelation &relation = d->relations[index.column()];
if (!relation.isDictionaryInitialized())
relation.populateDictionary();
if (!relation.dictionary.contains(value.toString())) // !!!!!!!! здесь !!!!!!!!
return false;
}
return QSqlTableModel::setData(index, value, role);
}
Теперь можно не вникая в суть почему так происходит просто заменить вызов setData на вызов из более раннего предка , то есть из QSqlTableModel:
return QSqlTableModel::setData(item , value , role);
И все заработает как надо , то есть при установке через setData значения 0 будет уже возвращаться true.
Но теперь мы для себя можем открыть некоторые новые подробности использования QSqlRelationalTableModel. А именно , что такое dictionary :

В relation.dictionary у нас присутствуют все 5 значений из relation таблицы. Вот содержание таблицы поставщиков:

relation.dictionary это QHash<QString, QVariant> dictionary в cnherneht QRelation
struct QRelation
{
public:
QRelation(): model(0),m_parent(0),m_dictInitialized(false){}
void init(QSqlRelationalTableModel *parent, const QSqlRelation &relation);
void populateModel();
bool isDictionaryInitialized();
void populateDictionary();
void clearDictionary();
void clear();
bool isValid();
QSqlRelation rel;
QRelatedTableModel *model;
QHash<QString, QVariant> dictionary;//maps keys to display values
private:
QSqlRelationalTableModel *m_parent;
bool m_dictInitialized;
};
Вывод такой : Если dictionary это набор значений id строковое представление связи , то значение "0" не появится в dictionary никогда , так как поле id в таблице поставщиков и не сможет никогда стать равным 0! Все логично.
Вот такой вот нюанс!....