Перейти к содержимому

Как сделать несколько запросов в одном запросе sql

  • автор:

Вывод нескольких SELECT-ов в одну таблицу

можно воспользоваться объединением запросов (union):

select "запрос 1", count(*) from . where . union select "запрос 2", count(*) from . where . union . 

Отслеживать
ответ дан 29 ноя 2016 в 6:39
aleksandr barakin aleksandr barakin
68k 218 218 золотых знаков 79 79 серебряных знаков 221 221 бронзовый знак

Предложу такой вариант: Написать процедуру, в которой: 1) Будет создаваться таблица, определяющая Вашу результирующую таблицу 2) Делать выборки исходной таблицы 3) Проходится по каждой выборки и вставлять данные в таблицу, созданную в 1 пункте

Отслеживать
ответ дан 29 ноя 2016 в 0:44
2,015 4 4 золотых знака 27 27 серебряных знаков 53 53 бронзовых знака

Вот как решил проблему

SELECT "request_1" AS "Запрос 1", "request_2" AS "Запрос 2", "request_3" AS "Запрос 3", "request_4" AS "Запрос 4" FROM ( -- Исполняем запрос 1 SELECT count("customer"."id") FROM "customer" WHERE "customer"."unsubscribed_types" = 'daily_weekdays' OR "customer"."unsubscribed_types" = 'daily_weekends' OR "customer"."unsubscribed_types" = 'weekly_free' OR "customer"."unsubscribed_types" = 'weekly_best_weekly' OR "customer"."unsubscribed_types" = 'special_partner' OR "customer"."unsubscribed_types" = 'bonus_activation' ) AS "request_1", ( -- Исполняем запрос 2 SELECT count("customer"."id") FROM "customer" WHERE "customer"."unsubscribed_types" ISNULL OR "customer"."unsubscribed_types" = '<>' ) AS "request_2", ( -- Исполняем запрос 3 SELECT count("customer"."id") FROM "customer" WHERE "customer"."unsubscribed_types" = 'daily_weekdays' AND "customer"."unsubscribed_types" = 'daily_weekends' AND "customer"."unsubscribed_types" = 'weekly_free' AND "customer"."unsubscribed_types" = 'weekly_best_weekly' AND "customer"."unsubscribed_types" = 'special_partner' AND "customer"."unsubscribed_types" = 'bonus_activation' ) AS "request_3", ( -- Исполняем запрос 4 SELECT count("customer"."id") FROM "customer" WHERE "unsubscribed_types" = 'daily_weekdays' ) AS "request_4", ; 

Отслеживать
ответ дан 29 ноя 2016 в 1:09
Sergey SHevchenko Sergey SHevchenko
49 1 1 золотой знак 1 1 серебряный знак 9 9 бронзовых знаков

  • sql
  • postgresql
  • запрос-в-запросе
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.8.3130

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Урок 2. Составные условия

В прошлом уроке мы научились выбирать совершеннолетних пользователей с помощью простого SQL запроса.

SELECT last_name, first_name, birthday FROM users WHERE age >= 18

Теперь попробуем немного уточнить запрос. Например, выберем всех совершенолетних мужчин. В таблицу я добавил дополнительное строковое поле sex, которое хранит m для мужчин и w для женщин:

Новая таблица users

id first_name last_name birthday age sex
1 Дмитрий Иванов 1996-12-11 20 m
2 Олег Лебедев 2000-02-07 17 m
3 Тимур Шевченко 1998-04-27 19 m
4 Светлана Иванова 1993-08-06 23 w
5 Олег Ковалев 2002-02-08 15 m
6 Алексей Иванов 1993-08-05 23 m
7 Алена Процук 1997-02-28 18 w

Давайте добавим вывод столбца sex и оставим только мужчин. Для этого в блоке условий, который начинается со слова WHERE нужно добавить AND sex = ‘m’:

SELECT last_name, first_name, birthday, sex FROM users WHERE age >= 18 AND sex = 'm'

После выполнения SQL запроса получиться такая таблица:

Результат выполнения SQL-запроса

id last_name first_name birthday sex
1 Иванов Дмитрий 1996-12-11 m
3 Шевченко Тимур 1998-04-27 m
6 Иванов Алексей 1993-08-05 m

