5

pg拡張子(バージョン0.5.4)のnode.jsを使用して、postgresデータベースに挿入または更新を行おうとしています。

これまでのところ、私はこのコードを持っています:(...)

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);
                });
            }
        });

問題は、両方のクエリは機能しますが、更新が失敗した場合に挿入関数を実行するだけでなく、常に両方を実行しているということです。

コード内のデバッグ関数は、次のように出力します。

アップデート

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}

** 編集 **

node-postgres開発者からの回答:

挿入と更新の影響を受ける行数を取得することができます。ネイティブバインディングでは完全には実装されていませんが、純粋なjavascriptバージョンでは機能します。私は来週か2週間以内にこれに取り組みます。それまでの間、純粋なjavascriptバージョンを使用して、こちらをご覧ください。

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

**編集終了**

誰か助けてもらえますか?

4

3 に答える 3

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 に渡す必要があります。ここで示した方法で行き詰まっている場合は、更新後に実際のエラー オブジェクトをチェックして、行が既に存在するために失敗したか、または他の理由で失敗したかを判断する必要があります (これは実際の db エラーであり、処理する必要があります)。

次に、更新が失敗してから挿入が完了するまでの潜在的な競合状態に対処する必要があります。他の関数が同じ ID で挿入しようとすると、問題が発生します。トランザクションはそのために適しています。それは私が今得たすべてです。それが役に立てば幸い。

于 2011-11-03T07:42:13.553 に答える
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 ベースのソリューションです。

最初の質問は次のとおりです: 挿入、PostgreSQL での重複更新について?

于 2012-04-28T15:08:24.143 に答える