2016-04-23 71 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 –