Посмотрим на SQL запрос. Сейчас блок WHERE содержит составное условие: возраст больше или равен 18 годам и пол равен m. Это простое логическое выражение, которому соответствуют все записи для которых оба условия верны. То есть у которых одновременно и возраст от 18 лет и sex = «m».

Кстати, о sex = «m». Так как мы используем равенство, в результируеющей таблице в колонке sex для всех записей у нас выводится m. Это не логично, ведь мы и так знаем, что выбираем мужчин, поэтому смысла в том, что мы эту информацию выводим в таблице нет. А значит можно удалить sex из запроса. Удалим и посмотрим на результат выполнения SQL-запроса:

SELECT last_name, first_name, birthday FROM users WHERE age >= 18 AND sex = 'm'
Результат выполнения SQL-запроса

id last_name first_name birthday
1 Иванов Дмитрий 1996-12-11
3 Шевченко Тимур 1998-04-27
6 Иванов Алексей 1993-08-05

Строки выводятся те же, однако столбца sex больше нет.

Обратите внимание, что извлекаем мы столбцы last_name, first_name, birthday, а фильтрутем по age и sex. То есть не обязательно чтобы столбцы, которые мы получаем, совпадали со столбцами в условии. Главное, чтобы все они были в таблице.

Но вернемся к составным условиям.

Кроме операции AND (И), в условии можно применять OR (ИЛИ). Давайте заменим AND на OR, а также вернем колонки sex и age:

SELECT last_name, first_name, birthday, sex FROM users WHERE age >= 18 OR sex = 'm'

И посмотрим на результат:

Новая таблица users

>

id last_name first_name birthday sex age
1 Иванов Дмитрий 1996-12-11 m 20
2 Лебедев Олег 2000-02-07 m 17
3 Шевченко Тимур 1998-04-27 m 19
4 Иванова Светлана 1993-08-06 w 23
5 Ковалев Олег 2002-02-08 m 15
6 Иванов Алексей 1993-08-05 m 23
7 Процук Алена 1997-02-28 w 18

Получили всех мужчин, а также женщин, которым исполнилось 18 лет. В частности в SQL-таблице две женщины старше 18 лет и все мужчины, даже те, которым меньше 18. Всё это соответствует условию ИЛИ. ИЛИ возраст от 18 лет, ИЛИ мужской пол.

Теперь переключимся на таблицу products. В ней появилось поле country, которое содержит данные о стране производителе:

Таблица products

id name count price country
1 Телевизор 3 43200.00 RU
2 Микроволновая печь 4 3200.00 RU
3 Холодильник 3 12000.00 UA
4 Роутер 1 1340.00 US
5 Компьютер 0 26150.00 US
6 Утюг 6 3200.00 BL
7 Пылесос 11 4500.00 UA

Давайте выберем товары, произведененные в России, Белоруссии и на Украине. Напишем SQL-запрос:

SELECT * FROM products WHERE country = "RU" OR country = "UA" OR country = "BL"

После выполнения запроса мы получим следующую таблицу:

Результат выполнения запроса

id name count price country
1 Телевизор 3 43200.00 RU
2 Микроволновая печь 4 3200.00 RU
3 Холодильник 3 12000.00 UA
6 Утюг 6 3200.00 BL
7 Пылесос 11 4500.00 UA

Разберем запрос: в блоке WHERE мы используем три условия, разделенные OR (или). Во всех трех условиях мы с помощью символа равенства сравниваем значение в столбце country с одной из стран: ИЛИ Россия, ИЛИ Украина, ИЛИ Белоруссия.

Если мы хотим получить товары еще каких-то стран, то нужно добавить еще условия OR. Это не очень удобно, так как запрос становится громоздиким.

Но его можно упростить. Кроме стандартных условий сравнения AND и OR в языке SQL есть условие принадлежности IN, которое в данном случае подходит лучше. Напишем после WHERE:

SELECT * FROM products WHERE country IN ("RU", "UA", "BL")

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

Но давайте добавим к запросу еще одно условие. Например нам нужны не просто товары, а товары стоимостью до 10 000 рублей. Напишем:

