2011-10-26 47 views
4

我想在postgres數據庫中使用node.js與pg擴展(版本0.5.4)插入或更新。在Postgres使用node.js的upsert

到目前爲止,我有這樣的代碼: (...)

client.query({ 
      text: "update users set is_active = 0, ip = $1 where id=$2", 
      values: [ip,id] 
     }, function(u_err, u_result){ 
      debug(socket_id,"update query result: ",u_result); 
       debug(socket_id,"update query error: ",u_err); 

        date_now = new Date(); 
      var month = date_now.getMonth() + 1; 

      if(!u_err){ 

       client.query({ 
        text: 'insert into users (id,first_name,last_name,is_active,ip,date_joined) values' + 
        '($1,$2,$3,$4,$5,$6)', 
        values: [ 
          result.id, 
          result.first_name, 
          result.last_name, 
          1, 
          ip, 
          date_now.getFullYear() + "-" + month + "-" + date_now.getDate() + " " + date_now.getHours() + ":" + date_now.getMinutes() + ":" + date_now.getSeconds() 
          ] 
       }, function(i_err, i_result){ 
        debug(socket_id,"insert query result: ",i_result); 
        debug(socket_id,"insert query error: ",i_err); 
       }); 
      } 
     }); 

的問題是,儘管這兩個查詢的工作問題總是同時運行,而不是在更新失敗僅在運行插入功能。

代碼輸出類似的調試功能:

UPDATE

Object { type="update query result: ", debug_value={...}} 
home (linha 56) 
Object { type="update query error: ", debug_value=null} 
home (linha 56) 
Object { type="insert query result: "} 
home (linha 56) 
Object { type="insert query error: ", debug_value={...}} 

插入

Object { type="update query result: ", debug_value={...}} 
home (linha 56) 
Object { type="update query error: ", debug_value=null} 
home (linha 56) 
Object { type="insert query result: ", debug_value={...}} 
home (linha 56) 
Object { type="insert query error: ", debug_value=null} 

**編輯**

ANSWE [R從節點的Postgres開發商:

它可以檢索受INSERT和 更新行數。它在本地綁定中沒有完全實現,但是 在純javascript版本中工作。我將在下週或兩週內在 內處理此問題。在平均時間使用純JavaScript版本和 看看這裏:

https://github.com/brianc/node-postgres/blob/master/test/integration/client/result-metadata-tests.js

**編輯完**

誰能幫助?

回答

2

您的問題的直接答案是使用存儲過程做一個upsert。

http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE

事情是這樣的正常工作與pg模塊。

client.query({ 
    text: "SELECT upsert($1, $2, $3, $4, $5, $6)" 
    values: [ obj.id, 
      obj.first_name, 
      obj.last_name, 
      1, 
      ip, 
      date_now.getFullYear() + "-" + month + "-" + date_now.getDate() + " " + date_now.getHours() + ":" + date_now.getMinutes() + ":" + date_now.getSeconds() 
      ] 
}, function(u_err, u_result){ 
    if(err) // this is a real error, handle it 

    // otherwise your data is updated or inserted properly 
}); 

當然這假定您正在使用某種具有所需值的模型對象,即使它們沒有更改。你必須將它們全部傳遞給upsert。如果你堅持以你在這裏顯示的方式進行,你應該在更新後檢查實際的錯誤對象,以確定它是否失敗,因爲該行已經存在,或出於某種其他原因(這是真正的數據庫錯誤需要處理)。

然後,您必須處理更新失敗的時間與插入時間之間的潛在競爭條件。如果其他函數嘗試使用相同的ID插入,則會出現問題。交易對此很有幫助。這就是我現在所擁有的一切。希望能幫助到你。

+0

喜馬!感謝你的回答!我與node.js的pg模塊的開發人員聯繫了,並且我編輯了這個問題以表達他的迴應!關於你的答案,這是我最初的意圖,但是因爲我正在開發使用heroku並需要水龍頭來遷移數據庫我有一個問題,因爲我認爲水龍頭不能導出存儲過程。 (儘管我可能是錯誤的),無論如何,你能否告訴我關於存儲過程的性能問題?關於併發性問題我不認爲他們適用,但如果你可以發佈一些鏈接ilustrate Transictions它將是完美的...;)再次感謝! – jribeiro

2

我在使用JDBC連接到PG實例時遇到了此問題。我結束了使用的解決方案是:

UPDATE table SET field='C', field2='Z' WHERE id=3; 
INSERT INTO table (id, field, field2) 
     SELECT 3, 'C', 'Z' 
     WHERE NOT EXISTS (SELECT 1 FROM table WHERE id=3); 

更新什麼都不做,如果記錄不存在,如果記錄不存在插入什麼都不做。它工作得很好,是一個基於SQL的解決方案與存儲過程。

這裏是最初的問題: Insert, on duplicate update in PostgreSQL?

+0

我實際上也沿着這些路線實施了一些東西。但是我測試了第一個查詢的響應,並且只在沒有行被感染時才運行第二個查詢。這是/只在我使用的https://github.com/brianc/node-postgres的本地js模式中被支持。感謝您花時間回答! – jribeiro