我正在开发 sqlite3 数据库。我想创建一个包装函数来更新采用 rowid(主键)和更新对象的表条目。
const testUpdate = {
isFavorite : true,
rating : 4,
}
const updateMovie = function(id, update) {
return new Promise((resolve, reject) => {
const sql = 'UPDATE films SET isFavorite = ?, rating = ? WHERE id = ?';
db.run(sql, update.isFavorite, update.rating, id, (err, rows) => {
if (err)
reject(err);
resolve(rows);
});
});
}
使用
?
可以防止 SQL 注入和其他攻击,所以我知道我不应该对 SQL 使用字符串插值(这可以轻松解决我所有的问题),但是如果我希望我的更新对象具有 可变数量的属性怎么办(例如,在一种情况下,我想要更新 isFavorite、评分和 watchDate,而在另一种情况下,我只想更新 isFavorite)?
我想到了两种解决方案:
我该怎么办?
id | 标题 | 是最爱 | 评分 | 观看日期 | 用户ID |
---|---|---|---|---|---|
2 | 21克 | 1 | 4 | 2024-03-17 | 1 |
3 | 星球大战 | 0 | 空 | 空 | 1 |
4 | 矩阵 | 0 | 空 | 空 | 2 |
5 | 怪物史莱克 | 0 | 3 | 2024-03-21 | 2 |
这相对简单。
首先,您要找出要更新的所有密钥:
let keys = Object.keys(update)
首先,循环遍历每个键以确保它位于有效键列表中:
const validKeys = ["title","isFavorite","rating","watchDate","userId"];
keys = keys.filter(key => validKeys.indexOf(key) != -1);
然后,循环遍历每个键来构建设置的字符串 (
x = ?, y = ?, z = ?
)
const setStr = keys.map(key=> `${key} = ?`).join(', ');
然后,获取您想要将密钥更新为的所有值:
const values = keys.map(key=> update[key]);
因为这些值代表所有
?
,所以您需要添加 id
的最终值 (WHERE id = ?
)
values.push(id);
然后您可以使用传递的值运行 sql 语句。
db.run(`UPDATE films SET ${setStr} WHERE id = ?`, values, (err, rows)=>{
if(err) return console.error(err)
console.log(rows);
});
注意:你做的地方
,应该是(sql, update.isFavorite, update.rating, id,...
db.run 的第二个参数是一个列表。sql, [update.isFavorite, update.rating, id],...