如何修复多行节点postgres插入 - 语法错误在$ 4或附近

时间:2017-04-11 01:40:00

标签: node.js postgresql express node-postgres pg-promise

我有一个多行node-postgres插件,它给了我一些问题。它是一个参数化查询,它使用公用表表达式来更新主表和两个具有外键的表。查询使用主表的参数,但是,当我尝试参数化多行的外键表时,它会抛出语法错误。

首先,我有这个函数,它接受一个数组并返回一串值。

const buildValues = (id, values) => {
    return values 
        .map(val => "(" + id + ", '" + val + "', " + false + ")")
        .join(", ");
    };

这是我的问题:

app.post('/api/saveperson', function (req, res) {
  pg.connect(connectionString, (err, client, done) => {

    const insertPerson = `
    WITH x AS ( INSERT INTO people (title, notes, name)
        VALUES ($1, $2, $3)
        RETURNING personId
    ),
    b AS (
        INSERT INTO sports (personid, name, favorite)
        VALUES $4 )
    INSERT INTO instructions (personid, name, favorite)
    VALUES $5; 
    `;

      client.query(insertPerson, 
            [ req.body.title
            , req.body.notes
            , req.body.name
            , queries.buildValues("SELECT personId FROM x", req.body.sports)
            , queries.buildValues("SELECT personId FROM x", req.body.instructions)
            ]
         )
          .then( () => client.end())
          .catch( err => console.log(err));
  });
  return res.json(req.body);
});

1 个答案:

答案 0 :(得分:1)

不确定这是否是最佳解决方案,但我最终使用的是pg-promise库,而不仅仅是pg。然后我使用事务和链式查询:

  db.tx(t => {
      // BEGIN has been executed
      return t.one(
          `INSERT INTO people (title, notes, name) 
          VALUES ($[title], $[notes], $[name]) 
          RETURNING personid`, req.body)
          .then(data => {
            let sportsQueries = req.body.sports.map(sport => {
              return t.none(`INSERT INTO sports (personid, name) 
                          VALUES ($1, $2)`, [data.personid, sport]);     
            });

            let instructionsQueries = req.body.instructions.map(ins => {
              return t.none(`INSERT INTO instructions (personid, instruction) 
                          VALUES ($1, $2)`, [data.personid, ins]);
            });

            return t.batch(sportsQueries.concat(instructionsQueries));

          });
  })
     .then(data => {
         // Success, and COMMIT has been executed
     })
     .catch(error => {
         // Failure, and ROLLBACK has been executed
     })