【发布时间】:2012-11-27 23:08:59
【问题描述】:
我试图在事务范围内获取插入行的主键,因为我不想让数据库处于逻辑上不一致的状态。
我的问题是我找不到一种方法来检索以前执行的查询的 ID 值,我想将其用于下一个插入查询。在事务生效时查询 PostgreSQL 数据库在非外键表中显示没有结果(该行尚未提交?)。我相信这是由于事务的隔离级别造成的。
以下是我正在尝试对生产代码执行的操作,尽管为了清晰起见,对其进行了轻微编辑并缩小为一个功能。 const int lastInsertId 始终为 0,在这种情况下应该意味着没有找到任何值(从技术上讲,toInt() 函数失败了)。我尝试手动插入一个有效的非外键行,然后调用LASTVAL() 产生预期的结果 - 插入行的 ID。
那么,我做错了什么?我在这里遗漏或误解了什么?
void createEntityWithoutForiegnKeyConstraint(const QString &nameOfEntity)
{
db_.transaction();
QSqlQuery insertQuery(db_);
insertQuery.prepare("INSERT INTO \"EntityWithoutForeignKey\" (\"name\") VALUES (:name);");
insertQuery.bindValue(":name", nameOfEntity);
execQuery(__LINE__, insertQuery);
QSqlQuery lastIdQuery("SELECT LASTVAL();", db_); // auto executes
const int lastInsertId = lastIdQuery.value(0).toInt();
if (lastInsertId <= 0) // 0 is not a valid ID
throw exception("Oh noes.");
createEntityWithForeignKeyConstraint(lastInsertId, someData);
if (!db_.commit())
db_.rollback();
}
【问题讨论】:
-
同意;
INSERT ... RETURNING是这里的理想选择。详情请参阅INSERTdocumentation。 -
已确认 RETURNING 从 pgAdmin 用于测试插入,例如
INSERT INTO nonforeignkeyentity ("id", "name") VALUES (DEFAULT, 'teste') RETURNING "id"。但这不适用于QSqlQuery,所以我在这里仍然需要指导。如何从查询对象中检索该值。我必须为返回值绑定一个变量吗? -
insertQuery.record().indexOf("id");返回 0,根据 Qt 文档,这是一个有效的索引。我真的很慌张。如果该字段存在,为什么那里没有值? -
您可能必须在获取值之前调用 insertQuery.next()。
标签: qt transactions qtsql