2016-04-23 51 views
0

试图在postgres上做一个sql更新9.注意等号左边的$ 1。这将是传入的表中的列的名称。当我硬编码列名时,更新完美。但是,当我尝试通过列作为参数($ 1),更新失败。为什么,以及如何解决这个问题?等号左边的sql位置参数

pg.connect(connectionString,function (err, client) { 
    client.query("UPDATE people SET $1 = $2 WHERE pin = $3 RETURNING pin", 
     [param1, param2, param3], function(err, result){ 
     if(err) { 
      console.log("Error updating data: ", err); 
      res.send(false); 
     }else{ 
      res.send(true); 
     } 
     }); 
    }); 
+0

您可以将列名想像为其他语言中的变量名,因此允许使用它们的占位符类似于使用'eval',所以它通常是不允许的。检查数据库接口的文档中的“引用标识符”或“转义标识符”函数,使用该函数正确引用'param1'并使用字符串连接来将引用的值存入SQL。请注意,标识符(例如表格或列名称)的引用规则与值不同,因此请务必使用正确的引用函数。 –

回答

0

client.query,使您的查询在两个SQL语句执行的内部使用事先准备好的声明:

PREPARE some_generated_name AS 
UPDATE people SET $1 = $2 WHERE pin = $3 RETURNING pin; 

EXECUTE some_generated_name('data1', 'data2', 'data3'); 

这是一种合理的方法,如果你想执行相同的查询多次。 PREPARE告诉PostgreSQL解析和提前计划查询,因为很多EXECUTE声明即将到来,他应该为它做好准备。

然后PostgreSQL尽其所能地提前完成任何事情,包括解析和计划。分析意味着他在语法上验证查询并“理解”查询,计划意味着他试图预测哪个操作将在哪个表上执行。

这是PostgreSQL试图将声明式SQL转换为程序性指令集的部分,例如“获取此特定表”,“在此表中更新此列与此变量匹配的列”,...(在练习这个系统是复杂得多,但真的很有趣)

问题是,动态列名不可能解析,所以PostgreSQL拒绝PREPARE您的查询。

您不应该使用列变量,因为您拥有数量有限的众所周知的列,所以您必须使用固定的命名列,使用白名单来验证用户输入并使用简单字符串连接。

+0

我想我明白你在说什么。下面的作品。可以吗?该列仍然没有硬编码,但它不再作为参数传递。这是安全风险吗? 'pg.connect(的connectionString,函数(ERR,客户端){ client.query( “UPDATE人 SET的param1 = $ 1,其中销= $ 16 RETURNING销”, [param2的,参数3],... ' – Tenbrink

+0

看起来像这会让我容易受到SQL注入的影响吗? – Tenbrink

+0

如果你不过滤param1 –

相关问题