3

PHP-PDO-SQLite でのトランザクションと更新に問題があります。

$db = new PDO('sqlite:database1.sqlite');

/*
$rowsnumber1 = $db->exec("CREATE TABLE IF NOT EXISTS questions(
id INTEGER PRIMARY KEY AUTOINCREMENT,
question TEXT NOT NULL,
answers INTEGER NOT NULL
)");
print('$rowsnumber1: '.$rowsnumber1.'<br />');

$rowsnumber2 = $db->exec("CREATE TABLE IF NOT EXISTS answers(
id INTEGER PRIMARY KEY AUTOINCREMENT,
qid INTEGER NOT NULL,
answer TEXT NOT NULL
)");
print('$rowsnumber2: '.$rowsnumber2.'<br />');
*/

//print('Inserting: '); $res = $db->exec("INSERT INTO questions (question,answers) VALUES ('Question',0)"); var_dump($res); print('<br />');

$qid = 1;

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

$db->beginTransaction();

// Variant 1
//print('Executing 1: '); $res1 = $db->exec("INSERT INTO answers (qid,answer) VALUES ($qid,'Answer')"); var_dump($res1); print('<br />');
//print('Executing 2: '); $res2 = $db->exec("UPDATE questions SET answers = answers+1 WHERE id = '".$qid."'"); var_dump($res2); print('<br />');

// Variant 2
print('Preparing 1: '); $statement1 = $db->prepare("INSERT INTO answers (qid,answer) VALUES (:qid,:answer)"); var_dump($statement1); print('<br />');
print('Preparing 2: '); $statement2 = $db->prepare("UPDATE questions SET answers = answers+1 WHERE id='".$qid."'"); var_dump($statement2); print('<br />');

print('Executing 1: '); $res1 = $statement1->execute(array('qid'=>$qid,'answer'=>'Answer')); var_dump($res1); print('<br />');
print('Executing 2: '); $res2 = $statement2->execute(); var_dump($res2); print('<br />');

$db->commit();
}
catch(Exception $e)
{
$db->rollBack();
print("Transaction failed: " .$e->getMessage());
}

質問の「id」と回答の「qid」が同じ($qid)の場合は問題ありません。問題は、テーブル「質問」に存在しない質問の「ID」を使用して回答を挿入しようとしたときに始まります。たとえば、テーブル「questions」には 1 つの質問 (「id」は「1」) があり、「id」=「5」で質問への回答を挿入しようとします。回答は挿入されますが、そのような「id」=「5」の質問がないため、質問は更新されません (セル「answers」は増分されません)。問題は、トランザクションがロールバックせず、更新が実行されて結果が「true」になるということですが、実際には更新はありません。トランザクションの何が問題で、更新すると「true」が返される理由

4

2 に答える 2

1

私は自分が間違ったことを理解しました。問題は、「try」セクションにロジックがないことです。$db->commit(); の前に 次の 2 行を書くべきでした。

if($res1 != 1) throw new Exception("Inserting the answer failed");
if($res2 != 1) throw new Exception("Updating the question failed");

prepare(); について そしてexecute(); - ここの PDO のマニュアルをうっかり読んでしまいましたhttp://www.php.net/manual/en/pdostatement.execute.php 問題は、execute(); ということです。ステートメントが実行された場合は「true」を返しますが、それが行に影響を与えたかどうかはチェックしません。そしてメソッド exec(); 行が影響を受けたかどうかを確認します。つまり、メソッド prepare(); そしてexecute(); この状況では適していません。コメントした「バリアント1」を使用する必要がありました。

于 2013-05-11T05:40:12.030 に答える