Мультизапросы в goDB

Мультизапрос, это выполнение нескольких запросов, за один раз. Запросы разделяются точкой с запятой.


$queries = '
	INSERT INTO `table1` VALUES(1,2,3);
	INSERT INTO `table2` VALUES(4,5,6);
	INSERT INTO `table3` VALUES(7,8,9);
';
$mysqli->multi_query($queries);
			

Этот вариант быстрее последовательной отправки запросов, но это не транзакция. То есть, в случае ошибки, например, в 3-м запросе, первые два всё равно внесут свои изменения в базу.

Mysqli для реализации мультизапросов предоставляет метод multi_query(). goDB оставляет этот метод нетронутым, а дополнительно предоставляет multiQuery().

Первый формат multiQuery()

В первом формате вызова данного метода, шаблоны, данные и форматы разбора передаются отдельными массивами.


array goDB::multiQuery(array $patterns, array $datas, array $fetches [, bool $transaction]);			
			

Пример:


$patterns = array(
	'INSERT INTO `table1` VALUES(?i,?i)',
	'INSERT INTO `table2` VALUES(?i,?i)',
	'INSERT INTO `table3` VALUES(?i,?i)',
);
$datas = array(
	array(1, 2),
	array(3, 4),
	array(5, 6),
);
$fetches = array('id', 'id', 'id');

$db->multiQuery($patterns, $datas, $fetches);
			

В этом случае будет выполнен следующий мультизапрос:


INSERT INTO `table1` VALUES(1,2);
INSERT INTO `table2` VALUES(3,4);
INSERT INTO `table3` VALUES(5,6);
			

А в качестве результата получен массив ID'шников вставленных строк.

Аргумент $transaction указывает надо ли выполнять мультизапрос в виде транзакции. По умолчанию надо (True).

Если $transaction=True и движок таблиц поддерживает транзакции, в случае ошибки в одном из запросов, состояние базы откатывается на начало мультизапроса. В противном случае, результаты верных запросов до первого ошибочного будут сохранены.

В этом формате вызова $patterns, $datas и $fetches должны быть порядковыми массивами одного размера.

Мультизапрос по одному шаблону


array goDB::multiQuery(string $patterns, array $datas, string $fetches [, bool $transaction]);			
			

Количество запросов составляющих мультизапрос определяется размером $datas. При этом $patterns и $fetches могут быть простыми строками, одинаковыми для каждого запроса.

Предыдущий пример немного по другому:


$patterns = 'INSERT INTO ?t VALUES(?i,?i)';
$datas = array(
	array('table1', 1, 2),
	array('table2', 3, 4),
	array('table3', 5, 6),
);
$fetches = 'id';

$db->multiQuery($patterns, $datas, $fetches);
			

В этом случае $fetch может содержать префикс last:, указывающий на то, что получить нужно только последний результат. То есть "id" вернёт массив с ID'шниками каждой строки, а "last:id" только последний ID.

Одним массивом


array goDB::multiQuery(array $queries);			
			

$queries = array();

$queries[] = array(
	'SELECT * FROM `users` WHERE `id`=?i',
	array(11),
	'rowassoc',
);

$queries[] = array(
	'INSERT INTO `table` VALUES (?i,?i)',
	array(1, 2),
	'id',
);

$queries[] = array(
	'SELECT `a` FROM `table` WHERE `b`=?i',
	array(5),
	'el',
);

$db->multiQuery($queries);
			

Будет выполнено:


SELECT * FROM `users` WHERE `id`=11; -- будет получена запись в виде ассоциативного массива
INSERT INTO `table` VALUES (1,2);    -- будет получен ID вставленной строки
SELECT `a` FROM `table` WHERE `b`=5; -- будет получено значение указанного поля
			

В массивах можно указать только шаблоны и данные, а форматы разбора отдельным аргументом.


$db->multiQuery($queries, null, 'last:id');			
			

Заметьте, что аргументы метода остаются на своих местах, например указание отключенния транзакции:


$db->multiQuery($queries, null, null, false);
			

Ошибки

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

В случае ошибок в шаблонах и данных, выпадают те же goDBExceptionData*. Формирование запросов происходит перед запуском мультизапроса, так что если даже ошибка в шаблоне будет только в последнем запросе, всё равно не выполниться ни один.

В случае ошибки в формате разбора (неизвестный формат или assoc для INSERT) выбрасывается исключение goDBExceptionFetch*, однако, все запросы на тот момент уже выполнены, но получить их результаты не удастся.

При несовпадении размеров массивов $patterns, $datas и $fetches выбрасывается goDBExceptionMulti.

© Григорьев Олег aka vasa_c, 2006—2010