【问题标题】:Retrieve Interim Results in SQL Transaction在 SQL 事务中检索中间结果
【发布时间】:2021-08-28 15:48:34
【问题描述】:

我曾尝试用 JavaScript 编写 SQL-Transaction,但偶然发现了两个我似乎无法弄清楚的问题。

a) 这总是给我一个UnhandledPromiseRejectionWarning。我只是不知道自己做错了什么,也不知道如何正确处理带有承诺的错误。在每个 .then() 之后捕获它们也没有奏效

b) 有没有办法在交易中获得临时结果,以便我可以让我的 result.insertId 工作?我仍然希望在每次查询后回滚。

return db.promise().query("START TRANSACTION") // db is a sql pool
    .then(() => {
    return db.promise().query(
        SqlString.format( 
        `INSERT INTO Standort (Street, Number, City, PLZ) 
        VALUES('${street}',${number},'${city}',${plz})`
        )
    )
    })
    .then ((result) => { 
    console.log("first result: " + result.insertId);
    return db.promise().query(
        SqlString.format( 
        `INSERT INTO Table1 (Table1ID) 
        VALUES(${result.insertId})`
        )
    )
    })
    .then((result) => { 
    return db.promise().query(
        SqlString.format(
        `INSERT INTO Table2 (Name, Table2ID) 
        VALUES('${vorname}', ${result.insertId})`
        )
    )
    })
    .then((result) => { 
    return db.promise().query(
        SqlString.format(
        `INSERT INTO Table3 (Email, Table3ID) 
        VALUES( '${email}',${result.insertId})`
        )
    )
    })
    .then((result) => {
        return db.promise().query("COMMIT");
    })
    .catch((error) => { 
        console.log(error); 
        db.promise().query("ROLLBACK"); 
        db.promise().query("RELEASE");
    }
    );

【问题讨论】:

  • @Bravo 所以你的意思是没有办法在两者之间得到结果?
  • @Bravo 好的,如果我在每个 db.promise().query(.. 之前运行 return 并将 db.promise().query("COMMIT"); 移动到它自己的 .then() 它仍然没有给我查询结果并抛出 UnhandledPromiseRejectionWarning
  • 对不起,恐怕我不明白..我究竟需要把等待放在哪里?请您把您的建议作为答案吗?
  • 引用前面的每一个查询结果,所以每一个结果都传入.then
  • 是的,第一个结果已经是未定义的。错误是sqlMessage: "Unknown column 'undefined' in 'field list'"

标签: javascript sql promise transactions


【解决方案1】:

result.insertId 的问题在于 result 是一个数组

你想要result[0].insertId

您获得UnhandledPromiseRejectionWarning 的原因是因为您在.catch( 中抛出了一个未处理的错误

这很可能是因为您实际上是“并行”执行两个查询 - 您需要将这些查询链接如下:

您将result 设为undefined 的原因是您没有返回 .then 中的任何内容(原始代码有问题 - 现在已编辑)

最后,根据 cmets,result.insertID 将是 undefined,因为插入 ID 在 result.insertId 中返回 - 大小写很重要

return db.promise().query("START TRANSACTION") // db is a sql pool
.then(() => {
    return db.promise().query(
        SqlString.format(
            `INSERT INTO Standort (Street, Number, City, PLZ) 
        VALUES('${street}',${number},'${city}',${plz})`));
})
.then((result) => {
    console.log("first result: " + result);
    return db.promise().query(
        SqlString.format(
            `INSERT INTO Table1 (Table1ID) 
        VALUES(${result[0].insertId})`));
})
.then((result) => {
    return db.promise().query(
        SqlString.format(
            `INSERT INTO Table2 (Name, Table2ID) 
        VALUES('${vorname}', ${result[0].insertId})`));
})
// note this alternative syntax ... ([result])
.then(([result]) => {
    return db.promise().query(
        SqlString.format(
            `INSERT INTO Table3 (Email, Table3ID) 
        VALUES( '${email}',${result.insertId})`));
})
.then((result) => {
    return db.promise().query("COMMIT");
})
.catch((error) => {
    console.log(error);
    return db.promise().query("ROLLBACK").then(() => db.promise().query("RELEASE"))
})
.catch((error) => {
    // error in rollback or release!
    console.log(error);
})

添加的.catch 存在以防ROLLBACKRELEASE 拒绝

或者,将 async/await 与 try/catch 一起使用: (删除了 SQL 查询,因为它们没有改变)

async function someFunction() {
    // ...
    // ...
    try {
        await db.promise().query("START TRANSACTION"); // db is a sql pool
        let result = await db.promise().query(.....);
        console.log("first result: " + result);
        result = await db.promise().query(.....);
        result = await db.promise().query(.....);
        // note the syntax change here too
        // either syntax can be used
        // just means you either use result[0].insertId
        // or result.insertId
        [result] = await db.promise().query(.....);
        return db.promise().query("COMMIT");
    } catch(error) {
        console.log("Error inserting records");
        console.log(error);
        try {
            await db.promise().query("ROLLBACK");
            return db.promise().query("RELEASE");
        } catch {
            console.log("Error in ROLLBACK/RELEASE");
            console.log(error);
        }
    }
}

看到您的代码在第一行中使用 return,我可以放心地假设您在 function 中 - 只需将其设为 async function

【讨论】:

  • 在执行您的(第一个)解决方案后,我仍然遇到相同的错误。我认为除了 UnhandledPromiseRejection 之外的主要问题是我无法访问结果。尤其是第一个,因为表中有一个 INSERT,所以显然必须有一个结果..
  • 对不起,我的错。 result.insertID 未定义
  • 我正在使用包 mysql2 并使用该包在我的本地实例上创建了一个池。
  • first result: [{"fieldCount":0,"affectedRows":1,"insertId":25,"info":"","serverStatus":3,"warningStatus":0},null]
  • 好吧,我不知道为什么这次的结果 obejct 看起来不一样。但问题是我尝试使用 result.insertId 而不是 result[0].insertId 来访问它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
相关资源
最近更新 更多