致命错误:未捕获的异常 'mysqli_sql_exception' 带有消息 'No index used in query/prepared statement'

Posted

技术标签:

【中文标题】致命错误:未捕获的异常 \'mysqli_sql_exception\' 带有消息 \'No index used in query/prepared statement\'【英文标题】:Fatal error: Uncaught exception 'mysqli_sql_exception' with message 'No index used in query/prepared statement'致命错误:未捕获的异常 'mysqli_sql_exception' 带有消息 'No index used in query/prepared statement' 【发布时间】:2011-07-31 14:30:07 【问题描述】:

当我运行以下代码时,我收到错误提示

致命错误:未捕获的异常 带有消息的“mysqli_sql_exception” '查询/准备中没有使用索引 声明'

$mysql = new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME) or die('There was a problem connecting to the database');
        if (mysqli_connect_errno()) 
            printf("DB error: %s", mysqli_connect_error());
            exit();
        

    $get_emp_list = $mysql->prepare("SELECT id, name FROM calc");
    if(!$get_emp_list)
        echo "prepare failed\n";
        echo "error: ", $mysql->error, "\n";
        return;
    
    $get_emp_list->execute();
    $get_emp_list->bind_result($id, $emp_list);

这是可行的模式--

--
-- Table structure for table `calc`
--

CREATE TABLE IF NOT EXISTS `calc` (
  `id` int(12) NOT NULL,
  `yr` year(4) NOT NULL,
  `mnth` varchar(12) NOT NULL,
  `name` varchar(256) NOT NULL,
  `paidleave` int(12) NOT NULL,
  `balanceleave` int(12) NOT NULL,
  `unpaidleave` int(12) NOT NULL,
  `basesalary` int(12) NOT NULL,
  `deductions` int(12) NOT NULL,
  `tds` int(12) NOT NULL,
  `pf` int(12) NOT NULL,
  `finalsalary` int(12) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

【问题讨论】:

【参考方案1】:

致命错误不在 MySQL 中;缺少索引通知是一个相对低严重性的警告。

致命错误在您的 php 代码中,因为以下三个情况:

mysqli 报告了很多个警告,即使在相对无害的情况下也是如此。 由于您的mysqli_report(MYSQLI_REPORT_ALL); 行,您将抛出mysqli_sql_exception 的所有错误警告。 您的 PHP 代码没有捕获该异常(即它不在具有适当 catch() 块的 try 块中),未捕获的异常是致命的。

正如另一个答案中提到的,你不能对第一个做太多事情。因此,您可以通过将mysqli_report(...) 设置更改为MYSQLI_REPORT_STRICTMYSQLI_REPORT_OFFMYSQLI_REPORT_ALL 以外的任何设置来修复它。

(编辑:w3d 下面的评论很好地解释了原因,并建议您可以使用mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 作为一个不错的选择)

为了获得最佳实践,并结合这一点,您应该通过在代码中适当地使用trycatch() 来正确修复它。

【讨论】:

它通常是低严重性但不应忽视:消息指出mysql服务器必须执行全表扫描,即必须检查每条记录是否属于结果集.在大型数据库的情况下,搜索列的附加索引可能会有所帮助。 具体来说,要删除这些特定警告,您需要从report_mode 属性中删除MYSQLI_REPORT_INDEX 标志。此标志“报告查询中是否使用了索引或错误索引”。因此,在执行查询之前使用 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 而不是 mysqli_report(MYSQLI_REPORT_ALL)`。【参考方案2】:
mysqli_report(MYSQLI_REPORT_ALL ^ MYSQLI_REPORT_INDEX);

关闭“在查询中未使用索引或错误索引时报告”但保持其他报告打开。

【讨论】:

【参考方案3】:

看看这个错误报告:#35450 mysqli extension reports too many warnings

引用笔记中的几句话:

Mysqli 扩展抛出太多 警告。 例如,“选择 * FROM 表”导致警告: “警告:mysqli::query(): 没有索引 用于查询/准备语句 SELECT * FROM 表..."

并且,引用另一个注释,这似乎很有趣:

使用mysqli_report() 禁用它。

【讨论】:

嗯...我不认为这是弃用的,因为我使用它很好.. mysqli_report(MYSQLI_REPORT_ALL); Deprecated 并不意味着“不起作用”,而是“不应再使用,并且可能有一天会被删除” 对,但我所拥有的不是警告,而是致命错误。我想知道致命错误。 它不应该被弃用(似乎是偶然的):bugs.php.net/bug.php?id=55329 是的,它仍然是 PHP7 中的有效命令,文档中没有弃用消息:php.net/manual/en/function.mysqli-report.php【参考方案4】:

解决它的另一种方法是使 MySQL 中的表列“名称”成为索引。

ALTER TABLE `calc` ADD INDEX ( `name` ) ;

【讨论】:

如果你有一张小桌子,这还不够。在这种情况下,MySQL/MariaDB 将隐式禁用表中的索引,如果没有使用索引,则将其与 mysqli throwing 结合起来,你有一个很好的 when-stars-align 混乱 :) “适用于 prod,不适用于 staging/dev "。

以上是关于致命错误:未捕获的异常 'mysqli_sql_exception' 带有消息 'No index used in query/prepared statement'的主要内容,如果未能解决你的问题,请参考以下文章

为啥我收到致命错误:未捕获的异常 'GuzzleHttp\Exception\RequestException' 和消息 'cURL 错误 60

致命错误:未捕获的异常“Phalcon\Mvc\Model\Exception”与消息“语法错误,意外令牌>,

线程以未捕获的异常退出,AyncTask #2 致命错误

致命错误:未捕获的异常“PDOException”,带有消息“SQLSTATE [42000]:语法错误或访问冲突 PHP 和 PDO

致命错误:未捕获的异常“异常”,消息“不正确的响应 ID:(请求 ID:1)”

致命错误:未捕获的异常“异常”;需要 CURL PHP 扩展 Google_Client.php