我尝试使用node.js pg
npm包创建PostgreSQL预处理语句。但是,我一直收到错误:
无法确定参数$ 1的数据类型
function promiseQuery(sql, values) {
return new Promise(function(resolve, reject) {
pool.query('select $1 from workers', ['name'], function(err, result) {
if (err) {console.log(err); reject(err)}
else resolve(result.rows);
})
});
}
在数据库中,name
字段设置为text not null
。
我也尝试pg-promise,但也没有成功。
答案 0 :(得分:3)
在查询select name from workers
中,从SQL syntax name
的角度来看是identifier
,标识符永远不能作为$N
参数传递,它们必须逐字出现在命令中。否则无法准备查询。
$N
参数只能出现在文字(常量)所在位置的查询中。
如果在任何客户端库之外尝试与PREPARE
SQL命令类似的内容,则会出现相同的错误:
PREPARE p as SELECT $1 FROM pg_class;
ERROR: could not determine data type of parameter $1
解决方案是在使用字符串替换技术为列名或表名构建javascript中的查询,然后再将其提交到数据库。
答案 1 :(得分:2)
延伸DanielVérité的答案......
您无法将Prepared Statements与动态列名组合在一起,您必须在客户端生成查询。
使用pg-promise的SQL Names语法,您可以正确地转义您的查询:
db.any('SELECT $1~ FROM table', [colName])
// OR:
db.any('SELECT $1:name FROM table', [colName])
// OR:
db.any('SELECT ${colName~} FROM table', {colName})
// OR:
db.any('SELECT ${colName:name} FROM table', {colName})
// Etc, other variable syntax, like $[], $//, $<>, $()
如果你想为列表做这个,那么最简单的方法就是这样:
const colNames = ['one', 'two', 'three'];
db.any('SELECT $1~ FROM table', [colNames])
// etc, the same variations as above, all will generate:
// SELECT "one","two","three" FROM table
或来自所有对象属性:
const data = {
one: 123,
two: true,
three: 'text'
};
db.any('SELECT $1~ FROM table', [data])
// etc, the same variations as above, all will generate:
// SELECT "one","two","three" FROM table
所有这些方法都将正确地转义查询,确保无法进行SQL注入。