Spec-Zone.ru › MySQL Connectors 1.0

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

По умолчанию, 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. 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-8.0-en/c-api-multiple-queries.html

Spec-Zone.ru

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