SELECT * FROM products WHERE country IN ("RU", "UK", "BL") AND price < 10000

И посмотрим результат:

Результат выполнения SQL-запроса

id name count price country
2 Микроволновая печь 4 3200.00 RU
6 Утюг 6 3200.00 BL
7 Пылесос 11 4500.00 UA

Получили новую таблицу с тремя записями, которые удовлетовряют новому условию. И в этом условии мы совместили AND и IN. То есть в SQL-запросах можно совмещать логические операции AND и OR с оператором IN. Что делает их очень гибкими.

Теперь давай попробуем выбрать товары, стоимостью от 10000 до 20000.

Условие с country уберем и напишем:

SELECT * FROM products WHERE price >= 10000 AND price 

В результате получается такая таблица:

Таблица products

id name count price country
3 Холодильник 3 12000.00 UA

Выполним — получили 1 товар в этом ценовом интервале. Рассмотрим на запрос. Как видите в этой конструкции мы снова написали двойное условие по одному полю — price. И с одной строны всё логично и понятно, а с другой стороны эту конструкцию также можно упростить.

SELECT * FROM products WHERE price BETWEEN 10000 AND 20000

Теперь запрос звучит так: ВЫБРАТЬ все столбцы из таблицы products, в которых цена между 10000 и 20000. Звучит более чем понятно.

После запуска мы получим всё тот же один товар.

Вообще AND, OR, IN и BETWEEN — это основные конструкции для построения условий в SQL запросах и используются они в блоке WHERE. Вы можете применять их как по одиночке, так комбинируя в самых разлчных вариантах.

Следующий урок

Урок 3. Порядок AND и OR

Вы узнаете о приоритете AND и OR, а также с ошибками, которые возникают у новичков в SQL-запросах с несколькими условиями.

Полный курс с практикой

  • 57 уроков
  • 261 задание
  • Сертификат
  • Поддержка преподавателя
  • Доступ к курсу навсегда
  • Можно в рассрочку

Как сделать несколько запросов в одном запросе sql

WITH предоставляет способ записывать дополнительные операторы для применения в больших запросах. Эти операторы, которые также называют общими табличными выражениями (Common Table Expressions, CTE ), можно представить как определения временных таблиц, существующих только для одного запроса. Дополнительным оператором в предложении WITH может быть SELECT , INSERT , UPDATE или DELETE , а само предложение WITH присоединяется к основному оператору, которым также может быть SELECT , INSERT , UPDATE или DELETE .

7.8.1. SELECT в WITH

Основное предназначение SELECT в предложении WITH заключается в разбиении сложных запросов на простые части. Например, запрос:

WITH regional_sales AS ( SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region ), top_regions AS ( SELECT region FROM regional_sales WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) ) SELECT region, product, SUM(quantity) AS product_units, SUM(amount) AS product_sales FROM orders WHERE region IN (SELECT region FROM top_regions) GROUP BY region, product;

выводит итоги по продажам только для передовых регионов. Предложение WITH определяет два дополнительных оператора regional_sales и top_regions так, что результат regional_sales используется в top_regions , а результат top_regions используется в основном запросе SELECT . Этот пример можно было бы переписать без WITH , но тогда нам понадобятся два уровня вложенных подзапросов SELECT . Показанным выше способом это можно сделать немного проще.

Необязательное указание RECURSIVE превращает WITH из просто удобной синтаксической конструкции в средство реализации того, что невозможно в стандартном SQL. Используя RECURSIVE , запрос WITH может обращаться к собственному результату. Очень простой пример, суммирующий числа от 1 до 100:

WITH RECURSIVE t(n) AS ( VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 100 ) SELECT sum(n) FROM t;

В общем виде рекурсивный запрос WITH всегда записывается как не рекурсивная часть, потом UNION (или UNION ALL ), а затем рекурсивная часть, где только в рекурсивной части можно обратиться к результату запроса. Такой запрос выполняется следующим образом:

Вычисляется не рекурсивная часть. Для UNION (но не UNION ALL ) отбрасываются дублирующиеся строки. Все оставшиеся строки включаются в результат рекурсивного запроса и также помещаются во временную рабочую таблицу.

