【问题标题】:How to insert multiple rows (from a req. body) in a transaction如何在事务中插入多行(来自请求正文)
【发布时间】:2021-02-10 19:35:04
【问题描述】:

我想问一下是否有办法通过 req 插入多行。身体(来自前端)。我设法创建了一种插入一行的方法,但如果可能的话,我想插入多行 task,同时只插入一次 job

我读过一种方法是使用 json 数组并循环它,但不知道该怎么做。如果您有其他方法,那也将是一个很大的帮助!

我目前使用 node.js / express.js 作为后端,并使用 node-postgres 作为与 db 的连接。

//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
                                ($1) RETURNING id)
                            INSERT INTO tasks(
                                employee_id, job_id) VALUES
                                ($2,(
                                    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();

        } catch (err) {
            console.error(err.message);
            res.status(500).send("Server Error");
    }
});

谢谢!

【问题讨论】:

  • 当您要插入 2 个不同的项目时,您确定要使用 $1 两次吗?
  • @FrankHeikens 哎呀,我没有注意到那个错字。谢谢!固定(第二个应该是 2 美元)

标签: node.js postgresql node-postgres


【解决方案1】:

在第二个 INSERT 和 UNNEST() 中使用 SELECT 来获取数组中的所有项目:

WITH INSERTED AS (  
    INSERT INTO jobs (job_name) 
    VALUES($1) 
    RETURNING id
)
INSERT INTO tasks(employee_id, job_id) 
SELECT  UNNEST($2) -- PostgreSQL array input, you might need another function for your type of input
    ,   id
FROM inserted;

编辑:使用一些 json 对象作为输入的示例:

WITH INSERTED AS (  
    INSERT INTO jobs (job_name) 
    VALUES($1::json #>> '{name}') -- selects the name from the json object as TEXT
    RETURNING id
)
INSERT INTO tasks(employee_id, job_id) 
SELECT  column1 
    ,   id
FROM inserted
    , json_to_recordset($1::json #> '{tasks}') AS t(column1 int, column2 text);

$1 是一个使用了两次的 json 对象。 PostgreSQL 将提取 INSERT 所需的元素。

【讨论】:

  • 嗨,抱歉,您能解释一下 unnest 的工作原理吗?我已经阅读了文档并检查了其他资源,但对我来说仍然有点模糊。如果我错了,请纠正我,但据我了解,我可以使用unnest 从 req.body 打开对象数组(json)。我应该如何格式化我的数组?我读到它应该是"arrayName":[{ "Row1col1: "Row1value1", "Row1col2": "Row1value2" }. {"Row2col1": "Row2value1", "Row2col2": "Row2val2"}] 如果这个问题可能是我在阅读文档时很容易错过的问题,我深表歉意。
  • @TechArtificer:你能给我们展示一个有效的 json 对象吗?
  • 这是JSON 我打算通过req.body 发送到数据库。 JSON 中的示例假设插入的数据将具有多列而不是只有一列(与我上面发布的代码相反)并且具有不同的数据类型(int 和 string),以防我将来可能需要它附加参考。
  • @TechArtificer:查看新示例,仅使用单个输入参数,即您向我们展示的完整 json 对象。
  • 您好,我“认为”它正在工作,因为我能够读取并接受 json,但是我遇到了一个错误,上面写着 'Expected ":", but found "}". 我检查了谷歌搜索,这似乎是一个问题使用node-pg as described in this issue,我尝试在sqlValues tasks 上使用JSON.stringify,但它仍然返回错误。谢谢你的帮助!呃,如果我可以问,是否可以在交易中设置条件?例如不能两次插入同一个employee_id,或者检查表中是否已经存在employee_id?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 2019-07-14
  • 2021-02-06
相关资源
最近更新 更多