私はLAPP環境(linux apache postgresql php)で作業しています。私はトランザクション内で準備された文を使用する方法を知るためにtriynです(可能な場合)。準備されたステートメントをPHPからトランザクションを通して使用することはできますか?
例1、簡単なトランザクション:
私はコードが言葉その後、より良い説明を願って、私は右のトランザクションをundestood場合は、上記の例では
BEGIN;
INSERT INTO requests (user_id, description, date) VALUES ('4', 'This dont worth anything', NOW());
UPDATE users SET num_requests = (num_requests + 1) WHERE id = '4';
--something gone wrong, cancel the transaction
ROLLBACK;
UPDATE users SET last_activity = NOW() WHERE id = '4'
COMMIT;
、データベース内でのみ有効になりますlast_activityの更新...あなたは?
/* skip the connection */
pg_query($pgConnection, "BEGIN");
pg_query($pgConnection, "INSERT INTO requests (user_id, description, date) VALUES ('$id_user', 'This dont worth anything', NOW())");
pg_query($pgConnection, "UPDATE users SET num_requests = (num_requests + 1) WHERE id = '$id_user'");
//something gone wrong, cancel the transaction
pg_query($pgConnection, "ROLLBACK");
pg_query($pgConnection, "UPDATE users SET last_activity = NOW() WHERE id = '$id_user'");
pg_query($pgConnection, "COMMIT");
をそして、それは正常に動作します:私はPHPでそのトランザクションを使用しようとすると
(両方PDOまたはPG_方法で)コードは、(例2)のようになります。私は準備された文と例2をenvolveしようとすると、私の問題が来る、とにかく
たぶん見て醜いが、が動作する(提案は常に歓迎されている)ように見える(私は例の準備の使用2ということを知っています文が
)実施例3は非常に便利ではありません。
/* skip the connection */
pg_prepare($pgConnection, 'insert_try', "INSERT INTO requests (user_id, description, date) VALUES ('$1', '$2', $3)");
pg_query($pgConnection, "BEGIN");
pg_execute($pgConnection, 'insert_try', array($user_id, 'This dont worth anything', date("Y-m-d")));
/* and so on ...*/
まあ、例3は、単に仕事をいけない、準備されたステートメントが原因ロールバックでトランザクションた場合に有効になります。
したがって、準備された文をトランザクションで使用することはできませんか、間違った方法をとっていますか?
編集:いくつかの後
は、私は、この時点で到着しましたよ、PDOで試してみてください。
<?php
$dbh = new PDO('pgsql:host=127.0.0.1;dbname=test', 'myuser', 'xxxxxx');
$rollback = false;
$dbh->beginTransaction();
//create the prepared statements
$insert_order = $dbh->prepare('INSERT INTO h_orders (id, id_customer, date, code) VALUES (?, ?, ?, ?)');
$insert_items = $dbh->prepare('INSERT INTO h_items (id, id_order, descr, price) VALUES (?, ?, ?, ?)');
$delete_order = $dbh->prepare('DELETE FROM p_orders WHERE id = ?');
//move the orders from p_orders to h_orders (history)
$qeOrders = $dbh->query("SELECT id, id_customer, date, code FROM p_orders LIMIT 1");
while($rayOrder = $qeOrders->fetch(PDO::FETCH_ASSOC)){
//h_orders already contain a row with id 293
//lets make the query fail
$insert_order->execute(array('293', $rayOrder['id_customer'], $rayOrder['date'], $rayOrder['code'])) OR var_dump($dbh->errorInfo());
//this is the real execute
//$insert_order->execute(array($rayOrder['id'], $rayOrder['id_customer'], $rayOrder['date'], $rayOrder['code'])) OR die(damnIt('insert_order'));
//for each order, i move the items too
$qeItems = $dbh->query("SELECT id, id_order, descr, price FROM p_items WHERE id_order = '" . $rayOrder['id'] . "'") OR var_dump($dbh->errorInfo());
while($rayItem = $qeItems->fetch(PDO::FETCH_ASSOC)){
$insert_items->execute(array($rayItem['id'], $rayItem['id_order'], $rayItem['descr'], $rayItem['price'])) OR var_dump($dbh->errorInfo());
}
//if everything is ok, delete the order from p_orders
$delete_order->execute(array($rayOrder['id'])) OR var_dump($dbh->errorInfo());
}
//in here i'll use a bool var to see if anythings gone wrong and i need to rollback,
//or all good and commit
$dbh->rollBack();
//$dbh->commit();
?>
上記のコードは、この出力で失敗します。だから、
array(3) { [0]=> string(5) "00000" [1]=> int(7) [2]=> string(62) "ERROR: duplicate key violates unique constraint "id_h_orders"" }
array(3) { [0]=> string(5) "25P02" [1]=> int(7) [2]=> string(87) "ERROR: current transaction is aborted, commands ignored until end of transaction block" }
Fatal error: Call to a member function fetch() on a non-object in /srv/www/test-db/test-db-pgsql-08.php on line 23
、最初の実行が失敗したとき(id 293のもの)にトランザクションが自動的に中止されたように思えます... PDOの自動ロールバックなどがありますか?
私の目標は、最初のbig whileループを完了し、最後にフラグとしてbool varを使用して、トランザクションをロールバックするかコミットするかを決定することです。
準備された文を実行することは、通常の文を実行するのと同じように、トランザクションの中で確実に動作するはずです。私はいつもそれらを使用しますが、PHPではなくPerlから使用します。おそらく、実際にサーバ上で実行されているものをトレースすると(set log_statement = 'all')、期待していないときにコミットが行われていると表示されますか? – araqnid
私は、この問題がPDOの不適切な使用により多くなる可能性があると思います。 APIは、より深いフィードバックのためにライブラリを使用し、何が失敗しているのか、理由、場所、およびタイミングを簡単に確認できます。 –
ちょっとeditet、ありがとう – Strae