Вычисляется рекурсивная часть так, что рекурсивная ссылка на сам запрос обращается к текущему содержимому рабочей таблицы. Для UNION (но не UNION ALL ) отбрасываются дублирующиеся строки и строки, дублирующие ранее полученные. Все оставшиеся строки включаются в результат рекурсивного запроса и также помещаются во временную промежуточную таблицу.

Примечание

Строго говоря, этот процесс является итерационным, а не рекурсивным, но комитетом по стандартам SQL был выбран термин RECURSIVE .

В показанном выше примере в рабочей таблице на каждом этапе содержится всего одна строка и в ней последовательно накапливаются значения от 1 до 100. На сотом шаге, благодаря условию WHERE , не возвращается ничего, так что вычисление запроса завершается.

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

WITH RECURSIVE included_parts(sub_part, part, quantity) AS ( SELECT sub_part, part, quantity FROM parts WHERE part = 'our_product' UNION ALL SELECT p.sub_part, p.part, p.quantity FROM included_parts pr, parts p WHERE p.part = pr.sub_part ) SELECT sub_part, SUM(quantity) as total_quantity FROM included_parts GROUP BY sub_part

Работая с рекурсивными запросами, важно обеспечить, чтобы рекурсивная часть запроса в конце концов не выдала никаких кортежей (строк), в противном случае цикл будет бесконечным. Иногда для этого достаточно применять UNION вместо UNION ALL , так как при этом будут отбрасываться строки, которые уже есть в результате. Однако часто в цикле выдаются строки, не совпадающие полностью с предыдущими: в таких случаях может иметь смысл проверить одно или несколько полей, чтобы определить, не была ли текущая точка достигнута раньше. Стандартный способ решения подобных задач — вычислить массив с уже обработанными значениями. Например, рассмотрите следующий запрос, просматривающий таблицу graph по полю link :

WITH RECURSIVE search_graph(id, link, data, depth) AS ( SELECT g.id, g.link, g.data, 1 FROM graph g UNION ALL SELECT g.id, g.link, g.data, sg.depth + 1 FROM graph g, search_graph sg WHERE g.id = sg.link ) SELECT * FROM search_graph;

Этот запрос зациклится, если связи link содержат циклы. Так как нам нужно получать в результате « depth » , одно лишь изменение UNION ALL на UNION не позволит избежать зацикливания. Вместо этого мы должны как-то определить, что уже достигали текущей строки, пройдя некоторый путь. Для этого мы добавляем два столбца path и cycle и получаем запрос, защищённый от зацикливания:

WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS ( SELECT g.id, g.link, g.data, 1, ARRAY[g.id], false FROM graph g UNION ALL SELECT g.id, g.link, g.data, sg.depth + 1, path || g.id, g.id = ANY(path) FROM graph g, search_graph sg WHERE g.id = sg.link AND NOT cycle ) SELECT * FROM search_graph;

Помимо предотвращения циклов, значения массива часто бывают полезны сами по себе для представления « пути » , приведшего к определённой строке.

В общем случае, когда для выявления цикла нужно проверять несколько полей, следует использовать массив строк. Например, если нужно сравнить поля f1 и f2 :

WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS ( SELECT g.id, g.link, g.data, 1, ARRAY[ROW(g.f1, g.f2)], false FROM graph g UNION ALL SELECT g.id, g.link, g.data, sg.depth + 1, path || ROW(g.f1, g.f2), ROW(g.f1, g.f2) = ANY(path) FROM graph g, search_graph sg WHERE g.id = sg.link AND NOT cycle ) SELECT * FROM search_graph;

Подсказка

Часто для распознавания цикла достаточного одного поля и тогда ROW() можно опустить. При этом будет использоваться не массив данных составного типа, а простой массив, что более эффективно.

Подсказка

Этот алгоритм рекурсивного вычисления запроса выдаёт в результате узлы, упорядоченные по пути погружения. Чтобы получить результаты, отсортированные по глубине, можно добавить во внешний запрос ORDER BY по столбцу « path » , полученному, как показано выше.

Для тестирования запросов, которые могут зацикливаться, есть хороший приём — добавить LIMIT в родительский запрос. Например, следующий запрос зациклится, если не добавить предложение LIMIT :

