【问题标题】:How to return the serial primary key from a db insert to use for another db insert如何从数据库插入返回串行主键以用于另一个数据库插入
【发布时间】:2019-08-29 13:23:48
【问题描述】:

我正在使用带有 postgresql 的 express 生成的模板,并且我有 2 个用于创建寄售和跟踪的休息路线方法。 但是,我希望在每个寄售插入上更新跟踪,但我需要串行主键来执行此操作。因此,从 createCon 函数中,我要求它在插入后返回 id,以用于 createConTracking 中的 cid 字段。

路由/index.js 文件

var db = require('../queries');
router.post('/api/cons', db.createCon);
router.post('/api/cons/:id/tracking', db.createConTracking);

queries.js

var promise = require('bluebird');
var options = {
  promiseLib: promise
};
var pgp = require('pg-promise')(options);
var db = pgp(connectionString);
function createCon(req, res, next) {
  var conid = parseInt(req.body.conid);
  db.none('insert into consignments(conid, payterm,........)'+
    'values($1, $2, ......)',
    [conid, req.body.payterm,........])
    .then(function () {
      res.status(200)
        .json({
          status: 'success',
          message: 'Inserted one con'
        });
    })
    .catch(function (err) {
      return next(err);
    });
}

function createConTracking(req, res, next) {
  var cid = parseInt(req.params.id);
  var userid = req.user.email;
  var conid = parseInt(req.body.conid);
  db.none('insert into tracking(status, remarks, depot, userid, date, cid, conid)'+
    'values($1, $2, $3, $4,$5, $6, $7)',
    [req.body.status, req.body.remarks, req.body.depot, userid, req.body.date, cid, conid])
    .then(function (data) {
      res.status(200)
        .json({
          data:   data,
          status: 'success',
          message: 'Updated Tracking'
        });
    })
    .catch(function (err) {
      return next(err);
    });
}

数据库

CREATE TABLE consignments (
  ID SERIAL PRIMARY KEY,
  conId INTEGER,
  payTerm VARCHAR,

CREATE TABLE tracking (
  ID SERIAL PRIMARY KEY,
  status VARCHAR,
  remarks VARCHAR,
  cid INTEGER
  );

【问题讨论】:

  • 您的代码示例令人困惑。您的要求是针对执行两个操作的单个 HTTP 处理程序,而不是针对两个单独的 HTTP 处理程序。

标签: postgresql rest express pg-promise


【解决方案1】:

我是pg-promise的作者。


您应该在不更改数据时在一个任务中执行多个查询(方法task),或者在更改数据时执行事务(方法tx)。如果对数据库进行两次更改,就像在您的示例中一样,它应该是一个事务。

您可以将RETURNING id 附加到您的第一个插入查询,然后使用方法one 来指示您希望返回一行。

function myRequestHandler(req, res, next) {
    db.tx(async t => {
        const id = await t.one('INSERT INTO consignments(...) VALUES(...) RETURNING id', [param1, etc], c => +c.id);
        return t.none('INSERT INTO tracking(...) VALUES(...)', [id, etc]);
    })
        .then(() => {
            res.status(200)
                .json({
                    status: 'success',
                    message: 'Inserted a consignment + tracking'
                });
        })
        .catch(error => {
            return next(error);
        });
}

在上面的示例中,我们在事务中执行两个查询。对于第一个查询,我们使用第三个参数进行简单的返回值转换,以及转换(如果它是像 BIGSERIAL 这样的 64 位)。

【讨论】:

    【解决方案2】:

    只需将RETURNING 子句添加到您的INSERT 语句。该子句允许您返回有关插入记录中实际值的数据。

    insert into consignments(conid, payterm,........)
    values($1, $2, ......)
    returning id;
    

    【讨论】:

    • 除了答案,我想说如果您的查询返回某些内容,您不必使用db.none(...) 方法。
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2022-09-26
    • 1970-01-01
    • 2014-11-21
    • 2015-03-31
    相关资源
    最近更新 更多