2013-05-09 2 views
3

PHP-PDO-SQLite에서 트랜잭션에 문제가 있습니다.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) 아무런 문제가 없습니다. 문제는 "question"테이블에없는 질문의 "id"가 포함 된 대답을 삽입하려고 할 때 시작됩니다. 예를 들어, "questions"표에는 하나의 질문 ("id"가 "1")이 있고 "id"= "5"라는 질문에 대한 대답을 넣으려고합니다. 대답은 삽입되지만 질문은 "id"= "5"와 같은 질문이 없으므로 업데이트되지 않습니다 (셀 "답변"이 증가하지 않음). 문제는 트랜잭션이 롤백을하지 않고 업데이트가 실제로 실행되지만 결과가 "true"로 업데이트가 실행된다는 것입니다. 거래가 잘못되어 왜 명세서를 사용할 때 업데이트가 "true"를 반환합니까?

답변

1

나는 내가 잘못한 것을 이해했다. 문제는 'try'섹션에 논리가 없다는 것입니다. $ db-> commit() 전에; 다음 두 줄을 써야합니다.

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

준비(); 및 execute(); - 여기서 PDO 설명서를 부주의하게 읽었습니다 http://www.php.net/manual/en/pdostatement.execute.php 문제는 바로 execute(); 문이 실행될 경우 'true'를 반환하지만 행에 영향을 미치는지 여부는 확인하지 않습니다. 그리고 메소드 exec(); 행이 영향을 받았는지 확인합니다. 나는. 메소드 prepare(); 및 execute(); 이 상황에서는 적합하지 않습니다. 'Variant 1'을 사용 했어야합니다.

0

나는 쓰기 액세스 문제가 지속 된 후에 만 ​​비슷한 문제가있었습니다.

Apparantly 나는 커밋에 실패한 트랜잭션 내부에서 "foreign key constraint failed"오류가 발생했습니다.

데이터베이스 테이블을 직접 가져와 문제를 해결해야했습니다.

이 정보가 도움이되기를 바랍니다.