#php #mysql #multidimensional-array
#php #mysql #многомерный массив
Вопрос:
У меня есть массив из csv с аналогичной структурой:
$array = array(
array('name', 'age', 'gender'),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
Я хотел бы вставить его в таблицу MySQL, где элементы первого массива (имя, возраст, пол) являются заголовками столбцов, а каждый последующий массив представляет собой строку в таблице.
Может кто-нибудь посоветовать, как лучше всего это сделать?
Ответ №1:
Следующий код будет работать, но он предполагает, что длина всех вложенных массивов одинакова, другими словами, что каждый вложенный массив содержит значения для всех атрибутов, определенных в первом вложенном массиве.
$array = array(
array('name', 'age', 'gender' ),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
$fields = implode(', ', array_shift($array));
$values = array();
foreach ($array as $rowValues) {
foreach ($rowValues as $key => $rowValue) {
$rowValues[$key] = mysql_real_escape_string($rowValues[$key]);
}
$values[] = "(" . implode(', ', $rowValues) . ")";
}
$query = "INSERT INTO table_name ($fields) VALUES (" . implode (', ', $values) . ")";
Это решение будет работать с любым количеством атрибутов, определенных в первом вложенном массиве, при условии, что все остальные вложенные массивы имеют одинаковую длину. Для массива выше вывод будет:
INSERT INTO table_name (name, age, gender) VALUES (Ian, 24, male), (Janice, 21, female)
Для демонстрации см. http://codepad.org/7SG7lHaH , но обратите внимание, что я удалил вызов mysql_real_escape_string() на codepad.org , потому что они не допускают этой функции. Вы должны использовать его в своем собственном коде.
Комментарии:
1. как только вы используете implode для размещения их в базе данных, как вы можете разнести их в исходный массив, который у вас был раньше? В настоящее время я сталкиваюсь с той же проблемой
2. Неизвестный столбец ‘Ian’ в ‘списке полей’ вот ваш вывод. Код не работает
Ответ №2:
$fields = implode(',', array_shift($array)); // take the field names off the start of the array
$data = array()
foreach($array as $row) {
$name = mysql_real_escape_string($row[0]);
$age = (int) $row[1];
$gender = mysql_real_escape_string($row[2]);
$data[] = "('$name', $age, '$gender')";
}
$values = implode(',', $data);
$sql = "INSERT INTO yourtable ($fields) VALUES $values";
$result = mysql_query($sql) or die(mysql_error());
Это должно привести к появлению строки запроса типа:
INSERT INTO yourtable (name, age, gender) VALUES ('Ian', 24, 'male'), ('Janice', 21, 'female'), etc....
Комментарии:
1. одна из проблем может заключаться в том, что переменные $name $ age $ gender каждый раз будут разными, и их количество будет разным, поэтому смогу ли я получить имя переменной из первого массива? что-то вроде подсчета элементов в первом массиве, а затем его увеличения. Таким образом, переменная будет примерно такой — $data[0][$ x] ?
2. Пока ПЕРВАЯ строка в массиве содержит имена полей, а 2-я, 3-я и т. Д. Строки Имеют значения, Эта функция будет обрабатывать любое количество строк. до предела памяти PHP и любой точки, в которой строка запроса увеличивается, чтобы превысить ограничение mysql max_allowed_packet.
3. @MarcB Я думаю, что он говорит о другом количестве полей, а не о строке.
4. @Aurelio: а. понял. в этом случае нет, этот фрагмент кода содержит только 3 поля.
5. да, извините, возможно, я не совсем ясно выразился. Поскольку я не всегда буду знать количество и название полей. Поэтому я думаю, что код Аурелио сделает это. Спасибо
Ответ №3:
для этого массива вы могли бы сделать что-то столь же простое, как это:
$array = csv_array(); // this is your array from csv
$col_name = $array[0][0];
$col_age = $array[0][1];
$col_gender = $array[0][2];
for($i = 1; $i < count($array); $i ){
//this is where your sql goes
$sql = "INSERT INTO `table` ($col_name, $col_age, $col_gender)
VALUES($array[$i][0], $array[$i][1], $array[$i][2])";
$db->query($sql);
}
Вы должны очистить ввод, чего я не делал в моем примере. Если ваша структура массива не гарантируется одинаковой, вам придется сделать что-то еще.
Ответ №4:
Вы могли бы сделать это таким образом:
$rows = array(
array('name', 'age', 'gender'),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
$columns = array_shift($rows);
$rows = array_map(function($row) {
/*
* TODO: escape column values
*/
return '"' . implode('", "', $row) . '"';
}, $rows);
$sql = 'INSERT INTO ...
(' . implode(', ', $columns) . ')
VALUES (' . implode('), (', $rows) . ')';
Поскольку mysql (расширение) будет «приводить» ваши значения при вставке, вам не нужно обращать внимание на типы столбцов: если столбец определен как целое число, в базе данных он будет вставлен как целое число, даже если вы заключите значение в кавычки (например: возраст).
Обратите внимание на задачу, которую я отметил в источнике: очень небезопасно вставлять значения, не экранируя их (SQL-инъекция).
Ответ №5:
Предполагая, что значение в массиве является НАДЕЖНЫМ и БЕЗОПАСНЫМ.
$count = count($array);
$keys = $array[0];
for($i = 1; $i < $count; $i )
{
$query = "INSERT INTO tablename (" . implode(",", $keys) . ") VALUES ('" . implode ("','", $array[$i]) . "');";
$query = str_replace(',)', ')', $query);
mysql_query($query);
}
Комментарии:
1. цитирование имен полей превращает их в строки, и они больше не будут рассматриваться как имена полей. В остальном, по большей части, выглядит хорошо.
2. знаете ли вы, почему я могу получать предупреждение «недопустимые переданные аргументы» с этим кодом в implode ()?
3. @chentudou Ты уверен, что хорошо скопировал код? Я попробовал это перед публикацией и работает хорошо. Кроме того, как вы можете видеть, этот код будет работать также, если есть больше (или меньше), чем 3 поля.
4. я попробовал еще раз… предупреждение о взрыве исчезло, но в нем говорится об ошибке в синтаксисе SQL. Я буду продолжать пытаться, может быть, это моя ошибка.
5. @AurelioDeRosa: Вы поменяли местами параметры для implode. Отредактировано.
Ответ №6:
Мое решение в 2 приближениях.
-
Сохраните значения массива как сериализованные представления данных в простой таблице БД.
-
Сохраните значения массива в отдельных полях таблицы.
Рабочий пример:
$array = array(
0 => array ( "name", "age", "gender"),
1 => array ( "Ian", "24", "male"),
2 => array ( "Janice", "21", "female")
);
foreach($array as $key1 => $value1){
foreach($value1 as $key2 => $value2){
// assuming the first element (0) in the array is the header value and the header value is a valid array key
if($key1 > 0){
$items[$key1-1][ $array[0][$key2] ] = $value2;
}
}
}
// 1. store values as serialized representation
foreach ($items as $key => $value) {
$sql = "INSERT INTO datatable SET data = ".mysql_real_escape_string(serialize($value))."";
echo $sql.PHP_EOL;
}
// 2. auto create fields in database and store values
foreach ($array[0] as $key1) {
$sql = "ALTER TABLE forms ADD '".$key1."' TEXT NOT NULL";
echo $sql.PHP_EOL;
}
foreach ($items as $key1 => $value1) {
foreach($value1 as $key2 => $value2){
$sql = "INSERT INTO datatable SET ".$key2." = '".mysql_real_escape_string($value2)."'";
echo $sql.PHP_EOL;
}
}
Ответ №7:
Массив
$arrayData = array(
array(
'name' => 'Paul',
'age' => 28,
'gender' => 'male',
),
array(
'name' => 'Rob',
'age' => 23,
'gender' => 'male',
)
);
foreach($arrayData as $data){
$query = "INSERT INTO persons (name,gender,age)
VALUES ('$data[name]', '$data[gender]', $data[age])";
//echo $query;die;
mysql_query($query) or die(mysql_error());
//exit;
}
Ответ №8:
Лучший способ сделать это — использовать подготовленные операторы и транзакции с помощью библиотеки PDO. PDO — самый простой выбор для любого взаимодействия с БД в PHP.
Подготовленные инструкции быстры, просты и предлагают привязку параметров, которая защитит вас от SQL-инъекций в качестве побочного эффекта.
Транзакции БД гарантируют, что все данные вставлены или вообще не вставлены. Они также могут значительно повысить производительность такого рода задач.
Вот пример кода:
// create new connection to MySQL using PDO class
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=$charset", $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
]);
$array = array(
array('name', 'age', 'gender'),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
// discard the header row (1st row) from the array
array_shift($array);
// start transaction
$pdo->beginTransaction();
// prepre SQL statemenet with 3 placeholders
$stmt = $pdo->prepare('INSERT INTO csv_table(name, age, gender) VALUES(?,?,?)');
foreach ($array as $row) {
$stmt->execute($row);
}
// end transaction
$pdo->commit();
Как насчет строки заголовка?
Как вы можете видеть в приведенном выше коде, я отбрасываю строку заголовка. Поскольку таблицы SQL являются жесткими, мне нужно заранее знать, каковы имена столбцов. Если вы хотите динамически сопоставлять столбцы в CSV со столбцами в вашей схеме, вам нужно добавить некоторую логику, которая будет просматривать жестко запрограммированный список столбцов (вы также можете извлечь эту информацию information_schema
) и сопоставлять его с именами столбцов из вашего CSV.
Код можно настроить следующим образом. Выполните итерацию по именам столбцов из CSV и выдайте исключение, если какой-либо из столбцов не определен в вашем коде. Если все столбцы проверены, то implode()
имена столбцов и введите их в вашу строку SQL.
$array = array(
array('name', 'age', 'gender'),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
$table_columns = ['age', 'gender', 'name'];
// Validate CSV header row (1st row) against your schema columns
$header = array_shift($array);
foreach ($header as $col_name) {
if (!in_array($col_name, $table_columns, true)) {
throw new Exception('Incorrect column name specified in CSV file');
}
}
// start transaction
$pdo->beginTransaction();
// prepre SQL statemenet with 3 placeholders
$stmt = $pdo->prepare('INSERT INTO csv_table('.implode(',', $header).') VALUES(?,?,?)');
foreach ($array as $row) {
$stmt->execute($row);
}
// end transaction
$pdo->commit();
Ответ №9:
Наиболее прямым способом вставки мульти-массива в SQL может быть:
$queryIn = "INSERT INTO table (resultsArray) values (" . print_r($multiArray, true) . "')";
Это работает.