我已经有很长一段时间了,在搜寻并参考上帝之后,知道有多少文档,无法弄清楚我在做什么错。
我要做什么
我正在尝试使用以下功能在数据库上执行准备好的更新状态:
function _UPDATE_IP_BAD(&$mysqli, $id_of_ip, &$value){
ini_set('display_errors', 1); ini_set('log_errors',1); error_reporting(E_ALL); mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$timestamp = time();
// UPDATE `dbmxpca_ipinfo`.`list` SET `is_bad` = '0.0111000000000000000', `cached_bad` = '1553849540' WHERE (`id` = '2');
$exec_data = array();
$prepare = "UPDATE dbmxpca_ipinfo.list SET `is_bad`=?, `cached_bad`=? WHERE `id`=?";
//$prepare = 'UPDATE dbmxpca_ipinfo.list SET `is_bad`=?, `cached_bad`=? WHERE `id`=?;';
//$prepare = 'UPDATE dbmxpca_ipinfo.list SET is_bad=?, cached_bad=? WHERE id=?;';
// $prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET is_bad=?, cached_bad=? WHERE id=?;';
//$prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET ( `is_bad`, `cached_bad` ) VALUES (?, ?) WHERE (`id`=' . $id_of_ip . ');';
//$prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET ( `is_bad`, `cached_bad` ) VALUES (?, ?) WHERE (`id`=' . $id_of_ip . ');';
//$prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET `is_bad`=?, `cached_bad`=? WHERE (`id`=?);';
//$prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET `is_bad`=?, `cached_bad`=? WHERE (`id`=?);';
//$prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET `is_bad` = ?, `cached_bad` = ? WHERE (`id` = ?);';
// $prepare = 'UPDATE `dbmxpca_ipinfo`.`list` SET `is_bad` = \'?\', `cached_bad` = \'?\' WHERE (`id` = \'?\');';
//$bind_types = 'iii';
$bind_types = 'dii';
//$bind_types = 'idi';
// $bind_types = 'di';
//$bind_values = array($value, $timestamp);
$bind_values = array($value, $timestamp, $id_of_ip);
$exec_result = DB_EXEC2($mysqli, $prepare, $bind_types, $bind_values, $exec_data);
if ($exec_result){
return true;
}
return false;
}
/ *
我这样称呼它:
UPDATE_IP_BAD($mysqli, 2, 0);
($ mysqli已在其他位置定义和初始化)。
问题
问题在于,DB_EXEC2()报告了一个成功的查询(应该影响到1行),但是数据库中两个值均未更新。未报告任何错误,但是数据库值保持不变。我在做错什么吗?
我尝试了多种不同的方式来编写准备好的语句(注释掉的行都行不通),而未注释的行也没有。我什至尝试了不同的绑定类型(整数与双精度),但无济于事。我已经研究了好几个小时,对可能出现的问题完全感到困惑。如我所见,即使在函数顶部添加其他错误报告也不会产生任何错误。
DB_EXEC2()是一个自定义函数,用于执行准备好的语句。它将操作结果记录到文件中。函数定义如下:
function DB_EXEC2(&$mysqli, $prepare, $bind_types, &$bind_values, &$result_data = null){
// Get number of bind types.
$nBindTypeCount = strlen($bind_types);
// Get number of bind values.
$nBindValCount = count($bind_values);
// Make sure they match.
if ($nBindTypeCount != $nBindValCount){
$errmsg = 'DB_EXEC2 Error: [Number of bind types does not match number of bind parameters].';
if (ENABLE_LOG_DB){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
return false;
}
// Prepare
$stmt = $mysqli->prepare($prepare);
if ($stmt === false){
// ------------ Prepared statement error ------------
$errmsg = 'SQL Prepared-Statement Error: [' . $mysqli->errno . ': ' . $mysqli->error . '].';
if (ENABLE_LOG_DB){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
$stmt->close();
return false;
}
// Make array of all params.
$fparams = array();
array_push($fparams, $bind_types);
foreach($bind_values as $bvk){
array_push($fparams, $bvk);
}
// Fucking piece of shit "hack" for this piece of shit function call_user_func_array().
$ptrParams = array();
$nParamCount = count($fparams);
for ($i = 0; $i < $nParamCount; $i++){
$ptrParams[$i] = &$fparams[$i];
}
// Dump values to log file for debugging.
if (ENABLE_LOG_DB){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', 'ptrParams Dump:');
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', '-----------------------');
foreach ($ptrParams as $ptrParamsK){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', ' ' . $ptrParamsK);
}
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', '-----------------------');
}
// Bind.
call_user_func_array(array($stmt, 'bind_param'), $ptrParams);
// Attempt to execute.
if ($stmt->execute() === true){
// ------------ Execution success ------------
$errmsg = 'SQL execution successful:';
if (ENABLE_LOG_DB){
$errmsg = 'SQL execution successful.';
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', $errmsg);
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', 'Affected Rows = [' . $stmt->affected_rows . '].');
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', 'Error = [' . $stmt->error . '].');
}
// TODO: If $result_data is null, just return true on success.
$result = $stmt->get_result();
if (!$result){
// ------------ GetResult Execution error ------------
if (ENABLE_LOG_DB){
$errmsg = 'GetResult Error: [' . $mysqli->error . ' - ' . mysqli_error($mysqli) . '].';
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
$stmt->close();
return false;
}
else{
// ------------ GetResult Execution success ------------
// Create structure to store the results.
if (!isset($result_data)){
$result_data = array();
}
if (mysqli_num_rows($result) > 0){
// $result_data should hold all resulting rows. If we get 1 result as
// we normally should, all payload should be at $result_data[0].
while($row = mysqli_fetch_assoc($result)){
array_push($result_data, $row);
}
$stmt->close();
return true;
}
else{
// No results
$stmt->close();
return true;
}
}
$stmt->close();
return true;
}
else{
// ------------ Execution error ------------
$errsql = $stmt->error;
$errsql2 = 'N/A';
$errmsg = 'SQL Error: [' . $errsql . ': ' . $errsql2 . '].';
if (ENABLE_LOG_DB){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
$stmt->close();
return false;
}
}
日志输出(供参考):
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: ptrParams Dump:
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: -----------------------
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: dii
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: 0
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: 1561439914
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: 2
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: -----------------------
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: SQL execution successful.
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: Affected Rows = [1].
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_EXEC2]: Error = [].
[06/25/2019 @ 01:18:34 AM EDT] [ERROR] [@DB_EXEC2]: GetResult Error: [ - ].
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_CLOSE]: Closing database connection...
[06/25/2019 @ 01:18:34 AM EDT] [INFO] [@DB_CLOSE]: Done.
**更新1 **
由于@Your常识而添加了此代码:
$stmt = DB_EXEC3($mysqli, $sql, $aParams, $strBindTypes);
if ($stmt === true){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', "Success!");
return true;
}
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', "stmt->execute() did not return true.");
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', "-- Error ID: $stmt->errno");
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', "-- Error: $stmt->error");
if (isset($stmt->error_list)){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', "-- Error List:");
foreach ($stmt->error_list as $errk => $errv){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', "---- $errk -> $errv");
}
}
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', "-- Affected rows: $stmt->affected_rows");
,结果日志将输出以下内容:
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@DB_CONNECT]: Attempting mysqli initialization... please wait.
[06/25/2019 @ 04:14:25 AM EDT] [ERROR] [@UPDATE_IP_BAD]: stmt->execute() did not return true.
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@UPDATE_IP_BAD]: -- Error ID: 0
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@UPDATE_IP_BAD]: -- Error:
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@UPDATE_IP_BAD]: -- Error List:
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@UPDATE_IP_BAD]: -- Affected rows: 1
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@DB_CLOSE]: Closing database connection...
[06/25/2019 @ 04:14:25 AM EDT] [INFO] [@DB_CLOSE]: Done.
因此,基本上,系统不会报告任何错误(尽管所有错误报告均已启用,这要归功于https://phpdelusions.net/mysqli/error_reporting
似乎暗示一切进展顺利(影响1行),但实际上由于某些神秘原因,行数据保持不变...
答案 0 :(得分:0)
我注释掉了错误记录部分(因为我不想设置内容和文件路径等),更改表名,并且代码似乎可以正常工作:
UPDATE_IP_BAD($mysqli, 1, 0);
function UPDATE_IP_BAD(&$mysqli, $id_of_ip, $value){
ini_set('display_errors', 1); ini_set('log_errors',1); error_reporting(E_ALL); mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$timestamp = time();
$exec_data = array();
$prepare = "UPDATE list SET `is_bad`=?, `cached_bad`=? WHERE `id`=?";
$bind_types = 'dii';
$bind_values = array($value, $timestamp, $id_of_ip);
$exec_result = DB_EXEC2($mysqli, $prepare, $bind_types, $bind_values, $exec_data);
if ($exec_result){
return true;
}
return false;
}
function DB_EXEC2(&$mysqli, $prepare, $bind_types, &$bind_values, &$result_data = null)
{
// Get number of bind types.
$nBindTypeCount = strlen($bind_types);
// Get number of bind values.
$nBindValCount = count($bind_values);
// Make sure they match.
if ($nBindTypeCount != $nBindValCount)
{
$errmsg = 'DB_EXEC2 Error: [Number of bind types does not match number of bind parameters].';
/* if (ENABLE_LOG_DB)
{
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
*/
return false;
}
// Prepare
$stmt = $mysqli->prepare($prepare);
if($stmt === false)
{
// ------------ Prepared statement error ------------
$errmsg = 'SQL Prepared-Statement Error: [' . $mysqli->errno . ': ' . $mysqli->error . '].';
/* if (ENABLE_LOG_DB)
{
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
} */
$stmt->close();
return false;
}
// Make array of all params.
$fparams = array();
array_push($fparams, $bind_types);
foreach($bind_values as $bvk)
{
array_push($fparams, $bvk);
}
// Fucking piece of shit "hack" for this piece of shit function call_user_func_array().
$ptrParams = array();
$nParamCount = count($fparams);
for ($i = 0; $i < $nParamCount; $i++)
{
$ptrParams[$i] = &$fparams[$i];
}
// Dump values to log file for debugging.
/* if(ENABLE_LOG_DB)
{
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', 'ptrParams Dump:');
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', '-----------------------');
foreach ($ptrParams as $ptrParamsK)
{
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', ' ' . $ptrParamsK);
}
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', '-----------------------');
} */
// Bind.
call_user_func_array(array($stmt, 'bind_param'), $ptrParams);
// Attempt to execute.
if ($stmt->execute() === true)
{
// ------------ Execution success ------------
$errmsg = 'SQL execution successful:';
/* if(ENABLE_LOG_DB)
{
$errmsg = 'SQL execution successful.';
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', $errmsg);
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', 'Affected Rows = [' . $stmt->affected_rows . '].');
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'INFO', 'Error = [' . $stmt->error . '].');
}
*/
// TODO: If $result_data is null, just return true on success.
$result = $stmt->get_result();
if (!$result){
// ------------ GetResult Execution error ------------
/* if (ENABLE_LOG_DB){
$errmsg = 'GetResult Error: [' . $mysqli->error . ' - ' . mysqli_error($mysqli) . '].';
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
*/
$stmt->close();
return false;
}
else{
// ------------ GetResult Execution success ------------
// Create structure to store the results.
if (!isset($result_data)){
$result_data = array();
}
if (mysqli_num_rows($result) > 0){
// $result_data should hold all resulting rows. If we get 1 result as
// we normally should, all payload should be at $result_data[0].
while($row = mysqli_fetch_assoc($result)){
array_push($result_data, $row);
}
$stmt->close();
return true;
}
else{
// No results
$stmt->close();
return true;
}
}
$stmt->close();
return true;
}
else{
// ------------ Execution error ------------
$errsql = $stmt->error;
$errsql2 = 'N/A';
$errmsg = 'SQL Error: [' . $errsql . ': ' . $errsql2 . '].';
/* if (ENABLE_LOG_DB){
\SYSTEM\DBMSLOG2(DB_LOGNAME, 'ERROR', $errmsg);
}
*/
$stmt->close();
return false;
}
}
答案 1 :(得分:0)
说实话,您的函数很难阅读。让我建议您改为我写的very simple mysqli helper function。有了它,您的代码将成为
function UPDATE_IP($mysqli, $id_of_ip, $value){
$prepare = "UPDATE list SET `is_bad`=?, `cached_bad`=? WHERE `id`=?";
$bind_values = array($value, time(), $id_of_ip);
return mysqli($mysqli, $prepare, $bind_values)->affected_rows();
}
现在您可以这样称呼
$num_rows = UPDATE_IP_BAD($mysqli, 2, 0);
echo $num_rows;
,它应该显示受影响的行数。
我刚刚注意到ipinfo.list.list
不是一个有效的表名,因此必须出现错误。您必须正确配置mysqli才能查看mysql错误。请参阅此canonical mysqli connection code。我写道,除其他外,它还配置了错误报告。进行设置后,您将立即看到错误。
答案 2 :(得分:0)
事实证明,设置了以下选项:SET AUTOCOMMIT = 0
函数中的DB_CONNECT()
(原始帖子中未包括)。删除它似乎已经解决了问题。
因此,确实有可能出现第三种结果 (与评论中所说的相反)。