使用事务时,查询中包含的子查询如何在pg-promise中工作?

时间:2016-08-07 21:59:15

标签: node.js postgresql pg-promise

我正在使用pg-promise作为node.js,我想确保我正确理解有关交易的文档。

说我执行了以下交易:

db.tx(function(t) {
  t.any('SELECT * FROM users')
  .then(function(users) {
    var queries = [];
    for (var i =0; i < users.length; i++) {
      queries.push(t.any("INSERT INTO stocks_owned (ticker, shares, user_id) VALUES ('GOOG', 10, $1)", users[i].user_id));
    }
    return t.batch(queries);
  })
})

这最终会有什么postgres查询?

postgres交易将是:

BEGIN;
SELECT * FROM users;
SAVEPOINT my_savepoint;
INSERT INTO stocks_owned (ticker, shares, user_id) VALUES ('GOOG', 10, 1);
INSERT INTO stocks_owned (ticker, shares, user_id) VALUES ('GOOG', 10, 2);
...
INSERT INTO stocks_owned (ticker, shares, user_id) VALUES ('GOOG', 10, 999);
COMMIT;

换句话说,其他查询中包含的子查询是否包含在同一个BEGIN/COMMIT块中?

1 个答案:

答案 0 :(得分:0)

  

这最终会有什么postgres查询?

您列出的那些,但不会有任何SAVEPOINT,因为保存点仅用于代替嵌套交易。

  

其他查询中包含的子查询是否包含在同一个BEGIN / COMMIT块中?

没有子查询这样的东西,从驱动程序的角度来看,只有查询,所有在事务中执行的都将在BEGIN / COMMIT块内。

要确切了解pg-promise正在执行的内容,您应该使用pg-monitor,或者至少 - 处理event query

var pgOptions = {
    query: function (e) {
        console.log(e.query); // log the query being executed
    }
};

var pgp = require('pg-promise')(pgOptions);

以下是您的代码中的错误:

t.any('SELECT * FROM users')

应该是:

return t.any('SELECT * FROM users')

或者那里没有事务逻辑,因为你没有从回调中返回任何东西。

做最简单,最有效的方法:

db.tx(t => {
    return t.map('SELECT * FROM users', [], user => {
        return t.none("INSERT INTO stocks_owned(ticker, shares, user_id) VALUES('GOOG', 10, ${user_id})", user);
    }).then(t.batch);
})
    .then(data => {
        // success, data = [null, null, ...]
    })
    .catch(error => {
        // error
    });

<强>更新

以上示例不再是最有效的方法。最有效的方法是执行一个选择,然后执行单个多行插入。请参阅Multi-Row Inserts