如何正确地将多行插入到带有node-postgres的PG中?

ogq8wdun  于 2022-11-29  发布在  Node.js
关注(0)|答案(7)|浏览(105)

可按如下方式插入单行:

client.query("insert into tableName (name, email) values ($1, $2) ", ['john', 'john@gmail.com'], callBack)

此方法会自动注解掉任何特殊字符。
如何一次插入多行?
我需要实现这一点:

"insert into tableName (name, email) values ('john', 'john@gmail.com'), ('jane', 'jane@gmail.com')"

我可以只使用js字符串操作符来手动编译这样的行,但随后我需要添加特殊字符escape。

mnemlml8

mnemlml81#

如下所示使用pg-format

var format = require('pg-format');

var values = [
  [7, 'john22', 'john22@gmail.com', '9999999922'], 
  [6, 'testvk', 'testvk@gmail.com', '88888888888']
];
client.query(format('INSERT INTO users (id, name, email, phone) VALUES %L', values),[], (err, result)=>{
  console.log(err);
  console.log(result);
});
2mbi3lxu

2mbi3lxu2#

另一种使用PostgreSQL json函数的方法:

client.query('INSERT INTO table (columns) ' +
  'SELECT m.* FROM json_populate_recordset(null::your_custom_type, $1) AS m',
  [JSON.stringify(your_json_object_array)], function(err, result) {
    if (err) {
      console.log(err);
    } else {
      console.log(result);
    }
});
vs91vp4v

vs91vp4v3#

本文之后:pg-promise库中的Performance Boost,以及它的建议方法:

// Concatenates an array of objects or arrays of values, according to the template,
// to use with insert queries. Can be used either as a class type or as a function.
//
// template = formatting template string
// data = array of either objects or arrays of values
function Inserts(template, data) {
    if (!(this instanceof Inserts)) {
        return new Inserts(template, data);
    }
    this.rawType = true;
    this.toPostgres = function () {
        return data.map(d=>'(' + pgp.as.format(template, d) + ')').join(',');
    };
}

使用它的一个例子,完全在你的情况:

var users = [['John', 23], ['Mike', 30], ['David', 18]];

db.none('INSERT INTO Users(name, age) VALUES $1', Inserts('$1, $2', users))
    .then(data=> {
        // OK, all records have been inserted
    })
    .catch(error=> {
        // Error, no records inserted
    });

它还可以处理对象数组:

var users = [{name: 'John', age: 23}, {name: 'Mike', age: 30}, {name: 'David', age: 18}];
  
db.none('INSERT INTO Users(name, age) VALUES $1', Inserts('${name}, ${age}', users))
    .then(data=> {
        // OK, all records have been inserted
    })
    .catch(error=> {
        // Error, no records inserted
    });

更新-1

有关通过单个INSERT查询实现高性能的方法,请参见Multi-row insert with pg-promise

更新-2

这里的信息现在已经很旧了,请参阅自定义类型格式的最新语法。以前的_rawDBType现在是rawTypeformatDBType被重命名为toPostgres

wgx48brx

wgx48brx4#

您必须动态地生成查询。虽然这是可能的,但这是有风险的,如果您做错了,很容易导致SQL注入漏洞。也很容易在查询中的参数索引和传入的参数之间出现一个错误。
也就是说,下面是一个如何编写的示例,假设您有一个类似{name: string, email: string}的用户数组:

client.query(
  `INSERT INTO table_name (name, email) VALUES ${users.map(() => `(?, ?)`).join(',')}`,
  users.reduce((params, u) => params.concat([u.name, u.email]), []),
  callBack,
)

另一种方法是使用@databases/pg(我写的)这样的库:

await db.query(sql`
  INSERT INTO table_name (name, email)
  VALUES ${sql.join(users.map(u => sql`(${u.name}, ${u.email})`), ',')}
`)

@databases要求查询用sql标记,并使用它来确保传递的任何用户数据总是被自动转义。这还允许您内联地编写参数,我认为这会使代码更具可读性。

ih99xse1

ih99xse15#

使用npm模块postgres(porsager/postgres),其核心具有标记的模板字符串:
https://github.com/porsager/postgres#multiple-inserts-in-one-query

const users = [{
  name: 'Murray',
  age: 68,
  garbage: 'ignore'
},
{
  name: 'Walter',
  age: 80,
  garbage: 'ignore'
}]

sql`insert into users ${ sql(users, 'name', 'age') }`

// Is translated to:
insert into users ("name", "age") values ($1, $2), ($3, $4)

// Here you can also omit column names which will use all object keys as columns
sql`insert into users ${ sql(users) }`

// Which results in:
insert into users ("name", "age", "garbage") values ($1, $2, $3), ($4, $5, $6)

只是想我会张贴,因为它就像一个全新的测试版,我发现它是一个更好的SQL库的哲学。我认为将优于其他postgres/节点库张贴在其他答案。恕我直言

4si2a6ki

4si2a6ki6#

嗨,我知道我参加聚会迟到了,但对我起作用的是一张简单的Map。
我希望这将有助于寻求相同的人

let sampleQuery = array.map(myRow =>
    `('${myRow.column_a}','${myRow.column_b}') `
    ) 

 let res = await  pool.query(`INSERT INTO public.table(column_a, column_b) VALUES ${sampleQuery}  `)
xkrw2x1b

xkrw2x1b7#

client.query("insert into tableName (name, email) values ($1, $2),($3, $4) ", ['john', 'john@gmail.com','john', 'john@gmail.com'], callBack)

没有帮助?此外,您还可以手动生成查询字符串:

insert into tableName (name, email) values (" +var1 + "," + var2 + "),(" +var3 + ", " +var4+ ") "

如果您阅读这里的https://github.com/brianc/node-postgres/issues/530,您可以看到相同的实现。

相关问题