Это DataKinds
в действии, которое:
Это, однако, вызывает путаницу на уровне типа. Теперь в типах [X]
может быть либо [X] :: *
, либо тип списка X
, либо вместо этого мы могли бы иметь [X] :: [T]
из-за подъема - это значение [X]
(только список, содержащий только единственное значение X
) с X
типа T
, поднятое на уровне уровня.
Чтобы преодолеть эту двусмысленность, GHC требует цитаты перед конструкторами с поднятыми значениями. Итак, у нас есть [X] :: *
и '[X] :: [T]
.
Конкретно, в вашем случае Get '[JSON] [User]
включает как значение списка [JSON]
, поднятое до уровня типа, так и тип списка [User]
, Чтобы лучше понять разницу, обратите внимание, что терминов типа '[JSON]
нет, поскольку это не тип списка. Мы могли бы даже иметь Get '[JSON,JSON,JSON] [User]
как хорошо выраженное выражение или даже Get '[] [User]
. Вместо этого мы не можем иметь Get '[JSON] [User,User]
, так как [User,User]
не является типом.
(Тип Get '[JSON,JSON,JSON] [User]
, даже если он действителен, не может быть осмысленно использован библиотекой Servant. не знаю, для чего этот поднятый список используется в Слуге.)
Класс mysqli предоставляет несколько различных способов выполнения ваших вставок, каждый из которых имеет свои преимущества. Конечно, один из них должен соответствовать вашим потребностям.
В следующих примерах предполагается, что ваши неуказанные «извлеченные данные» хранятся в массиве массивов: $ bigArray [0 ... datasetsize] [0 ... 2].
Предполагается, что база данных mysqli равна $ db.
Метод 1 - Старая школа
Вы можете сделать это прямо, как вы привыкли просто создавая строку запроса и запрашивая с ней базу данных. Вкладыши в комплекте 10 штук, как вы указали. Следующий код показывает один такой пучок и тривиально распространяется на весь набор данных (bigArray). Вероятно, данные должны быть экранированы с помощью mysqli :: escape_string (здесь не делается).
Вставляемые данные считаются целыми во всех примерах.
$sql = "INSERT INTO testTable (fieldA, fieldB, fieldC) VALUES ";
for ($i = 0; $i < 10; ++$i)
{
if ($i > 0) $sql .= ", ";
$sql .= "({$bigArray[$i][0]}),({$bigArray[$i][1]}),({$bigArray[$i][2]})";
}
$db->query($sql);
Метод 2 - Как можно проще
Если вы хотите использовать подготовленный оператор и привязку параметров, первое усилие может выглядеть следующим образом. Хотя это и не является оптимальным, утверждение готовится только один раз. Однако переменные привязаны к каждой вставке, которая является расточительной (но простой). Поскольку вставки не объединены, пример зацикливается на 10.
$statement = $db->prepare("INSERT INTO testTable (fieldA, fieldB, fieldC) VALUES (?,?,?)");
for ($i = 0; $i < 10; ++$i)
{
$statement->bind_param("iii",$bigArray[$i][0],$bigArray[$i][1],$bigArray[$i][2]);
$statement->execute();
}
Метод 3 - Оптимизированный
Подготовленные операторы и множественные вставки объединяют производительность, которая почти идентична запросам сырой вставки метода 1. Фактические результаты будут зависеть от вашей установки, но быстрый тест в моей системе с локальной и удаленной базой данных показал производительность на несколько процентных пунктов быстрее с оптимизированным методом, увеличив на несколько пунктов больше, если данные в методе 1 должен быть экранирован.
В следующих случаях используется call_user_func_array, но вы могли бы избежать этого, если знаете, сколько вложений вы хотите связывать каждый раз и напрямую строить bind_param. Это будет еще больше увеличивать производительность.
Для ясности эти примеры включают внешний цикл и предполагают вставку 10k общих строк (т.е. bigArray [0..9999] [0..2]).
$sql = "INSERT INTO testTable (fieldA,fieldB,fieldC) VALUES (?,?,?)".str_repeat(",(?,?,?)",9);
$statement = $db->prepare($sql);
// This is the type string used by statement::bind_param.
// Example assumes all INTs.
$types = (array)str_repeat("i",30);
$values = array_fill(0,30,0); // A bit of unneeded variable init.
// * See notes following code snippet on why the intermediate array is used.
$intermediate = array();
for ($n = 0; $n < 30; ++$n)
{
$intermediate[$n] = &$values[$n];
}
call_user_func_array(array(&$statement, "bind_param"), array_merge($types,$f));
for ($j = 0; $j < 1000; ++$j)
{
for ($i = 0; $i < 10; ++$i)
{
$values[$i*3] = $bigArray[$i][0];
$values[$i*3+1] = $bigArray[$i][1];
$values[$i*3+2] = $bigArray[$i][2];
}
$statement->execute();
}
// call_user_func_array with bind_param requires the values be
// passed by reference which is evaluated only on the initial
// call. Using $values[...] = &$bigArray[...] below won't work
// and an intermediate array referencing $values is used. This
// bit of "extra funky stuff" can be avoided at a very slight
// performance penalty by setting $values[...] = $bigArray[...]
// AND EVALUATING EACH TIME (move call_user_func_array
// inside the outer loop, i.e. right above $statement->execute()).
Mysqli не является собственной базой данных, а просто набором функций для отправки запроса в старой mysql.
Итак, используя mysqli, вы можете запускать любой mysql-запрос.
Однако в случае динамически поставляемых значений вы не можете избежать «лишних фанки в PHP», поскольку вы должны использовать подготовленные заявления для этого. И, к сожалению, raw mysqli с ними не так просто.
Итак, чтобы выполнить такую вставку, вам нужно сначала создать запрос с заполнителями
INSERT INTO table (field1, field2 , field3) VALUES (?,?,?), (?,?,?), (?,?,?);
затем связывают все значения с помощью call_user_func_array()
и, наконец, execute
;