I have a multi-dimensional array which contains ten thousands of data. A lot... The array is structured like this:
Array (
[0] => Array ( [0] => city [1] => code [2] => country )
[1] => Array ( [0] => city [1] => code [2] => country )
)
What I am trying to do is to insert the array values city, code and country into a table in a mysql database. I found posts that match exactly what I want to do, but for some reason it is not working with me. When I say it is not working I mean that the php doesn't even start. If I remove the here below code, the file runs normaly. So the problem really comes from that code portion. Hope someone will not mind helping me. Thank you in advance. Cheers. Marc.
//some code to build the array
//db_connect code
$sql = array();
foreach( $myarray as $row )
{
$sql[] = '("'.$row[0].'", "'.$row[1]).'","'.$row[2].'")';
}
mysql_query('INSERT INTO test (t_city, t_code, t_country) VALUES '.implode(',', $sql));
As said before, the error in building the sql array, is a surplus bracket. Change
$sql[] = '("'.$row[0].'", "'.$row[1]).'","'.$row[2].'")';
to
$sql[] = '("'.$row[0].'", "'.$row[1].'","'.$row[2].'")';
As ashein noted in comments, the query length is limited by the "max_allowed_paket" variable. If the query is larger than this, an error is raised and connection gets closed.
There is a bracket after $row[1] :)
Use this (remove the bracket):
$sql[] = '("'.$row[0].'", "'.$row[1].'","'.$row[2].'")';
You can try inserting every array record as separate sql-query.
foreach( $myarray as $row )
{
mysql_query('INSERT INTO test (t_city, t_code, t_country) VALUES ("'.$row[0].'", "'.$row[1]).'","'.$row[2].'");
}
but there would be a lot of queries
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
You want to dynamically build such a query by submitting multiple of the value pairs at once and not running into limits.
So what you do is to build the insert query while adding iteratively one row after the other. If adding a row would trigger the limit, the query is send and the query is reset:
# sample data
$data = array(
array('city1', 'code', 'country'),
array('city2', 'code', 'country'),
array('city3', 'code', 'country'),
array('city4', 'code', 'country'),
array('city5', 'code', 'country'),
array('city6', 'code', 'country'),
array('city7', 'code', 'country'),
);
$max_allowed_packet = 1048576; # mysql default value
$max_allowed_packet = 128; # for demonstration purposes
$sql = new SQLInsertQuery('INSERT INTO test (t_city, t_code, t_country) VALUES ', $max_allowed_packet);
foreach($data as $row) {
$sql->addRow($row);
}
$sql->query(); # manually query any potential left-over query.
This example outputs the following:
Running: INSERT INTO test (t_city, t_code, t_country) VALUES ('city1','code','country'),('city2','code','country');
Running: INSERT INTO test (t_city, t_code, t_country) VALUES ('city3','code','country'),('city4','code','country');
Running: INSERT INTO test (t_city, t_code, t_country) VALUES ('city5','code','country'),('city6','code','country');
Running: INSERT INTO test (t_city, t_code, t_country) VALUES ('city7','code','country');
Demo, Gist
You might want to add a counter for the queries run as well so you can validate after the loop and the final query if at all a query was sent (the limit can be too low so that no query is send at all - depending on your data - so it's worth to have a sanity check for this edge-case).
I hope this example is helpful.
Related
This question already has answers here:
Best way to INSERT many values in mysqli?
(4 answers)
Closed 4 years ago.
i have Multi array data like "cars name & cars modal"
Car name match with car model. both are different column in database (cars_name,cars_model). I want to store data from this array into database in their fields
Output:
Array
(
[car_name] => Array
(
[0] => Honda
[1] => Ford Mustang
[2] => Volvo
)
[car_modal] => Array
(
[0] => 2015
[1] => 2016
[2] => 2014
)
)
i want to store array values into single column in each row using "mysql". For this purpose i like query like this but it shows error.
$sql = "INSERT INTO cars_data (cars_name,cars_modal)
VALUES ($cars_name,$cars_modal)";
nothing happened. But errors show like this...
Notice: Array to string conversion in
E:\xampp\htdocs\car_records\modal_data.php on line 45 Error: INSERT INTO cars_data (cars_name,cars_model)
VALUES (Array,Array)Unknown column 'Array' in 'field list'
The question is how to fix it. Please help me
To use one statement and mysqli prepared statements (comments in code)...
$cars_name = ["Honda", "Volvo"];
// Create an entry for each name
$params = str_repeat("(?),", count($cars_name));
// Build a bind for a list of strings
$binds = str_repeat("s", count($cars_name));
// Add the params to the insert (remove the last ,)
$sql = "INSERT INTO car_data (cars_name)
VALUES ".rtrim($params, ",");
$insert = $conn->prepare ( $sql );
// Bind the parameters, using ... is the argument unpacking operator
$insert->bind_param($binds, ...$cars_name);
// Execute the SQL
$insert->execute();
Update:
If you had two data items in the array, you would be able to adapt the above to something like...
// Source data - ensure that the two sets of data have the same number of entries
$car_data = [ 'cars_name' => ["Honda", "Volvo"],
'cars_modal' => [ '2015', '2016' ]];
$car_count = count($car_data['cars_name']);
// Create an entry for each name (2 binds per entry)
$params = str_repeat("(?,?),", $car_count);
// Build a bind for a list of strings
$binds = str_repeat("ss", $car_count);
// Reformat data for binding (needs to be a single list of the data
// with cars_name followed by cars_modal for each entry)
$merged_data = [];
foreach ( $car_data['cars_name'] as $key => $name ) {
$merged_data[] = $name;
$merged_data[] = $car_data['cars_modal'][$key];
}
// Add the params to the insert (remove the last ,)
$sql = "INSERT INTO car_data (cars_name,car_model)
VALUES ".rtrim($params, ",");
$insert = $conn->prepare ( $sql );
// Bind the parameters, using ... is the argument unpacking operator
$insert->bind_param($binds, ...$merged_data);
// Execute the SQL
$insert->execute();
you can insert multiple elements in one row, you just need to bring it in the right format :
insert into x (columns) VALUES (x1),(x2),(x3)
$string = "";
foreach($cars_name as $car){
$string .= "(" . $car . "), ";
}
$sql = "INSERT INTO car_data (cars_name) VALUES $string";
Pleas note that you should never accept user input without sanitizing it.
When I want to do so, I first implode this array to get a normal string separated by (,) then when I retrieve data I implode them again.
$cars_name = implode(',', $_POST['cars_name']);
The result will be
Honda,Volvo,Mercedes,Toyota,BMW
Then if you want to get back the array from database again just do as following:
$cars_array = explode(',', $databaseObject['cars']);
The result will be the same as the first array of yours.
I have a MySQL database with a backend: PHP.
In one table I have to insert 60,000 rows.
We made a query into my PHP that returns 1,000 rows. For each rows we have to insert 60 rows. We thought make a loop but we don't know if is the best practices that way.
The part of the code that insert the data is:
$turnos = $db->query("SELECT * FROM turno t
WHERE t.canchaId = :cancha
AND t.fecha BETWEEN :fechaInicio AND :fechaFin
AND t.nombre LIKE :cadena
ORDER BY t.fecha,t.hora ASC",
array("cancha" => $cancha["idCancha"], "fechaInicio" => $fechaInicio, "fechaFin" => $fechaFin, "cadena" => "%turno fijo%"));
foreach($turnos as $turno) {
//turnos have 1000 rows
$fecha = date_create($turno["fecha"]);
date_add($fecha, date_interval_create_from_date_string('7 days'));
$anioAuxiliar = 2017;
while(2017 == $anioAuxiliar){
//60 times
$data1 = turno[data1];
$data2 = turno[data2];
...
$fechaAGuardar = (String) $fecha->format('Y-m-d');
$result = $db->query("INSERT INTO turno(fechaAGuardar, data2, data3, data4, data5, data6, data7, data8) VALUES(:fechaAGuardar, :data2, :data3, :data4, :data5, :data6, :data7, :data8)",
array("fechaAGuardar" => $fechaAGuardar, "data2" => $data2, "data3" => $data3, "data4" => $data4, "data5" => $data5, "data6" => $data6, "data7" => $data7, "data8" => $data8));
date_add($fecha, date_interval_create_from_date_string('7 days'));
$anioAuxiliar = (int) $fecha->format("Y");
}
$cantidad_turnos = $cantidad_turnos + 1;
}
This php is into a hosting with phpmyadmin.
So my questions are:
This is the best way to insert 60,000 rows?
Shall we considerer take into account another constraint? (eg: phpmyadmin don't allow you insert that amount of rows)
Thanks for helping me, Any suggestions are welcome
//EDIT//
The inserts data change, we have to insert datetime, and for each loop we have to add 7 day the last date inserted. So we can't use insert with select
As a bunch of fellows described in the comments, INSERT/SELECT is the way to go if this data is in the same server/database. There's no need to use PHP at all. Your year comment can be handled with DATE_ADD.
Anyway, if there is any other requirement and you can't use PHP, consider using Bulk Data Loading.
Analysing your code, the MOST IMPORTANT TIP would be: don't use multiple INSERT INTO TABLE expressions. Each INSERT INTO will cause a round trip do the database and things will get really slow. Instead of it, concat multiple values with one INSERT INTO (example from the link):
INSERT INTO yourtable VALUES (1,2), (5,5), ...;
Good luck!
I am using DHTMLX javascript library to present a grid in a form. My users could have hundreds of products in their grid but I am only capturing the the rows they add a price to. I then need to add those rows to a MySQL database along with some other information.
Getting standard $POST information and manipulating it in my PHP scripts is about the limit of my skills so far so where I need help is the array created by the updated rows. An example of what is being captured in my $POST is:
Array
(
[product] => 64
[dept] => 000
[submit] => Submit
[gridbox_1_4] => 422
[gridbox_64_4] => 534
[gridbox_175_4] => 1234
[gridbox_180_4] => 645
)
I currently capture the basic $POST variables with:
$itemcat = filter($_POST['product']);
$dept7 = filter($_POST['dept']);
My question is how do I capture the gridbox variables so I can use them in an INSERT statement? The only number that will change is the middle number which represents a primary key in my database for the products I need to INSERT into another table. I am assuming I need to explode the $POST variable somehow maybe? Then how do I INSERT them using something like:
"INSERT INTO submissions
(product_id, user_id,submission_id, sugg_price)
VALUES ('" . $gridbox_id . "','" . $myid . "','NULL', '" . $sugg . "')";
All of my reading today on arrays has given me a good understanding of how they work from a 100ft view but not how to specifically solve my problem or even how to start. I'm hoping the community can send me down the right path.
You can loop over the $_POST array and perform a regular expression match on each key:
// PDO will make your life so much easier
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);
// prepared statements are great - prepare once, use many
$stmt = $dbh->prepare('
INSERT INTO submissions
( product_id, user_id, submission_id, sugg_price)
VALUES
(:product_id, :user_id, NULL , :sugg_price)
');
// avoid SQL injection by passing your variables in as parameters
// see http://bobby-tables.com to understand why
$stmt->bindValue('user_id', $myid);
foreach ($_POST as $key => $val) {
if (preg_match("/^gridbox_(\d+)_4$/", $key, $matches)) {
$stmt->execute(array(
':product_id' => $matches[1],
':sugg_price' => $val
));
}
}
I am trying to insert an unknown number of rows into MySQL using PHP. This is how it should work:
Javascript parses HTML DOM to create a multi-dimensional array based on a css class. The array will have a certain number of rows(or sub-arrays) corresponding to the number of elements that have that class. (This could be any integer 0 or greater... obviously).
Then, on a JavaScript event, the array is sent to a PHP script.
The PHP script will INSERT data from the array into MySQL.
My problem is that I don't know how to tell my PHP script how many values are in the array. And I don't know how to write the mysql_query() without knowing the number of values (or rows) that should be inserted.
You can insert more than one row at a time to MySQL:
INSERT INTO table1 (column1, column2, ...) VALUES (value_col1, value_col2), (value2_col1, value2_col2), ...;
In PHP, you can build your query by looping through rows and adding them to the SQL string:
$sql = "INSERT INTO table1 (col1, col2) VALUES ";
foreach($rows as $i=>$row) {
if ($i>0) {
$sql .= sprintf(",(%s,%s)", $row["col1_value"], $row["col2_value"]);
} else {
$sql .= sprintf("(%s,%s)", $row["col1_value"], $row["col2_value"]);
}
}
mysql_query($sql);
You have to be sure to properly escape your values depending upon what you're actually inserting.
Why don't you prepare a two dimensional array while searching with the css class identifier like this?
//This is jquery code - you can write javascript to do the same
$(`.class`).each(function(i,e){resultsArray.push($(this).val());});
This will save you from the headache of traversing a multidimensional array in the backend and you can simply do a count() in you PHP code and the following query preparation.
Query preparation
Assuming you have a two dimensional array you can use a bulk insert query like this:-
INSERT INTO tablename (a,b)
VALUES
('1', 'one'),
('2', 'two'),
('3', 'three')
And prepare the query dynamically using PHP like this -
$counter = 0;
$valuesPart = NULL;
foreach($_POST as $each)
{
if($counter > 0)
$appendComma = ",";
else
$appendComma ="";
$valuesPart .= $appendComma."(".$each['key1'].",".$each['key2'].")";
$counter++;
}
if(!empty($valuesPart))
$mysql_query = "INSERT INTO tablename (a,b) VALUES ".$valuesPart;
So, you don't need to know how many results are to be actually inserted.
If you stay with the multidimensional array, you will probably need to code or search for a code to traverse the multidimensional array which will probably involve recursion and a lot of complex code. There will be many chances of errors and it will be a slower (may be little but a finite amount which is not necessary).
So I assume the array is getting to PHP successfully, through $_POST or whatever? If you aren't sure then do a var_dump or echo_r so we can see.
EDIT - wow I put explode where I meant implode several times. fixed.
Assuming that it is, and that each 'sub' array is an associative array in form
[0]
'id' => 1
'name' => 'Billy'
'DOB' => .....
[1]
etc.
And the code to build a single query inserting all rows, like this INSERT INTO table ('f1','f2',f3') VALUES ('v11', 'v22', 'v33'), ('v21', 'v22', 'v23'), ......
$escapeAndQuote = function($x) {return "'".mysql_real_escape_string($x)."'";};
$rowwise = function($x) {return '('. implode(', ', array_map($escapeAndQuote, $x)) .')';
$fieldString = $rowwise(array_keys($arr[0]));
$valString = implode(', ', array_map($rowwise, $arr));
$sql = "INSERT INTO table $fieldString VALUES $valString";
mysql_query($sql, $conn);
Use a foreach loop to cycle through the array.
// Example:
foreach($submitted_array as $insert_array)
{
//php and mysql insert query here
}
Perhaps prepared statements would assist you in your endeavors. Essentially you will declare a generic insert statement and then "bind" values to each input. Read more on PHP PDO Prepared Statements.
I have an array with 30000 plus entries that need to go into a MySQL table.
What is the best practice? From here? Lets say [0], [1] and [2] in the database would be 'title', 'type' and 'customer'
Is it add key names matching the column names in the table and call som "magic" function? Or build the query manually...
Array
(
[0] => Array
(
[0] => 2140395946
[1] => 1SAP
[2] => 0041451463
)
[1] => Array
(
[0] => 2140411607
[1] => 2SAP
[2] => 0041411940
)
[2] => Array
(
[0] => 2140706194
[1] => 4SAP
[2] => 0041411943
)
etc. etc.
UPDATE - based on answers
Thanks for the answers.
The solution would normally be to manually create the SQL-string and all rows can be inserted as one:
INSERT INTO `tx_opengate_table` (`machine` ,`customer` ,`type`)
VALUES
('m123', 'dfkj45', 'A'),
('m137', 'kfkj49', 'A'), "repeat this line for each entry in the array"
... ... ...
('m654321', '34dgf456', 'C4') "end with out comma, or remove last comma"
;
Special for TYPO3
I happen to do this in the CMS TYPO3 and just came across a new function added not that long ago:
//Insert new rows
$table = 'tx_opengate_stuff';
$fields = array('machine','type','customer');
$lines = "array as given above"
$GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows($table,$fields,$lines);
I would say just build it yourself. You can set it up like this:
$query = "INSERT INTO x (a,b,c) VALUES ";
foreach ($arr as $item) {
$query .= "('".$item[0]."','".$item[1]."','".$item[2]."'),";
}
$query = rtrim($query,",");//remove the extra comma
//execute query
Don't forget to escape quotes if it's necessary.
Also, be careful that there's not too much data being sent at once. You may have to execute it in chunks instead of all at once.
Magic function? I'm guessing you mean some sort of DB abstraction layer? IMHO that would just double your work.
Just build the query manually looping through array[] INSERT'ing values as you go.
$statement = "INSERT INTO table (title, type, customer) VALUES ";
foreach( $data as $row) {
$statement .= ' ("' . implode($row, '","') . '")';
}
UPDATE: Changed explode to implode (I always get those confused).
You will have to build the query manually if you want the best performance during this operation. If you would iteratively add everything using PDO or some abstarction layer, you will have 30000+ insert queries.
Use foreach to iterate over the arraay, build one nested INSERT query that does all the work at once, and just send it to the server.