WITH RECURSIVE t(n) AS ( SELECT 1 UNION ALL SELECT n+1 FROM t ) SELECT n FROM t LIMIT 100;

Но в данном случае этого не происходит, так как в PostgreSQL запрос WITH выдаёт столько строк, сколько фактически принимает родительский запрос. В производственной среде использовать этот приём не рекомендуется, так как другие системы могут вести себя по-другому. Кроме того, это не будет работать, если внешний запрос сортирует результаты рекурсивного запроса или соединяет их с другой таблицей, так как в подобных случаях внешний запрос обычно всё равно выбирает результат запроса WITH полностью.

Запросы WITH имеют полезное свойство — они вычисляются только раз для всего родительского запроса, даже если этот запрос или соседние запросы WITH обращаются к ним неоднократно. Таким образом, сложные вычисления, результаты которых нужны в нескольких местах, можно выносить в запросы WITH в целях оптимизации. Кроме того, такие запросы позволяют избежать нежелательных вычислений функций с побочными эффектами. Однако есть и обратная сторона — оптимизатор не может распространить ограничения родительского запроса на запрос WITH так, как он делает это для обычного подзапроса. Запрос WITH обычно выполняется буквально и возвращает все строки, включая те, что потом может отбросить родительский запрос. (Но как было сказано выше, вычисление может остановиться раньше, если в ссылке на этот запрос затребуется только ограниченное число строк.)

Примеры выше показывают только предложение WITH с SELECT , но таким же образом его можно использовать с командами INSERT , UPDATE и DELETE . В каждом случае он по сути создаёт временную таблицу, к которой можно обратиться в основной команде.

7.8.2. Изменение данных в WITH

В предложении WITH можно также использовать операторы, изменяющие данные ( INSERT , UPDATE или DELETE ). Это позволяет выполнять в одном запросе сразу несколько разных операций. Например:

WITH moved_rows AS ( DELETE FROM products WHERE "date" >= '2010-10-01' AND "date" < '2010-11-01' RETURNING * ) INSERT INTO products_log SELECT * FROM moved_rows;

Этот запрос фактически перемещает строки из products в products_log . Оператор DELETE в WITH удаляет указанные строки из products и возвращает их содержимое в предложении RETURNING ; а затем главный запрос читает это содержимое и вставляет в таблицу products_log .

Следует заметить, что предложение WITH в данном случае присоединяется к оператору INSERT , а не к SELECT , вложенному в INSERT . Это необходимо, так как WITH может содержать операторы, изменяющие данные, только на верхнем уровне запроса. Однако при этом применяются обычные правила видимости WITH , так что к результату WITH можно обратиться и из вложенного оператора SELECT .

Операторы, изменяющие данные, в WITH обычно дополняются предложением RETURNING (см. Раздел 6.4), как показано в этом примере. Важно понимать, что временная таблица, которую можно будет использовать в остальном запросе, создаётся из результата RETURNING , а не целевой таблицы оператора. Если оператор, изменяющий данные, в WITH не дополнен предложением RETURNING , временная таблица не создаётся и обращаться к ней в остальном запросе нельзя. Однако такой запрос всё равно будет выполнен. Например, допустим следующий не очень практичный запрос:

WITH t AS ( DELETE FROM foo ) DELETE FROM bar;

Он удалит все строки из таблиц foo и bar . При этом число задействованных строк, которое получит клиент, будет подсчитываться только по строкам, удалённым из bar .

Рекурсивные ссылки в операторах, изменяющих данные, не допускаются. В некоторых случаях это ограничение можно обойти, обратившись к конечному результату рекурсивного WITH , например так:

WITH RECURSIVE included_parts(sub_part, part) AS ( SELECT sub_part, part FROM parts WHERE part = 'our_product' UNION ALL SELECT p.sub_part, p.part FROM included_parts pr, parts p WHERE p.part = pr.sub_part ) DELETE FROM parts WHERE part IN (SELECT part FROM included_parts);

Этот запрос удаляет все непосредственные и косвенные составные части продукта.

