Неустранимая ошибка: неперехваченное исключение ‘mysqli_sql_exception’ с сообщением ‘Индекс не используется в запросе / подготовленном операторе’

#php #mysqli

#php #mysql #mysqli #mysql-insert-id #sql

Вопрос:

Когда я запускаю следующий код, я получаю сообщение об ошибке

Неустранимая ошибка: неперехваченное исключение ‘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 failedn";
        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_sql_exception все ошибки и предупреждения из-за вашей mysqli_report(MYSQLI_REPORT_ALL); строки.
  • Ваш PHP-код не улавливает это исключение (т. Е. Оно не находится в try{} блоке с соответствующим catch(){} блоком), и неперехваченные исключения являются фатальными.

Вы ничего не можете сделать с первым, как упоминалось в другом ответе. Итак, вы можете исправить это, либо изменив свой mysqli_report(...) параметр на MYSQLI_REPORT_STRICT или MYSQLI_REPORT_OFF , либо на что-либо другое, кроме MYSQLI_REPORT_ALL .

(редактировать: комментарий w3d ниже дает хорошее объяснение, почему, и предлагает использовать mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) в качестве хорошей альтернативы)

Для получения наилучших практик и в сочетании с этим вы должны исправить это должным образом, используя try{} и catch(){} соответствующим образом в своем коде.

Комментарии:

1. Это часто имеет низкую степень серьезности, но не следует пренебрегать: в сообщении говорится, что сервер mysql должен выполнить полное сканирование таблицы, т. Е. Должен проверять каждую запись, принадлежит ли она к результирующему набору или нет. В случае большой базы данных может помочь дополнительный индекс к искомым столбцам.

2. В частности, чтобы удалить эти конкретные предупреждения, вам необходимо удалить MYSQLI_REPORT_INDEX флаг из report_mode свойства. Этот флаг «Сообщает, если в запросе не использовался индекс или неверный индекс». Итак, используйте 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 сообщает о слишком большом количестве предупреждений

Цитирую несколько предложений примечания :

Расширение Mysqli выдает слишком много предупреждений.
Например, «ВЫБРАТЬ * ИЗ таблицы» выдает предупреждение: «Предупреждение: mysqli::query(): нет индекса, используемого в запросе / подготовленном операторе ВЫБЕРИТЕ * ИЗ таблицы …»

И, цитируя другое примечание, которое кажется интересным :

Используйте mysqli_report() , чтобы отключить это.

Комментарии:

1. Хммм… Я не думаю, что это устарело, так как я использую его очень хорошо .. mysqli_report (MYSQLI_REPORT_ALL);

2. Устаревший не означает «не работает», но «больше не должен использоваться и может быть удален в один прекрасный день»

3. Верно, но то, что у меня есть, это не предупреждение, это фатальная ошибка. Я хотел бы знать о фатальных ошибках.

4. Он не должен был быть устаревшим (похоже, это было случайно): bugs.php.net/bug.php?id=55329

5. Да, это все еще допустимая команда в PHP7, без сообщения об устаревании в документах: php.net/manual/en/function.mysqli-report.php

Ответ №4:

сообщение «Индекс не используется в запросе / подготовленном операторе» относится не к вашему коду PHP, а к дизайну вашей таблицы, просто ДОБАВЬТЕ индекс в вашу таблицу.

действительно, лучше всего включить ошибку / предупреждения в DEVELOP:

 mysqli_report(MYSQLI_REPORT_ALL);
  

но отключается в рабочей среде:

 mysqli_report(MYSQLI_REPORT_STRICT);
  

Ответ №5:

Другой способ исправить это — сделать столбец таблицы ‘name’ в MySQL индексом.

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

Комментарии:

1. Этого недостаточно, если у вас небольшая таблица. В этом случае MySQL / MariaDB неявно отключит индексы в таблице и объединит это с выбрасыванием mysqli, если индексы не используются, у вас будет приятный беспорядок при выравнивании звездочек 🙂 «Работает в prod, не работает в staging / dev».