Php den, hazır deyim işlem düşünce kullanılabilir edemeyiz?

2 Cevap php

Ben bir LAPP ortamda (linux apache postgresql php) üzerinde çalışmak, ve ben sadece (mümkün ise) işlem içinde hazırlanmış deyimi nasıl kullanılacağını öğrenmek için triyn ediyorum.

Ben kod kelimeleri daha sonra daha iyi açıklamak umuyoruz:

Örnek 1, basit işlem:

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;

I doğru işlem undestood, yukarıdaki örnekte, veritabanındaki tek etkisi siz ... last_activity güncelleme olacak?

I php o işlem (her iki PDO veya pg_ yöntemleri ile) kullanmaya çalışırsanız kodu, (örneğin 2) gibi görünmelidir:

/* 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");

Ve bu gayet iyi çalışıyor. Belki çirkin (önerim her zaman açığız) görmek için, ama seem çalışmak

I hazırlanan tablolarda (i örnek 2'de hazırlanan tabloların kullanımı çok yararlı olmadığını biliyoruz) ile örnek 2 öznelerden biri çalıştığınızda Neyse, benim sorunum gel

Örnek 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 ...*/

Peki, örneğin 3 sadece dont iş, hazır deyim etkili olacak eğer işlem geri alma nedeniyle.

Yani, hazırlanan tablolar işlemde kullanılamaz, ya da ben yanlış yol alıyorum?

EDIT:

Bazı PDO ile çalıştıktan sonra, ben bu noktada geldi ediyorum:

<?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();
?>

Yukarıdaki kod, bu çıkışı ile başarısız:

array (3) {[0] => string (5) "00000" [1] => int (7) [2] => string (62) "HATA: anahtar benzersiz kısıtlaması ihlal yinelenen" id_h_orders ""}

array (3) {[0] => string (5) "25P02" [1] => int (7) [2] => string (87) "HATA: Geçerli işlem komutları işlem bloğunun sonuna kadar ihmal, iptal edilir "}

Ölümcül hata: satır 23 / srv/www/test-db/test-db-pgsql-08.php olmayan bir nesne üzerinde () getirme üye işlev çağrısı

Yani, gibi görünüyor zaman ilk ... işlem otomatik olarak iptal edilir (id 293 ile bir) başarısız yürütmek yapar PDO oto-geri alma, ya da başka bir şey?

Amacım ilk büyük while döngüsü tamamlamak, ve sonunda, bayrak gibi bir bool var kullanarak, işlem geri veya işlemeye karar etmektir.

2 Cevap

Herhangi bir deyim, bir işlem sırasında bir sunucu hatası üretir eğer iptal PostgreSQL ile, bu işlem işaretlenir. Yani aslında pek except geri döndürün şeyi yapabilir ki henüz sadece döndürülüyor anlamına gelmez. Ben size "geri alma" yöntemi çağırmak için bekler, PDO otomatik bir geri alma sorunu yok varsayalım.

Ben seni istiyorum ne elde etmek için, bir kayıt noktası kullanabilirsiniz. Aksine tüm işlem geri alınıyor yerine, sadece kayıt noktasına geri alma ve işleme devam edebilirsiniz. Psql'de Bu kullanarak bir örnek vereyim:

srh@srh@[local] =# begin;
BEGIN
srh@srh@[local] *=# insert into t values(9,6,1,true);
INSERT 0 1
srh@srh@[local] *=# savepoint xyzzy;
SAVEPOINT
srh@srh@[local] *=# insert into t values(9,6,2,true);
ERROR:  duplicate key value violates unique constraint "t_pkey"
srh@srh@[local] !=# insert into t values(10,6,2,true);
ERROR:  current transaction is aborted, commands ignored until end of transaction block
srh@srh@[local] !=# rollback to savepoint xyzzy;
ROLLBACK
srh@srh@[local] *=# insert into t values(10,6,2,true);
INSERT 0 1
srh@srh@[local] *=# commit;
COMMIT
srh@srh@[local] =#

Yani bu örnekte, t ilk sütunu birincil anahtardır. Ben 9 bir kimliği ile t içine iki satır eklemek için çalıştı, ve bir teklik kısıtlama var. Şimdi herhangi bir ifadesi "geçerli işlem iptal edilir ..." hatası alırsınız çünkü ben sadece doğru değerleri ile insert kokan olamaz. Ama ben geri "savepoint" yaptım ben ("xyzzy" kayıt noktası adıdır) oldu durumuna getiriyor "kayıt noktasına geri alma", yapabilirsiniz. Sonra doğru uç komutu ve nihayet (her ikisi de ekler taahhüt) işlem taahhüt olabilir.

Yani sizin durumunuzda, ben yapmanız gereken ne şüpheleniyorsanız UPDATE deyimi önce bir kayıt noktası oluşturmak: bu bir hata verirse, bir "kayıt noktasına geri alma" yapmak ve bayrağını ayarlayın. Sen Savepoint için benzersiz adlar oluşturmak gerekir: bir sayaç kullanarak, örneğin.

Ben neden bütün bu yaptığınızı anlamıyorum tamamen emin değilim. Elbette en kısa sürede size işlem geri gidiyoruz bildiğiniz gibi işlemeyi durdurmak istiyor? Ya da ne vardır döngü oluyor bazı diğer işlem var mı?

Sen kullanarak olmalıdır

pdo_obj->beginTransaction()
pdo_obj->commit()
pdo_obj->prepare()

Ayrıca rastgele bir ilk örnek sonunda taahhüt var.

begin
// do all your stuff
// check for errors through interface
commit OR not

pg_query($pgConnection, "ROLLBACK"); // end of tx(1)
// start new transaction after last rollback = tx(2)
pg_query($pgConnection, "UPDATE users SET last_activity = NOW() WHERE id = '$id_user'");
// commit tx(2) or don't here
// this isn't needed pg_query($pgConnection, "COMMIT");

Eğer taahhüt olmadıysa, ve manuel olarak başka bir işlem, malzeme ayarlamak kullanmanız gerekir. Başarısız olabilir, çünkü sorgu hazırlanması (çağırmak varsa), bir işlemin bir parçasıdır. Eğer gerçekten sadece elle bir SQL deyimi almak ve sorguları çevirmek olamaz. PDO arayüzü nedenle soyutlamalar vardır. :)

http://uk3.php.net/pdo <- PDO kullanarak PHP / Postgre'nin Katı örnekleri

good luck