2016-03-25 22 views
1

一度に2つのテーブルを挿入するには?私は、フィールドuser_idは、最初のテーブルでuser_information第二のテーブルを挿入するためにidを返すuser挿入を必要とする
は、私がthis answerを見つけましたが、私はどのように行うのparamsプリペアドステートメント一度に2つのテーブルに挿入するには?準備されたステートメント

var dbQuery = 'WITH insertUser AS (
    INSERT INTO "user" (status, create_date) VALUES ($1, $2) RETURNING id 
) 
    , insertUserInformation AS (
    INSERT INTO user_information (user_id, email) VALUES ($3, $4) 
) 
'; 

yield queryPromise(dbClient, dbQuery, [status, timestamp, ??, email]); 

pg

+0

このように:https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#transactions –

+0

回答がありましたらお手伝いしましたか?もしそうなら、それを受け入れてください。 –

答えて

1

トランザクションを使用します。これにより、すべてのクエリがコミットされるか、またはいずれもコミットされません。すべてのクエリを実行する前の不完全な状態は、他のプロセスでは表示されません。 node-postgresで取引を行う方法について

もっとhttps://github.com/brianc/node-postgres/wiki/Transactions

で利用可能であり、参考のために最も関連性の高いセクションでは、次のとおりです。

var Client = require('pg').Client; 

var client = new Client(/*your connection info goes here*/); 
client.connect(); 

var rollback = function(client) { 
    //terminating a client connection will 
    //automatically rollback any uncommitted transactions 
    //so while it's not technically mandatory to call 
    //ROLLBACK it is cleaner and more correct 
    client.query('ROLLBACK', function() { 
    client.end(); 
    }); 
}; 

client.query('BEGIN', function(err, result) { 
    if(err) return rollback(client); 
    client.query('INSERT INTO account(money) VALUES(100) WHERE id = $1', [1], function(err, result) { 
    if(err) return rollback(client); 
    client.query('INSERT INTO account(money) VALUES(-100) WHERE id = $1', [2], function(err, result) { 
     if(err) return rollback(client); 
     //disconnect after successful commit 
     client.query('COMMIT', client.end.bind(client)); 
    }); 
    }); 
}); 
+0

これは非同期で動作しますか?このコードを実行する関数の10,000インスタンスが同時に呼び出された場合、postgresドライバが無効な文を受け取らないことが保証されますか? (たとえば、すぐに別の「BEGIN」に続く「BEGIN」ステートメント) –

-1

であることを見つけることができませんこれが自然なSQL文として達成できるとは信じられません。手続きやその他の仕組みとしてまとめなければなりません。

+1

Postgresの1つのSQL文で、投稿が表示されるので、これを絶対に行うことができます。おそらく、バインドされたパラメータではできないかもしれませんが、そうでなければ確かに可能です。 –

+0

申し訳ありませんが、ポストには2つの異なるSQL文が使用されていることが示されています。私はあなたの方法が間違っていると言っているわけではありませんが、私はそれがシングルナチュラルSQLステートメントでは達成できないと述べています。 – FlyingGuy

1

postgresqlでは不可能です。私は関数を作成し、パラメータを使って単純に実行することで、まったく同じ問題を解決しました。あなたのテーブル構造に見られるように、あなたは多くの属性を持っていないので、これは比較的簡単です。

例コード:

function.sql

CREATE OR REPLACE FUNCTION createSomething 
(
    IN attr1 VARCHAR(20), 
    IN attr2 VARCHAR(200) 
) 
RETURNS void AS $$ 
DECLARE userId INTEGER; 
BEGIN 
    INSERT INTO table1 (col1, col2) VALUES 
    (
     attr1, 
     attr2 
    ) RETURNING id INTO userId; 

    INSERT INTO table2 (user_id, col11, col2) VALUES 
    (
     userId, 
     col11, 
     col12 
    ); 
END; 
$$ LANGUAGE plpgsql; 

使用法:

SELECT createSomething('value1', 'value2'); 

二insert文は、最近のユーザーのIDだったか知っているだろうし、それを使用することを、注意してください。

+0

お返事ありがとうございます、これを行う方法の例をいくつか教えていただけますか? – user1575921

+0

私は答えを編集しました。私は 'node-postgres'に慣れていないので、両方の技術を自分で接続しなければなりません。 – Fka

+0

トランザクションを使用してください。 2番目のクエリが失敗した場合は、ロールバックを実行することができ、データベースはまったく何も起こらないかのように、一貫した状態になります。 – Arjan

0

PostgreSQLのプリペアドステートメントは、あなたがそれを行うことはできません。トランザクションを使用する必要があります。

pg-promiseで実装されている例は、ES6ジェネレータを使用しています。これはあなたの質問から優先しているようです。

var pgp = require('pg-promise')({ 
    // initialization options; 
}); 

var db = pgp(/* your connection object or string */); 

db.tx(function*(t) { 
     let user = yield t.one('INSERT INTO user(status, create_date) VALUES($1, $2) RETURNING id', [status, timestamp]); 
     yield t.none('INSERT INTO user_information(user_id, email) VALUES($1, $2)', [user.id, email]); 
    }) 
    .then(()=> { 
     // SUCCESS; 
    }) 
    .catch(error=> { 
     // ERROR; 
    }); 

それともそれは約束を返しますので、あなたは、db.txから結果にさらにyieldを使用することができます。

関連する問題