我的架构中有多个关系.例如,一个包有许多任务组,任务组又有许多任务.所有表都通过多个表链接在一起,例如包含主键和taskgroup的主键.(我知道这不是严格需要的,因为XML是一对多的,但我想不出更好的结构).
是否可以将查询结果作为XML来反映一对多结构?所以,结果应该是这样的:
<package id=1>
<taskgroup id=1>
<task id=1>
<task id=2>
</taskgroup>
<taskgroup id=2>
<task id=3>
</taskgroup>
</package>
Run Code Online (Sandbox Code Playgroud)
通过使用XMLELEMENT()和XMLATTRIBUTE()函数来获取所有任务,我已经设法获得了我想要的一部分.像这样:
SELECT XMLELEMENT(name task,
XMLATTRIBUTES(p.name as packageName),
XMLELEMENT(name description, t.description),
XMLELEMENT(name tutorial,
XMLELEMENT(name someTaskChild1, t.data1)),
XMLELEMENT(name objectives,
XMLELEMENT(name someTaskChild2, t.data2)),
)
FROM packages p
INNER JOIN package_taskgroup pt ON p.id = pt.package_id
INNER JOIN taskgroups tg on pt.taskgroup_id = tg.id
INNER JOIN taskgroup_task tt on tg.id = tt.taskgroup_id
INNER JOIN tasks t on tt.task_id = t.id
WHERE p.id = …Run Code Online (Sandbox Code Playgroud) 我试图在事务范围内获取插入行的主键,因为我不想让db处于逻辑上不一致的状态.
我的问题是我找不到一种方法来检索先前执行的查询的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();
}
Run Code Online (Sandbox Code Playgroud) 以下代码失败QSqlQuery::exec().当我在没有预准备语句参数的情况下运行查询时,它会返回正确的结果,可以通过预期获得QSqlQuery::next()
executedQuery()报告":username"实际上没有被参数替换,但是有一个?(是否应该,因为查询没有成功执行?).
db_是一个QSqlDatabase类变量和isOpen()报告true.Qt框架版本是4.7.3.
DBSql::userInfo(const QString &username,
QString &passwd,
QString &name,
UserPriv priv)
{
QSqlQuery userQuery(db_);
const QString userStr("SELECT u.id, u.fullname, u.password, p.description \
FROM users u INNER JOIN privilege p ON u.privilege_id = p.id \
WHERE u.username = :username");
userQuery.bindValue(":username", username);
if (!userQuery.prepare(userStr))
std::cout << "prepare failed" << std::endl;
if (userQuery.exec()) {
while (userQuery.next()) {
userId = userQuery.value(0).toInt();
name = userQuery.value(1).toString();
passwd = userQuery.value(2).toString();
const QString privilegeDesc …Run Code Online (Sandbox Code Playgroud)