Несколько запросов в одном запросе

Я пытаюсь добавить новых пользователей в базу данных и автоматически повторять идентификатор. То, как я пытаюсь это сделать, - сначала запустить запрос, чтобы проверить общее количество строк, а затем добавить к нему 1, чтобы назначить идентификатор пользователя, которого я хочу добавить.

Одна из проблем, с которой я столкнулся, заключается в том, что в первом запросе назначение newUser.id ограничено блоком, и я не могу получить доступ к этому значению за его пределами. Идентификатор для newUser остается нулевым или неопределенным в зависимости от того, как я перемещаю вещи

/add user to DB
router.post("/", (req, res) => {

var newID;

const newUser = {
    id: null,
    name: req.body.name,
    email: req.body.email,
    active: true
};

 db.result("SELECT COUNT(*) FROM users")
    .then(data => {
        newID = parseInt(data.rows[0].count) + 1;
        newUser.id = newID;

     //IF I CONSOLE.LOG(newUser) here then the value for id is 14

    });

    //IF I CONSOLE.LOG(newUser) here then the value for id is NULL

  db.none(
    "INSERT INTO users(id, name, email, active) VALUES ($1, $2, $3, $4)",
    [newUser.id, newUser.name, newUser.email, newUser.active]
  )
    .then(data => {
      res.status(200).json({ msg: "new user was added" });
    })
    .catch(error => {
      console.log("ERROR", error);
    });

person Joon Joonam    schedule 23.02.2020    source источник
comment
Почему бы просто не использовать тип serial или столбец identity в postgres? Тогда вам вообще не нужно делать несколько запросов к БД.   -  person Bergi    schedule 24.02.2020
comment
Хм, я пробовал, но получаю ошибку: ERROR: duplicate key value violates unique constraint "users_pkey" DETAIL: Key (id)=(12) already exists. SQL state: 23505   -  person Joon Joonam    schedule 24.02.2020
comment
Итак, если я продолжу это делать, в конце концов, идентификатор будет работать до пустой строки. Почему не запускается на бесплатном при старте?   -  person Joon Joonam    schedule 24.02.2020
comment
Если вы используете последовательность, вам нужно оставить столбец id вне оператора INSERT, чтобы он использовал сгенерированное значение по умолчанию.   -  person Bergi    schedule 24.02.2020
comment
Или, возможно, вы создали последовательность, когда у вас уже были данные в таблице, но она все еще начиналась с 0?   -  person Bergi    schedule 24.02.2020


Ответы (2)


назначение newUser.id ограничено блоком, и я не могу получить доступ к этому значению за его пределами.

Для этого вам нужно будет использовать цепочку обещаний:

db.result("SELECT …")
.then(data => {
    newUser.id = parseInt(data.rows[0].count) + 1;
    return db.none("INSERT …", newUser);
}).then(data => {
    res.status(200).json({ msg: "new user was added" });
}, error => {
    console.log("ERROR", error);
});

Я пытаюсь добавить новых пользователей в базу данных и автоматически повторять идентификатор

Не делайте два запроса для этого. Используйте столбец идентификации или sequence в базе данных для этого.

Или, по крайней мере, объединить два запроса в один оператор для одновременного запуска:

db.none(
  "INSERT INTO users(id, name, email, active) VALUES ((SELECT COUNT(*)+1 FROM users), $1, $2, $3)",
  [newUser.name, newUser.email, newUser.active]
)
.then(data => {
  res.status(200).json({ msg: "new user was added" });
}, error => {
  console.log("ERROR", error);
});
person Bergi    schedule 23.02.2020

Поскольку вы используете более одного запроса одновременно, вы должны использовать задачу:

await db.task('add-new-user', async t => {
    const count = await t.one('SELECT count(*) FROM users', [], a => +a.count);
    newUser.id = count + 1;
    return t.none('INSERT INTO users(${this:name}) VALUES(${this:csv})', newUser);
});

P.S. Вместо этого вы должны использовать тип serial, и тогда вы сможете избежать всего этого.

person vitaly-t    schedule 23.02.2020
comment
Спасибо, да, определенно лучшим решением является использование серийного номера. - person Joon Joonam; 24.02.2020