Операторы, изменяющие данные в WITH , выполняются только один раз и всегда полностью, вне зависимости от того, принимает ли их результат основной запрос. Заметьте, что это отличается от поведения SELECT в WITH : как говорилось в предыдущем разделе, SELECT выполняется только до тех пор, пока его результаты востребованы основным запросом.

Вложенные операторы в WITH выполняются одновременно друг с другом и с основным запросом. Таким образом, порядок, в котором операторы в WITH будут фактически изменять данные, непредсказуем. Все эти операторы выполняются с одним снимком данных (см. Главу 13), так что они не могут « видеть » , как каждый из них меняет целевые таблицы. Это уменьшает эффект непредсказуемости фактического порядка изменения строк и означает, что RETURNING — единственный вариант передачи изменений от вложенных операторов WITH основному запросу. Например, в данном случае:

WITH t AS ( UPDATE products SET price = price * 1.05 RETURNING * ) SELECT * FROM products;

внешний оператор SELECT выдаст цены, которые были до действия UPDATE , тогда как в запросе

WITH t AS ( UPDATE products SET price = price * 1.05 RETURNING * ) SELECT * FROM t;

внешний SELECT выдаст изменённые данные.

Неоднократное изменение одной и той же строки в рамках одного оператора не поддерживается. Иметь место будет только одно из нескольких изменений и надёжно определить, какое именно, часто довольно сложно (а иногда и вовсе невозможно). Это так же касается случая, когда строка удаляется и изменяется в том же операторе: в результате может быть выполнено только обновление. Поэтому в общем случае следует избегать подобного наложения операций. В частности, избегайте подзапросов WITH , которые могут повлиять на строки, изменяемые основным оператором или операторами, вложенные в него. Результат действия таких запросов будет непредсказуемым.

В настоящее время, для оператора, изменяющего данные в WITH , в качестве целевой нельзя использовать таблицу, для которой определено условное правило или правило ALSO или INSTEAD , если оно состоит из нескольких операторов.

Пред. Наверх След.
7.7. Списки VALUES Начало Глава 8. Типы данных

Как сделать несколько запросов в одном запросе sql

Suggested improvement(s) to example 1.

reasons:
Multi_query only returns a non false response if a data/result set is returned and only checks for the first query entered. Switching the first SELECT query with the INSERT query will result in a premature exit of the example with the message "Multi query failed: (0)".
The example assumes that once the first query doesn't fail that the other queries have succeeded as well. Or rather it just exits without reporting that one of the queries after the first query failed seeing that if a query fails next_result returns false.

The changes in the example comes after the creation of the string $sql.

$mysqli = new mysqli ( "example.com" , "user" , "password" , "database" );
if ( $mysqli -> connect_errno ) echo "Failed to connect to MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( "DROP TABLE IF EXISTS test" ) || ! $mysqli -> query ( "CREATE TABLE test(id INT)" )) echo "Table creation failed: (" . $mysqli -> errno . ") " . $mysqli -> error ;
>

$sql = "SELECT COUNT(*) AS _num FROM test; " ;
$sql .= "INSERT INTO test(id) VALUES (1); " ;
$sql .= "SELECT COUNT(*) AS _num FROM test; " ;

// changes to example 1 start here

// don't bother checking the result from multi_query since it will return false
// if the first query does not return data even if the query itself succeeds.
$mysqli -> multi_query ( $sql );

do // while (true); // exit only on error or when there are no more queries to process
// check if query currently being processed hasn't failed
if ( 0 !== $mysqli -> errno )
echo "Multi query failed: (" . $mysqli -> errno . ") " . $mysqli -> error ;
break;
>

// exit loop if there ar no more queries to process
if ( false === ( $mysqli -> more_results () )
break;
>

// get result of the next query to process
// don't bother to check for success/failure of the result
// since at the start of the loop there is an error check &
// report block.
$mysqli -> next_result ()

> while ( true ); // exit only on error or when there are no more queries to process
?>

Note that the normal while ($mysqli->more_results() && $mysqli->next_result() has been replaced by two checks and while (true);
This is due to the 'problem' that next_result will return false if the query in question failed.
So one either needs to do one last check after the while loop to check if there was an error or one has to split up the different actions.
The changes in the example do the splitting.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *