2012-08-07 93 views
1

我有以下代碼:MySQL的交易無法正常工作

<?php 

// Conexion a MySQL 



$mysql_link = mysql_connect('localhost', 'root', '010101'); 

if (!$mysql_link) { 
    die('No se pudo conectar a la DB: ' . mysql_error()); 

} 

$mysql_db = mysql_select_db('test', $mysql_link); 

if (!$mysql_db) { 
die ('No se pudo seleccionar DB: ' . mysql_error()); 
    } 

$mysql_doc_query = "INSERT INTO documents (name, wfid, docid, archivo) VALUES  ('{$CodDoc}: {$documentoNombre} de {$DNI}', '{$workflowNombre}', '{$documentoNombre}',  '{$archivoNombre}'); 
     INSERT INTO keywords (document_id, keyword, value) VALUES (LAST_INSERT_ID(),  'DNI', '{$DNI}'), (LAST_INSERT_ID(), 'Cuit Empleador', 
     '{$cuitEmpleador}'), (LAST_INSERT_ID(), 'DigitalizadoPor', '{$usuario}'), 
    (LAST_INSERT_ID(), 'Direccion IP', '{$IP}'), (LAST_INSERT_ID(), 'Ubicacion',  CONCAT('pdfs/',LAST_INSERT_ID(),'.pdf'));"; 

    // Insert en mysql 
$log = fopen('/dev/shm/log.txt', 'w'); 
    if($log) { 
     fwrite($log, $mysql_doc_query); 
    } 

    mysql_query("START TRANSACTION"); 
    if (mysql_query($mysql_doc_query) == TRUE) 
    { 
     mysql_query("COMMIT"); 
    echo "\nCOMMIT!"; 
    } 
    else { 
     mysql_query("ROLLBACK"); 
     echo "\nROLLBACK!"; 
    } 
    mysql_close($mysql_link); 
fclose ($log); 
?> 

它總是給我ROLLBACK,但我不明白爲什麼。

任何線索?在log.txt歸檔中生成的代碼可以在PHP MY ADMIN中執行而不會出現問題。 (我知道這些變量沒有被引用,但是這是更大腳本的一部分)。

非常感謝。

+0

調試用'mysql_error()'你ROLLBACK塊你回滾之前 – 2012-08-07 20:08:05

+1

交易只能在InnoDB表使用。 – 2012-08-07 20:08:55

+0

這是什麼關鍵字查詢在做什麼? – Don 2012-08-07 20:11:18

回答

1

mysql_query()只支持一次發言。您正在執行多個INSERT語句一氣呵成:

$mysql_doc_query = "INSERT INTO documents (name, wfid, docid, archivo) VALUES  ('{$CodDoc}: {$documentoNombre} de {$DNI}', '{$workflowNombre}', '{$documentoNombre}',  '{$archivoNombre}'); 
     // Oops, new statement here! mysql_query() can't do that. 
     INSERT INTO keywords (document_id, keyword, value) VALUES (LAST_INSERT_ID(),  'DNI', '{$DNI}'), (LAST_INSERT_ID(), 'Cuit Empleador', 
     '{$cuitEmpleador}'), (LAST_INSERT_ID(), 'DigitalizadoPor', '{$usuario}'), 
    (LAST_INSERT_ID(), 'Direccion IP', '{$IP}'), (LAST_INSERT_ID(), 'Ubicacion',  CONCAT('pdfs/',LAST_INSERT_ID(),'.pdf'));"; 

這可能與mysql_error()進行調試您的ROLLBACK塊內:

if (mysql_query($mysql_doc_query) == TRUE) 
    { 
     mysql_query("COMMIT"); 
    echo "\nCOMMIT!"; 
    } 
    else { 
    echo "Error in query: " . mysql_error(); 
    mysql_query("ROLLBACK"); 
    echo "\nROLLBACK!"; 
    } 

如果您需要做兩個INSERT S,則需要兩個單獨的呼叫到mysql_query(),並檢查每個錯誤後。如果兩者都失敗,請執行您的ROLLBACK

+0

好吧,但我認爲使用交易將工作:S,我應該使用PDO? – JorgeeFG 2012-08-07 20:11:53

+0

@Jorge PDO在一次調用中不支持多個語句。但是建議切換到PDO,因爲它是支持預準備語句的更好的API,並且因爲舊的'mysql _ *()'API正在遭到貶損 – 2012-08-07 20:12:45

+0

@Jorge MySQLi has ['mysqli_multi_query()'](http://php.net /manual/en/mysqli.multi-query.php)並且還支持預準備語句。 – 2012-08-07 20:13:21

1

您的測試方法不好。 mysql_query()在出錯時返回一個布爾值FALSE,或者成功返回結果。通過PHP的類型轉換規則,結果句柄測試等於true。您必須使用嚴格的布爾比較,並excplicitly測試對假:

if (mysql_query($mysql_doc_query) !== FALSE) 
+0

我的第一個想法,但它是一個INSERT語句,並將成功返回布爾值TRUE。 – 2012-08-07 20:07:24

+0

手冊說:對於SELECT,SHOW,DESCRIBE,EXPLAIN和其他返回resultset的語句,mysql_query()在成功時返回一個資源,或者在錯誤時返回FALSE。 對於其他類型的SQL語句,INSERT,UPDATE,DELETE,DROP等,mysql_query()在成功時返回TRUE或在錯誤時返回FALSE。 這就是爲什麼我使用它。最初我使用if(mysql_query(query)){}而不是== TRUE – JorgeeFG 2012-08-07 20:09:47

+0

真的夠了。但你也試圖在單個查詢調用中插入** TWO **。 mysql驅動程序不允許將此作爲​​反sql注入緩解方法。所以你回來了布爾錯誤,並且因爲你沒有檢查mysql_error()來獲得失敗的真正原因,你只是得到了無用的「失敗」消息。 – 2012-08-07 20:09:51

1

在同一時間,你不能發送兩個MySQL查詢。您正在發送兩個不同的INSERT查詢。

此外,您必須發送沒有';'的查詢。因爲它是自動添加的。

1

運行交易標準的方式包括以下步驟:

mysql_query("SET AUTOCOMMIT=0"); //by default this is 1 
mysql_query("START TRANSACTION"); // start the transaction 

//run all the queries, possibly in a loop 
$q1 = mysql_query("INSERT INTO .... "); 
$q2 = mysql_query("INSERT INTO .... "); 

//check the success of all the queries and based on that commit or rollback 
if ($q1 and $q2) { 
    mysql_query("COMMIT"); 
} else {   
    mysql_query("ROLLBACK"); 
}