I am trying to migrate to Postgres from MySQL and have run into a little bit of a problem. I have a form where the user fills out about 40 fields, and these values are inserted into the database. With MySQL I'm used to doing it like this:
INSERT INTO table_name SET name="John Smith", email="jsmith@gmail.com", website="jsmith.org";
I'm also using the mysql
module with nodejs, and this is what my code currently looks like:
var data = {
name: req.body.name,
email: req.body.email,
website: req.body.website,
...
...
}
var query = connection.query('INSERT INTO table_name SET ?', data)
Since SET
isn't valid SQL, if I wanted to use Postgres, the query would look like this using the pg
module:
client.query('INSERT INTO table_name (name, email, website) VALUES ($1, $2, $3)', req.body.name, req.body.email, req.body.website)
This would turn out to be very tedious considering that I have almost 40 fields.
Is there any better way to do this or am I stuck with having to write the query manually?
Thank you.
答案 0 :(得分:4)
由于您已经有一个包含相关数据的对象
var data = {
name: req.body.name,
email: req.body.email,
website: req.body.website,
...
...
}
您可以编写一个查询函数来包装pg
客户端的query
方法并添加对象值作为支持:
function insert(client, table, values) {
const keys = Object.keys(values),
// IMPORTANT: escape column identifiers. If `values` should come
// from an uncontrolled source, naive concatenation would allow
// SQL injection.
columns = keys.map(k => client.escapeIdentifier(k)).join(', '),
placeholders = keys.map((k, i) => '$' + (i + 1)).join(', ');
return client.query(`INSERT INTO ${client.escapeIdentifier(table)}
(${columns}) VALUES (${placeholders})`,
// According to docs `query` accepts an array of
// values, not values as positional arguments.
// If this is not true for your version, use the
// spread syntax (...args) to apply values.
keys.map(k => values[k]));
}
...
insert(client, 'table_name', data);
或者你可能会用sql-template-strings
重写你的查询,这似乎相当不错。
答案 1 :(得分:1)
使用pg-promise时很容易实现,这里是完整的代码:
var pgp = require('pg-promise')();
var db = pgp(/*connection details*/);
app.get('/get', (req, res)=> {
var insert = pgp.helpers.insert(req.body, null, {table: 'table_name'});
db.none(insert)
.then(()=> {
// success
})
.catch(error=> {
// error
});
});
API:helpers.insert,none
方法helpers.insert可以为您生成完整的INSERT
语句,格式正确。
它不仅是最简单的方法,而且也是最灵活的方法,因为您不需要更改任何内容来开始生成多插入语句,即insert
方法的第一个参数是对象数组,您将获得多插入查询。
如果您只想要请求中的特定属性,那么最好的方法是单独指定它们,作为请求之外的ColumnSet(可重用,以获得最佳性能):
var cs = new pgp.helpers.ColumnSet(['name', 'email', 'website'], {table: 'table_name'});
app.get('/get', (req, res)=> {
var insert = pgp.helpers.insert(req.body, cs);
db.none(insert)
.then(()=> {
// success
})
.catch(error=> {
// error
});
});
没有转化
app.get('/get', (req, res)=> {
var insert = pgp.helpers.insert(req.body, cs) + 'RETURNING id';
db.many(insert)
.then(data=> {
// success
})
.catch(error=> {
// error
});
});
带转化的
app.get('/get', (req, res)=> {
var insert = pgp.helpers.insert(req.body, cs) + 'RETURNING id';
db.map(insert, [], a=>a.id)
.then(ids=> {
// ids = array of id-s
})
.catch(error=> {
// error
});
});