2012-08-07 95 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"); 
}