Spec-Zone.ru › MySQL Connectors 1.0

3.6.2 Поддержка выполнения нескольких операторов

По умолчанию, mysql_real_query() и mysql_query() интерпретируют строку оператора как один оператор для выполнения, и вы обрабатываете результат в зависимости от того, генерирует ли оператор набор результатов (набор строк, как для ) или количество затронутых строк (как для , , и так далее).

MySQL также поддерживает выполнение строки, содержащей несколько операторов, разделенных точкой с запятой (;) символами. Эта возможность активируется специальными параметрами, которые указываются либо при подключении к серверу с помощью mysql_real_connect(), либо после подключения путем вызова mysql_set_server_option().

Выполнение строки с несколькими операторами может привести к нескольким наборам результатов или показателям количества изменённых строк. Обработка этих результатов требует другого подхода, чем в случае с одним оператором: после обработки результата первого оператора необходимо проверить, существуют ли ещё результаты, и обработать их по очереди, если это так. Для поддержки обработки нескольких результатов в C API включены функции mysql_more_results() и mysql_next_result(). Эти функции используются в конце цикла, который итерирует до тех пор, пока доступны дополнительные результаты. Отсутствие обработки результатов таким образом может привести к разрыву подключения к серверу.

Обработка нескольких результатов также требуется, если вы выполняете операторы для хранимых процедур. Результаты хранимой процедуры имеют эти характеристики:

  • Операторы внутри процедуры могут генерировать наборы результатов (например, если она выполняет операторы). Эти наборы результатов возвращаются в порядке их создания по мере выполнения процедуры.

    В целом, вызывающая сторона не знает, сколько наборов результатов вернёт процедура. Выполнение процедуры может зависеть от циклов или условных операторов, которые изменяют путь выполнения от одного вызова к другому. Поэтому вы должны быть готовы к получению нескольких результатов.

  • Конечный результат процедуры — это результат состояния, который не содержит набора результатов. Состояние указывает, выполнилась ли процедура успешно или произошла ошибка.

Возможности обработки нескольких операторов и результатов могут быть использованы только с mysql_real_query() или mysql_query(). Они не могут быть использованы с интерфейсом подготовленных операторов. Обработчики подготовленных операторов определены для работы только со строками, содержащими один оператор. См. Главу 6, Интерфейс подготовленных операторов C API.

Для активации выполнения нескольких операторов и обработки нескольких результатов можно использовать следующие параметры:

  • Функция mysql_real_connect() имеет параметр flags, для которого два значения параметров важны:

    • CLIENT_MULTI_RESULTS позволяет программе-клиенту обрабатывать несколько результатов. Этот параметр обязательно должен быть включён, если вы выполняете операторы для хранимых процедур, которые генерируют наборы результатов. В противном случае такие процедуры приведут к ошибке Error 1312 (0A000): PROCEDURE proc_name can't return a result set in the given context. В MySQL 5.7 CLIENT_MULTI_RESULTS включено по умолчанию.

    • CLIENT_MULTI_STATEMENTS позволяет mysql_real_query() и mysql_query() выполнять строки операторов, содержащие несколько операторов, разделенных точкой с запятой. Этот параметр также неявно включает CLIENT_MULTI_RESULTS, поэтому параметр flags со значением CLIENT_MULTI_STATEMENTS для mysql_real_connect() эквивалентен параметру со значением CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS. То есть, CLIENT_MULTI_STATEMENTS достаточно для включения выполнения нескольких операторов и всей обработки нескольких результатов.

  • После установления подключения к серверу можно использовать функцию mysql_set_server_option() для включения или выключения выполнения нескольких операторов, передав в качестве аргумента значения MYSQL_OPTION_MULTI_STATEMENTS_ON или MYSQL_OPTION_MULTI_STATEMENTS_OFF. Включение выполнения нескольких операторов с помощью этой функции также включает обработку “простых” результатов для строки с несколькими операторами, где каждый оператор генерирует один результат, но недостаточно для обработки хранимых процедур, генерирующих наборы результатов.

Следующая процедура описывает рекомендуемую стратегию обработки нескольких операторов:

  1. Передайте CLIENT_MULTI_STATEMENTS в mysql_real_connect() для полного включения выполнения нескольких операторов и обработки нескольких результатов.

  2. После вызова mysql_real_query() или mysql_query() и проверки успеха, перейдите в цикл, в котором вы обрабатываете результаты операторов.

  3. Для каждой итерации цикла обработайте текущий результат оператора, получив либо набор результатов, либо количество затронутых строк. Если произошла ошибка, выйдите из цикла.

  4. В конце цикла вызовите mysql_next_result() для проверки наличия другого результата и запуска его извлечения, если таковой имеется. Если больше результатов нет, выйдите из цикла.

Один из возможных вариантов реализации описанной выше стратегии показан ниже. Конечная часть цикла может быть сокращена до простого тестирования, возвращает ли mysql_next_result() ненулевое значение. Приведённый код различает отсутствие дополнительных результатов и ошибку, что позволяет вывести сообщение для последнего случая.

/* connect to server with the CLIENT_MULTI_STATEMENTS option */
if (mysql_real_connect (mysql, host_name, user_name, password,
    db_name, port_num, socket_name, CLIENT_MULTI_STATEMENTS) == NULL)
{
  printf("mysql_real_connect() failed\n");
  mysql_close(mysql);
  exit(1);
}

/* execute multiple statements */
status = mysql_query(mysql,
                     "DROP TABLE IF EXISTS test_table;\
                      CREATE TABLE test_table(id INT);\
                      INSERT INTO test_table VALUES(10);\
                      UPDATE test_table SET id=20 WHERE id=10;\
                      SELECT * FROM test_table;\
                      DROP TABLE test_table");
if (status)
{
  printf("Could not execute statement(s)");
  mysql_close(mysql);
  exit(0);
}

/* process each statement result */
do {
  /* did current statement return data? */
  result = mysql_store_result(mysql);
  if (result)
  {
    /* yes; process rows and free the result set */
    process_result_set(mysql, result);
    mysql_free_result(result);
  }
  else          /* no result set or error */
  {
    if (mysql_field_count(mysql) == 0)
    {
      printf("%lld rows affected\n",
            mysql_affected_rows(mysql));
    }
    else  /* some error occurred */
    {
      printf("Could not retrieve result set\n");
      break;
    }
  }
  /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
  if ((status = mysql_next_result(mysql)) > 0)
    printf("Could not execute statement\n");
} while (status == 0);

mysql_close(mysql);

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/c-api-5.7-en/c-api-multiple-queries.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API