在 SQL 交易中检索中期结果

Retrieve Interim Results in SQL Transaction

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

a) 这总是给我一个 UnhandledPromiseRejectionWarning。我只是不知道自己做错了什么,也不知道如何正确地处理 promise 的错误。在每个 .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");
    }
    );

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

你想要result[0].insertId

您收到 UnhandledPromiseRejectionWarning 的原因是您在 .catch( 中抛出了一个未被处理的错误

这很可能是因为您本质上是“并行”执行两个查询 - 您需要按如下方式链接这些查询:

你会得到 result 作为 undefined 的原因是你没有在 .then 中返回任何东西(有问题的原始代码 - 现已编辑)

最后,根据评论,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