有没有一种方法可以在保存到数据库之前先插入两个相关行来检查错误
Is there a way to check for errors first from inserting in two related rows before saving in database
我目前正在将 job/task 列表作为学习 Web 开发的测试项目(REST API、Express.js、通过 pg-node 的 Postgresql 13)。
该结构是用户可以在各种任务和工作中添加员工。
- 1 个作业可以有多个任务
- 1 个任务可以有多个员工
- 员工在同一份工作中不能有超过 1 个任务,但可以在不同的工作中分配另一项任务。
UI 中的流程是一个模式,允许您填写工作详细信息(名称)、添加任务,然后分配员工执行上述任务。
我目前拥有的是创建两个在单击“创建”按钮时发送的端点,一个用于创建工作,第二个用于创建员工并将其分配给任务,因为我需要附加 job_id 到任务,我不能做,直到它已经 generated/created。这样做的问题是,在插入任务出错的情况下,作业已经创建并保存在数据库中,而无法分配任务和员工,导致在 [= 中的“创建”按钮时发生冲突48=].
我想要做的(如果可能的话)是创建一个查询,该查询将同时创建和插入工作以及初始任务和员工分配。如果在整个事务期间发生错误(例如,由于数据类型错误等条件失败导致任务插入失败),查询将不会将该作业保存在数据库中。
DB Fiddle 架构:https://www.db-fiddle.com/f/izPsVVxPZ8e9ZMPwbL9her/10
这是我的 2 条路线:
//Create Job
const {
name
} = req.body;
const job = await pool.query(`SELECT * FROM jobs WHERE
name = )`, [
job_name
]);
if (job.rows.length !== 0) {
return res.status(401).send("Job already exists.");
}
const newJob = await pool.query(
`INSERT INTO jobs (job_name) VALUES
() RETURNING *`,
[job_name]
);
res.json({ "message": "Job created successfully!" });
//Assign Task
const {
job_id
employee_id
} = req.body;
const checkTask = await pool.query(`SELECT * FROM treatments WHERE
job_id = AND
employee_id `, [
req.params.id, employee_id
]);
if (checkTreatment.rows.length !== 0) {
return res.status(401).send("Technician already assigned in the same treatment and schedule.");
}
const newTaskAssignment = await pool.query(
`INSERT INTO treatments (job_id,
employee_id) VALUES
(, ) RETURNING *`,
[req.params.id, job_id]
);
res.json({ "message": "Task added to job successfully!" });
此外,如果可能的话,我如何通过 API POST 路由进行批量插入 tasks/employee 赋值,我读到它涉及制作一个数组,但我没有深入研究它,如果你也能给我建议那会很棒(或任何阅读资源,我目前正在阅读文档和 Whosebug 主题)。
在此先感谢您的帮助!
更新: 我按照 kb.objectrocket.com
的教程成功完成了
涉及到使用Transactions(昨晚刚学的,真的很棒!)。这是解决我的问题的代码:
//2. Declare an asynchronous function for the PG transaction
async function execute() {
// Promise chain for pg Pool client
const client = await pool
.connect()
.catch(err => {
console.log("\nclient.connect():", err.name);
// iterate over the error object attributes
for (item in err) {
if (err[item] = undefined) {
process.stdout.write(item + " - " + err[item] + " ");
}
}
//end the Pool instance
console.log("\n");
process.exit();
});
try {
//Initiate the Postgres transaction
await client.query("BEGIN");
try {
const sqlString = `WITH INSERTED AS (
INSERT INTO jobs (job_name) VALUES
() RETURNING id)
INSERT INTO tasks(
employee_id, job_id) VALUES
(,(
SELECT id FROM inserted
))`;
const sqlValues = [job_name, employee_id
];
// Pass SQL string to the query() method
await client.query(sqlString, sqlValues, function(err, result) {
console.log("client.query() SQL result:", result);
if (err) {
console.log("\nclient.query():", err);
// Rollback before executing another transaction
client.query("ROLLBACK");
console.log("Transaction ROLLBACK called");
} else {
client.query("COMMIT");
console.log("client.query() COMMIT row count:", result.rowCount);
}
});
} catch (er) {
// Rollback before executing another transaction
client.query("ROLLBACK");
console.log("client.query():", er);
console.log("Transaction ROLLBACK called");
}
} finally {
client.release();
console.log("Client is released");
}
}
execute();
res.json({ "message": "Service job created successfully!" });
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
谢谢!
我目前正在将 job/task 列表作为学习 Web 开发的测试项目(REST API、Express.js、通过 pg-node 的 Postgresql 13)。
该结构是用户可以在各种任务和工作中添加员工。
- 1 个作业可以有多个任务
- 1 个任务可以有多个员工
- 员工在同一份工作中不能有超过 1 个任务,但可以在不同的工作中分配另一项任务。
UI 中的流程是一个模式,允许您填写工作详细信息(名称)、添加任务,然后分配员工执行上述任务。
我目前拥有的是创建两个在单击“创建”按钮时发送的端点,一个用于创建工作,第二个用于创建员工并将其分配给任务,因为我需要附加 job_id 到任务,我不能做,直到它已经 generated/created。这样做的问题是,在插入任务出错的情况下,作业已经创建并保存在数据库中,而无法分配任务和员工,导致在 [= 中的“创建”按钮时发生冲突48=].
我想要做的(如果可能的话)是创建一个查询,该查询将同时创建和插入工作以及初始任务和员工分配。如果在整个事务期间发生错误(例如,由于数据类型错误等条件失败导致任务插入失败),查询将不会将该作业保存在数据库中。
DB Fiddle 架构:https://www.db-fiddle.com/f/izPsVVxPZ8e9ZMPwbL9her/10
这是我的 2 条路线:
//Create Job
const {
name
} = req.body;
const job = await pool.query(`SELECT * FROM jobs WHERE
name = )`, [
job_name
]);
if (job.rows.length !== 0) {
return res.status(401).send("Job already exists.");
}
const newJob = await pool.query(
`INSERT INTO jobs (job_name) VALUES
() RETURNING *`,
[job_name]
);
res.json({ "message": "Job created successfully!" });
//Assign Task
const {
job_id
employee_id
} = req.body;
const checkTask = await pool.query(`SELECT * FROM treatments WHERE
job_id = AND
employee_id `, [
req.params.id, employee_id
]);
if (checkTreatment.rows.length !== 0) {
return res.status(401).send("Technician already assigned in the same treatment and schedule.");
}
const newTaskAssignment = await pool.query(
`INSERT INTO treatments (job_id,
employee_id) VALUES
(, ) RETURNING *`,
[req.params.id, job_id]
);
res.json({ "message": "Task added to job successfully!" });
此外,如果可能的话,我如何通过 API POST 路由进行批量插入 tasks/employee 赋值,我读到它涉及制作一个数组,但我没有深入研究它,如果你也能给我建议那会很棒(或任何阅读资源,我目前正在阅读文档和 Whosebug 主题)。
在此先感谢您的帮助!
更新: 我按照 kb.objectrocket.com
的教程成功完成了涉及到使用Transactions(昨晚刚学的,真的很棒!)。这是解决我的问题的代码:
//2. Declare an asynchronous function for the PG transaction
async function execute() {
// Promise chain for pg Pool client
const client = await pool
.connect()
.catch(err => {
console.log("\nclient.connect():", err.name);
// iterate over the error object attributes
for (item in err) {
if (err[item] = undefined) {
process.stdout.write(item + " - " + err[item] + " ");
}
}
//end the Pool instance
console.log("\n");
process.exit();
});
try {
//Initiate the Postgres transaction
await client.query("BEGIN");
try {
const sqlString = `WITH INSERTED AS (
INSERT INTO jobs (job_name) VALUES
() RETURNING id)
INSERT INTO tasks(
employee_id, job_id) VALUES
(,(
SELECT id FROM inserted
))`;
const sqlValues = [job_name, employee_id
];
// Pass SQL string to the query() method
await client.query(sqlString, sqlValues, function(err, result) {
console.log("client.query() SQL result:", result);
if (err) {
console.log("\nclient.query():", err);
// Rollback before executing another transaction
client.query("ROLLBACK");
console.log("Transaction ROLLBACK called");
} else {
client.query("COMMIT");
console.log("client.query() COMMIT row count:", result.rowCount);
}
});
} catch (er) {
// Rollback before executing another transaction
client.query("ROLLBACK");
console.log("client.query():", er);
console.log("Transaction ROLLBACK called");
}
} finally {
client.release();
console.log("Client is released");
}
}
execute();
res.json({ "message": "Service job created successfully!" });
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
谢谢!