2012-02-23 17 views
2

私はPHPとMySQLデータベースでPDOを使用しています。私がしたいのは、挿入が失敗したとき(一意フィールドの重複エントリなど)、例外エラーメッセージがスローされ、変更がロールバックされる(私の場合は自動インクリメントにならない)ときです。なぜこのPDOロールバックが機能しないのですか?

これは私がやったものですが、それは動作しません:

私は間違って行くのです
try { 
    $email = $_POST['Email']; 
    $FirstName = $_POST['FirstName']; 
    $LastName = $_POST['LastName']; 

    $query="INSERT INTO subscriber (Email,FirstName,LastName,CreateDate) VALUES (?,?,?,CURDATE())"; 
    $stmt = $conn->prepare($query); 

    $stmt->bindParam(1, $email , PDO::PARAM_STR); 
    $stmt->bindParam(2, $FirstName, PDO::PARAM_STR); 
    $stmt->bindParam(3, $LastName, PDO::PARAM_STR); 

    $stmt->execute(); 
} 
catch(PDOException $e) { 
    die ($e->getMessage().'<a href="addSub.php"> Back</a>'); 
    $conn->rollBack(); 
} 

これは編集バージョンです(挿入する部分全体で)、それは間違いありませんか?おかげで、すべての

if($_SERVER['REQUEST_METHOD'] == "POST"){ 


$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$conn->beingTransaction(); 
try { 

    $email = $_POST['Email']; 
    $FirstName = $_POST['FirstName']; 
    $LastName = $_POST['LastName']; 


    $query="INSERT INTO subscriber (Email,FirstName,LastName,CreateDate) VALUES (?,?,?,CURDATE())"; 
    $stmt = $conn->prepare($query); 


    $stmt->bindParam(1, $email , PDO::PARAM_STR); 
    $stmt->bindParam(2, $FirstName, PDO::PARAM_STR); 
    $stmt->bindParam(3, $LastName, PDO::PARAM_STR); 

    $conn->commit(); 

} 
catch(PDOException $e) 
    { 
    die ($e->getMessage().'<a href="addSub.php"> Back</a>'); 
    $conn->rollBack(); 
    } 


try { 
    $userID = $_SESSION['username']; 
    $query="INSERT INTO list_sub (SubID,ListID) VALUES ('',$_SESSION[ListID])"; 
    $stmt = $conn->prepare($query); 

    $conn->commit(); 

} 
catch(PDOException $e) 
    { 
    $conn->rollBack(); 
    die ($e->getMessage().'<a href="addSub.php"> Back</a>'); 
    } 

$conn = null; 
} 
+0

これを少し編集して回答を得ましたが、これは実際にはかなりローカライズされています。 'die()'はむしろ、自己記述的です:) –

答えて

9

これはすべてコードですか?

$conn->beginTransaction(); 

try { 
    .... 
    $conn->commit(); 
} catch (PDOException $e) { 
    $conn->rollback(); 
} 
+0

はその平均変更$ stmt-> execute()です。 $ conn-> commit();に – user782104

+0

また、私の編集版として複数のトランザクション(たとえば、2回挿入)がある場合はどうなりますか? – user782104

+0

いいえ... $ stmt-> execute()はまだ起きる必要があります。$ conn-> commit()を呼び出す前に$ stmt-> execute()を呼び出します。悪いところでは、投稿を編集して、仕事にぶつかった。 –

2

まず、die()のご利用には、プログラムを終了しますので、それが実行されますがない行の後。

しかし、それ以外にも、あなたが設定されていることを確認する必要があります。

まず、subscriberInnoDBテーブルタイプであることを確認します。 MySQLのデフォルトのテーブルタイプ(MyISAM)はトランザクションをサポートしていません。

第2に、PDOオブジェクトのPDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTIONに設定されていることを確認してください。このプロパティは、コンストラクタで設定するか、setAttribute()を使用して設定できます。

第3に、try句の前に実際に$conn->beginTransaction()でトランザクションを開始する必要があります。

+0

$ conn-> setAttribute(PDO :: ATTR_ERRMODE、PDO :: ERRMODE_EXCEPTION); これをコードの先頭に追加しますか? – user782104

0

Your put die...

この言語コンストラクトは、()を終了することと等価です。

1

AUTOINCREMENT値が連続しているという保証はありません。

2つのトランザクションが同時に同じテーブルに挿入されている場合、番号付けに穴があることを受け入れるか、最初のトランザクションが開始されるまで2番目のトランザクションが待機する必要があります。それがパフォーマンスにとって悪いので、「穴は許容可能です」という変形が実装されています。

5

PHP関数dieは、exitのエイリアスで、指定されたメッセージを印刷した直後に実行を終了するので、2番目の行、つまりロールバックは実行されません。

関連する問題