我在一個LAPP環境(linux apache postgresql php)上工作,而我只是三元組來找出如何在事務中使用準備好的語句(如果可能的話)。無法使用準備好的語句通過交易,從PHP?
希望代碼將解釋更好然後詞:
實施例1,簡單的事務:
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;
在上面的例子,如果我undestood權交易,在數據庫中的唯一的影響將是last_activity的更新...你呢?
,如果我嘗試使用該交易在PHP(均與PDO或PG_方法)的代碼應該看起來像(例如2):
/* 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");
而且工作正常。也許醜陋看到的,但似乎工作(建議總是歡迎)
不管怎麼說,我的問題來了,當我嘗試進化得只剩例2與預處理語句(我知道,在例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自動回滾還是其他?
我的目標是完成第一個大的while循環,最後使用bool var作爲標誌,決定是否回滾或提交事務。
執行準備好的語句肯定應該像執行正則語句一樣在事務內部工作。我一直使用它們,但是來自Perl,而不是PHP。也許跟蹤服務器上實際正在執行的內容(set log_statement ='all')是否會在您不期望提交時完成提交? – araqnid 2009-05-19 23:15:14
我認爲這個問題可能更多的是PDO使用不當。 API使用庫來獲得更深入的反饋,並使查看失敗的原因,原因,地點和時間更簡單。 – 2009-05-20 00:59:27
只是editet,謝謝 – Strae 2009-05-20 07:04:34