在 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
是为了防止 ROLLBACK
或 RELEASE
拒绝
或者,使用 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
我曾尝试在 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
是为了防止 ROLLBACK
或 RELEASE
拒绝
或者,使用 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