这是从 Flash Actionscript 应用程序调用的非常简单的方法,旨在仅删除一条记录。 这是一个包含 1,000 多个脚本的非常大的应用程序,其中许多脚本成功地使用了相同的模式……但是这个应用程序拒绝像其他脚本一样运行。
为了简单起见,我清理了部分代码,对于此目的没有意义 正如我之前所说,它非常简单(如您在代码中所见):
- 检查记录是否存在。
- 启动 MySql 事务(START TRANSACTION)
- 删除想要的记录
- 删除/更新一些其他相关信息(本代码省略)
- 如果一切正常,提交交易
问题如下:
- 如果我按代码所示运行脚本,在第一个 SELECT 语句 ($query1) 之后,mysqli_num_rows($result1) 返回 0(零)条记录,尽管我可以在数据库中看到该记录存在。而既然如此,显然不能删除,直接跳到脚本的末尾。但是,(这是最奇怪的行为!!!)记录实际上被删除了。
- 如果我注释 COMMIT 语句($query5),mysqli_num_rows($result1) 返回 1(一)。这应该没问题,并且 DELETE 语句运行正常($query4),但由于已对 COMMIT 进行注释,因此事务未正确完成并且所需的记录当然保留在数据库中。
- 如果我注释 SELECT 语句 ($query1) 并直接执行 DELETE 语句 ($query4),而不检查记录是否存在,记录将被正确删除,最后的 COMMIT 语句 ($query5) 确认数据库更改。
我已经一步步跟踪了好几个小时,但到目前为止,找不到这段代码无法正常运行的原因 我还用 mysqli_affected_rows 替换了 mysqli_num_rows(就 SELECT 语句而言,它们是相同的)但奇怪的行为仍然存在。
<?php
function f_ROLLBACK() {
global $messages;
global $conexion;
$query = "";
$query .= "ROLLBACK";
$result = mysqli_query( $conexion, $query);
if (!$result === true) {
$messages .= "\nInvalid Query\n".mysqli_error( $conexion )."\nQUERY:".$query;
} else {
$messages .= "\nTransaction successful ROLLBACK";
}//if (!$result === true)
return;
}//function f_ROLLBACK
include ("../config/DBconfig.inc.php");
$recID = isset($_POST["recID"]) ? $_POST["recID"] : "5";
$returnVars = array();
$messages = "";
$n = 0;
$now = gmdate("YmdHis");
//check if exists
$query1 = "";
$query1 .= "SELECT recID ";
$query1 .= " FROM records ";
$query1 .= " WHERE recID = ".$recID." ";
$result1 = mysqli_query( $conexion, $query1);
if (!$result1 === true) {
$messages .= "\nInvalid Query\n".mysqli_error( $conexion )."\nQUERY1:".$query1;
} else {
$rows1 = mysqli_num_rows($result1);
if ($rows1 < 1) {
$messages .= "\nSelected Record could not be found.";
} else {
$query2 = "";
$query2 .= "START TRANSACTION";
$result2 = mysqli_query( $conexion, $query2);
if (!$result2 === true) {
$messages .= "\nInvalid Query\n".mysqli_error( $conexion )."\nQUERY2:".$query2;
} else {
$query3 = "";
$query3 .= "SET autocommit = 0 ";
$result3 = mysqli_query( $conexion, $query3);
if (!$result3 === true) {
$messages .= "\nInvalid Query\n".mysqli_error( $conexion )."\nQUERY3:".$query3;
f_RollBack();
} else {
$query4 = "";
$query4 .= "DELETE FROM records ";
$query4 .= " WHERE recID = ".$recID." ";
$result4 = mysqli_query( $conexion, $query4);
if (!$result4 === true) {
$messages .= "\nInvalid Query\n".mysqli_error( $conexion )."\nQUERY4:".$query4;
f_RollBack();
} else {
$rows4 = mysqli_affected_rows($GLOBALS["___mysqli_ston"]);
if ($rows4 < 1) {
$messages .= "\nSelected Record could not be DELETED.\nQUERY4:".$query4;;
f_RollBack();
} else {
$query5 = "";
$query5 .= " COMMIT ";
$result5 = mysqli_query( $conexion, $query5);
if (!$result5 === true) {
$messages .= "\nInvalid Query\n".mysqli_error( $conexion )."\nTransaction has not been COMITTED."."\nQUERY5:".$query5;
}//if (!$result5 === true) COMMIT
}//if ($rows4 == -1)
}//if (!$result4 === true)
}//if ($rows3 < 1)
}//if (!$result3 === true)
}//if (!$result2 === true)
}//if (!$result1 === true)
mysqli_close($GLOBALS["___mysqli_ston"]);
if ($messages != "") {
$returnVars["retorno"] = "Error";
$returnVars["extra"] = $messages;
} else {
$returnVars["retorno"] = "OK";
$returnVars["extra"] = "";
}//if ($messages != "")
$returnString = http_build_query($returnVars);
//send variables back to Flash
echo $returnString;
?>
如果有人能发现我做错了什么,我将不胜感激。
最佳答案
我之前提供过这个但被否决了。我认为这个框架可能会对你有所帮助,所以我会再次冒险。哈哈。请注意,我希望它通过提供简单的调试方法(只需将 false 更改为 true ... 并打开调试!)来帮助您解决问题。
该系统的使用是将设置信息(#Sample Execution 之前的所有内容)放在页面顶部,将#functions 放在页面底部......然后有几个示例如何“使用”这两个函数从那时起用两行(一行定义查询,一行运行查询)获取数据。结果是数据库中的更改或包含您请求的数据的数组。希望能帮助到你。我们每天都在使用它。
define('DEBUG', false);
define('CLIDISPLAY', false);
if (CLIDISPLAY) {
define('PRE', '');
define('PRE_END', '');
} else {
define('PRE', '<pre>');
define('PRE_END', '</pre>');
}
require_once("../dbconnect.php");
$DBLink = new mysqli($VARDB_server, $VARDB_user, $VARDB_pass, $VARDB_database, $VARDB_port);
if ($DBLink->connect_errno) {
printf(PRE . "Connect failed: %s\n" . PRE_END, $DBLink->connect_error);
exit();
}
# Sample execution
$Query = "select * from vicidial_users where user='6666' and active='Y' limit 1";
$Records = GetData($DBLink, $Query);
print_r($Records[0]); // Single record return access via [0] to access a field named "id": $Records[0]['id']
// Multiple record return access via array walking
foreach ($Records as $Record) {
print_r($Record);
}
$Query = "update vicidial_users set active='Y' where user='6666' limit 1";
UpdateData($DBLink, $Query);
#Functions
function GetData($DBLink, $Query) {
if (DEBUG) {
echo PRE . "Query: $Query\n" . PRE_END;
}
if ($Result = $DBLink->query($Query)) {
if (DEBUG) {
printf(PRE . "Affected rows (Non-Select): %d\n" . PRE_END, $DBLink->affected_rows);
}
while ($Record = $Result->fetch_assoc()) {
$ReturnData[] = $Record;
}
return $ReturnData;
} else {
if (DEBUG) {
printf(PRE . "Errormessage: %s\n", $DBLink->error);
printf("Affected rows (Non-Select): %d\n", $DBLink->affected_rows);
echo "No Records Returned\n" . PRE_END;
}
return false;
}
}
function UpdateData($DBLink, $Query) {
if (DEBUG) {
echo PRE . "Query: $Query\n" . PRE_END;
}
if ($Result = $DBLink->query($Query)) {
if (DEBUG) {
printf(PRE . "%s\n", $DBLink->info);
printf("Affected rows (Non-Select): %d\n" . PRE_END, $DBLink->affected_rows);
}
return;
} else {
if (DEBUG) {
printf(PRE . "Errormessage: %s\n", $DBLink->error);
printf("Affected rows (Non-Select): %d\n", $DBLink->affected_rows);
echo "No Records Returned\n" . PRE_END;
}
return;
}
}
显然,dbconnect.php 及其加载的变量可以替换为您现有的版本。要排除故障:将调试更改为 TRUE 而不是 FALSE。然后查询将溢出到屏幕上,您可以将其直接复制/粘贴到您的数据库中,然后查看结果是否符合预期。请注意,为了获得最佳结果,您在执行此操作时仍然需要验证一些项目(其中一些只有在您运行相同查询时 php 脚本获得与您不同的结果时才需要):
- 确保您位于正在加载到您的凭据中的数据库中
- 确保您以与正在运行的脚本相同的用户身份使用相同的密码和相同的 IP 输入数据库。这可能需要使用 php 服务器上的 mysql 客户端从命令行访问数据库,以确保您的凭据和权限与 php 脚本相同。
CLIDISPLAY 常量仅用于从 CLI 而不是在网页上执行 php(使烦人的条目消失,但这些在 html 中非常有用)。
关于php - mysqli_query 返回 0 行(奇怪的行为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17508228/