I have a 1 dimensional array of strings ($answers). I want to store each string as a new record a long with an itemId (the same itemId for each answer) into my table "answers_tb".
I have tried.....
using a foreach to construct a new array 2 dimensional array, with the $answers array and the itemID and then imploding this new array into my query.
not working.
i get this error:
Column count doesn't match value count at row 1
here is my code:
$records = array();
foreach($answers as $item_id => $text_value) {
$records[] = '("' . $item_id . '","' . $text_value . '")';
}
$sql = "INSERT INTO answers_tb (item_id, text_value) VALUES('" . implode(',', $records)." ')";
mysql_query($sql) or die(mysql_error());
many thanks for getting this far, even if you cant help.
regards,
Aside from particular problem, just to teach you a lesson.
You are working on your task in wrong way, upside down.
To put it straight, you're writing a program that builds some text.
So, first of all, it would be extremely handy to know, what particular text you want to get as a result. Thus, you have to write desired SQL query by hand and run in SQL console to see if it works okay or has any errors. If you experience any problem on this stage, you may ask under mysql tag, what query you need.
The rest is going to be easy. Upon finishing your program just print it's result out, and compare with example you've got before. Then correct your code to make them match. Repeat.
Done.
Always do your job this way and you will have no problem.
This should work:
$records = array ();
$itemid = 3; // or any arbitrary value
foreach ($answers as $text_value) {
$records[] = '("' . $itemid . '","' . $text_value . '")';
}
$sql = "INSERT INTO answers_tb (item_id, text_value) VALUES " . implode(',', $records);
mysql_query ($sql)
or die (mysql_error ());
With your current solution you create a query like:
INSERT INTO answers_tb (item_id, text_value) VALUES (('1', 'asd'),('2', 'bsd'))
It shoould look like:
INSERT INTO answers_tb (item_id, text_value) VALUES ('1', 'asd'),('2', 'bsd')
So you don't need the extra parens.
Related
I'm hoping someone can give me a suggestion on a challenge I am facing. I am not sure that I'm able to do this the way I envision, so looking for advice from those more experienced.
I have a database table with around 20 columns. It's a lot of columns and unfortunately I cannot change that. The goal is to take a form submission and insert it into this table. So what I have is, the field names are identical to the column names in the database.
To try and keep the code cleaner, I would like to just pull the entire form (key and value) in, instead of doing the traditional $varWhatever = $_POST['whatever']; 20 times. Using something like this: foreach ($_POST as $key => $value)
Now my question is, if at all possible, how can I run that foreach loop in a way that will let me put the keys and values into a single SQL statement?
"INSERT INTO table_name (Loop all keys here) VALUES (Loop related values here)"
Is this even possible, or should I just go back to the more traditional way I mentioned above?
One way I am thinking is, before starting the loop, I could create the empty row and grab it's ID, then within the loop, I could run an update query on the row matching the ID. Sounds sloppy though.
Here is a solution I came up with. You first have to define an array of field names that acts as a whitelist of expected inputs. Then you just loop through that array to build a parameters array to bind the submitted values. And implode the array with a comma when building the query.
$fields = array('field1','field2','field3');
$binds = array();
foreach ($fields as $field) {
$binds[":$field"] = $_POST[$field];
}
$sql = "INSERT INTO table_name (" . implode(',',$fields) . ") VALUES (" . implode(',',array_keys($binds)) . ")";
$db->prepare($sql);
$db->execute($binds);
This assumes you are using PDO.
Yes, you can loop for all keys (eg. do an array_keys), but I don't recommend blindly taking any submission parameter and putting it into a SQL query.
Instead, I would keep a list of all valid columns of the form and work with that, remembering that each value needs sanitization, too.
For example:
<?php
$columns = array('column1', 'column2', 'column3', …);
foreach ($columns as $column) {
if (!isset($_POST[$column])) {
die("No data for column $column\n");
}
}
if (!check_csrf($_POST['csrt_token'])) { … }
# (setup database connection)
$SQL = "INSERT INTO table_name (" . implode(", ", $columns) . ") VALUES (";
foreach ($column as $column) {
$SQL .= "'" . $mysqli->real_escape_string($_POST[$column]) . "',";
}
$SQL[strlen($SQL)-1] = ')';
$mysqli->query($SQL);
I'm trying to insert data's(multiple records) into table with php loop.
This the code :
<?php
$array = array('blue','red','green','yellow','black','white','blue','green');
$array = array_values(array_unique($array)); // remove duplicate and re-index array also
$vals = array_count_values($array);
print_r($array);
?>
And out put will look like :
Array ( [0] => blue [1] => red [2] => green [3] => yellow [4] => black [5] => white )
Now I want to insert the output into my table(colours) with this code :
<?php
for($i = 0; $i < count($vals); $i++){
$query = "INSERT INTO colours VALUES('$array[$i]');";
mysql_connect('localhost','root','');
mysql_query($query);
}
?>
What am I doing wrong?
There are several things you need to correct here. The first, is to address the fact that you're not specifying a database, like this:
$conn = mysql_connect('localhost','root','');
$db = mysql_select_db('YourDataBaseHere', $conn);
I assume if you've already created a table, then it must live in some database that you've already created.
Second, I think your query may need some correcting. You are not specifying any column names for your test table. Third, you shouldn't be running queries in a loop. Instead, you can try building a query that does multiple inserts with a single request, like this:
$sql = "INSERT INTO colours (`color`) VALUES ('" . implode("'),('", $array) . "')";
mysql_query($sql, $conn);
For the intents and purposes of your particular use case, you do not even need a looping structure because the entire array's values are imploded into a string to form the final query, as shown. This will insert multiple rows for all your colors. This strategy may not be advisable for ultra-large arrays. I advise that you separately look up how to do multiple inserts with a single query using MySQL/PHP. Then the $sql line might make more sense to you.
Fourth, your original, unedited question used a table called "test" so I'm going to assume you're not in a production environment. Regardless, I would advise putting a password for your root admin account instead of leaving it blank. It's just good practice.
Also, read this: Why shouldn't I use mysql_* functions in PHP?
You probably want to do something a bit like this, specifying the column name you are inserting into for the colors table.
$conn = mysql_connect('localhost', 'root', '');
if (!$conn) {
die('Could not connect: ' . mysql_error());
}
for($i = 0; $i<$vals; $i++) {
$sql="INSERT INTO colors (Column_Name) VALUES ('$array[$i]');";
$result = mysql_query($sql);
if (!$result) {
die('Invalid query: ' . mysql_error());
}
}
That should get you on the right track.
You can do it without using for loop.
you query will be.
$array = array('blue','red','green','yellow','black','white','blue','green');
$array = array_values(array_unique($array));
$query = "INSERT INTO test VALUES ('".implode("'),('",$array)."');";
Your code should be like
mysql_connect('localhost','root',''); //put this line at the start
mysql_select_db("your db name"); //and add this line after it
$array = array('blue','red','green','yellow','black','white','blue','green');
$array = array_values(array_unique($array)); // remove duplicate and re-index array also
$arr_str = implode("'),('",$array);
$sql_query = "INSERT INTO `test` (`colours`) VALUES ('".$arr_str."')";
mysql_query($sql_query);
I ran into the following question while writing a PHP script. I need to store the first two integers from an array of variable lenght into a database table, remove them and repeat this until the array is empty. I could do it with a while loop, but I read that you should avoid writing SQL statements inside a loop because of the performance hit.
A simpliefied example:
while(count($array) > 0){
if ($sql = $db_connect->prepare("INSERT INTO table (number1, number2) VALUES (?,?)")){
$sql->bind_param('ii',$array[0],$array[1]);
$sql->execute();
$sql->close();
}
array_shift($array);
array_shift($array);
}
Is this the best way, and if not, what's a better approach?
You can do something like this, which is way faster aswell:
Psuedo code:
$stack = array();
while(count($array) > 0){
array_push($stack, "(" . $array[0] . ", " . $array[1] . ")");
array_shift($array);
array_shift($array);
}
if ($sql = $db_connect->prepare("INSERT INTO table (number1, number2)
VALUES " . implode(',', $stack))){
$sql->execute();
$sql->close();
}
The only issue here is that it's not a "MySQL Safe" insert, you will need to fix that!
This will generate and Array that holds the values. Within 1 query it will insert all values at once, where you need less MySQL time.
Whether you run them one by one or in an array, an INSERT statement is not going to make a noticeable performance hit, from my experience.
The database connection is only opened once, so it is not a huge issue. I guess if you are doing some insane amount of queries, it could be.
I think as long as your loop condition is safe ( will break in time ) and you got something from it .. it's ok
You would be better off writing a bulk insert statement, less hits on mysql
$sql = "INSERT INTO table(number1, number2) VALUES";
$params = array();
foreach( $array as $item ) {
$sql .= "(?,?),\n";
$params[] = $item;
}
$sql = rtrim( $sql, ",\n" ) . ';';
$sql = $db_connect->prepare( $sql );
foreach( $params as $param ) {
$sql->bind_param( 'ii', $param[ 0 ], $param[ 1 ] );
}
$sql->execute();
$sql->close();
In ColdFusion you can put your loop inside the query instead of the other way around. I'm not a php programmer but my general belief is that most things that can be done in language a can also be done in language b. This code shows the concept. You should be able to figure out a php version.
<cfquery>
insert into mytable
(field1, field2)
select null, null
from SomeSmallTable
where 1=2
<cfloop from="1' to="#arrayLen(myArray)#" index="i">
select <cfqueryparam value="myArray[i][1]
, <cfqueryparam value="myArray[i][]
from SomeSmallTable
</cfloop>
</cfquery>
When I've looked at this approach myself, I've found it to be faster than query inside loop with oracle and sql server. I found it to be slower with redbrick.
There is a limitation with this approach. Sql server has a maximum number of parameters it will accept and a maximum query length. Other db engines might as well, I've just not discovered them yet.
I have a question on how to go about the next phase of a project I am working on.
Phase I:
create a php script that scraped directory for all .txt file..
Open/parse each line, explode into array...
Loop through array picking out pieces of data that were needed and INSERTING everything into the database (120+ .txt files & 100k records inserted)..
this leads me to my next step,
Phase II:
I need to take a 'list' of several 10's of thousand of numbers..
loop through each one, using that piece of data (number) as the search term to QUERY the database.. if a match is found I need to grab a piece of data in a different column of the same record/row..
General thoughts/steps I plan to take
scrape directory to find 'source' text file.
open/parse 'source file'.... line by line...
explode each line by its delimiting character.. and grab the 'target search number'
dump each number into a 'master list' array...
loop through my 'master list' array.. using each number in my search (SELECT) statement..
if a match is found, grab a piece of data in another column in the matching/returned row (record)...
output this data.. either to screen or .txt file (havent decided on that step yet,..most likely text file through each returned number on a new line)
Specifics:
I am not sure how to go about doing a 'multiple' search/select statement like this?
How can I do multiple SELECT statements each with a unique search term? and also collect the returned column data?
is the DB fast enough to return the matching value/data in a loop like this? Do I need to wait/pause/delay somehow for the return data before iterating through the loop again?
thanks!
current function I am using/trying:
this is where I am currently:
$harNumArray2 = implode(',', $harNumArray);
//$harNumArray2 = '"' . implode('","', $harNumArray) . '"';
$query = "SELECT guar_nu FROM placements WHERE har_id IN ($harNumArray2)";
echo $query;
$match = mysql_query($query);
//$match = mysql_query('"' . $query . '"');
$results = $match;
echo("<BR><BR>");
print_r($results);
I get these outputs respectively:
Array ( [0] => sample_source.txt )
Total FILES TO GRAB HAR ID's FROM: 1
TOAL HARS FOUND IN ALL FILES: 5
SELECT guar_nu FROM placements WHERE har_id IN ("108383442","106620416","109570835","109700427","100022236")
&
Array ( [0] => sample_source.txt )
Total FILES TO GRAB HAR ID's FROM: 1
TOAL HARS FOUND IN ALL FILES: 5
SELECT guar_nu FROM placements WHERE har_id IN (108383442,106620416,109570835,109700427,100022236)
Where do I stick this to actually execute it now?
thanks!
update:
this code seems to be working 'ok'.. but I dont understand on how to handle the retirned data correctly.. I seem to only be outputting (printing) the last variable/rows data..instead of the entire list..
$harNumArray2 = implode(',', $harNumArray);
//$harNumArray2 = '"' . implode('","', $harNumArray) . '"';
//$query = "'SELECT guar_num FROM placements WHERE har_id IN ($harNumArray2)'";
$result = mysql_query("SELECT har_id, guar_num FROM placements WHERE har_id IN (" . $harNumArray2 . ")")
//$result = mysql_query("SELECT har_id, guar_num FROM placements WHERE har_id IN (0108383442,0106620416)")
or die(mysql_error());
// store the record of the "example" table into $row
$row = mysql_fetch_array($result);
$numRows = mysql_num_rows($result);
/*
while($row = #mysql_fetch_assoc($result) ){
// do something
echo("something <BR>");
}
*/
// Print out the contents of the entry
echo("TOTAL ROWS RETURNED : " . $numRows . "<BR>");
echo "HAR ID: ".$row['har_id'];
echo " GUAR ID: ".$row['guar_num'];
How do I handle this returned data properly?
thanks!
I don't know if this answers your question but I think you're asking about sub-queries. They're pretty straightforward and just look something like this
SELECT * FROM tbl1 WHERE id = (SELECT num FROM tbl2 WHERE id = 1);
That will only work if there is one unique value to that second subquery. If it returns multiple rows it will return a parse error. If you have to select multiple rows research JOIN statements. This can get you started
http://www.w3schools.com/sql/sql_join.asp
I am not sure how to go about doing a 'multiple' search/select statement like this?
With regards to a multiple select, (and I'll assume that you're using MySQL) you can perform that simply with the "IN" keyword:
for example:
SELECT *
FROM YOUR_TABLE
WHERE COLUMN_NAME IN (LIST, OF, SEARCH, VALUES, SEPARATED, BY COMMAS)
EDIT: following your updated code in the question.
just a point before we go on... you should try to avoid the mysql_ functions in PHP for new code, as they are about to be deprecated. Think about using the generic PHP DB handler PDO or the newer mysqli_ functions. More help on choosing the "right" API for you is here.
How do I handle this returned data properly?
For handling more than one row of data (which you are), you should use a loop. Something like the following should do it (and my example will use the mysqli_ functions - which are probably a little more similar to the API you've been using):
$mysqli = mysqli_connect("localhost", "user", "pass");
mysqli_select_db($mysqli, "YOUR_DB");
// make a comma separated list of the $ids.
$ids = join(", ", $id_list);
// note: you need to pass the db connection to many of these methods with the mysqli_ API
$results = mysqli_query($mysqli, "SELECT har_id, guar_num FROM placements WHERE har_id IN ($ids)");
$num_rows = mysqli_num_rows($results);
while ($row = mysqli_fetch_assoc($results)) {
echo "HAR_ID: ". $row["har_id"]. "\tGUAR_NUM: " . $row["guar_num"] . "\n";
}
Please be aware that this is very basic (and untested!) code, just to show the bare minimum of the steps. :)
I have a form that allows users to input classes and activities into multiple fields, these fields are declared like this :
label for ="classact">Classes and Activities</label>
<input type = "text" name = "classact[0]" value ="" id ="classact[0]">
<input type = "text" name = "classact[1]" value ="" id ="classact[1]">
<input type = "text" name = "classact[2]" value ="" id ="classact[2]">
When the form is passed this is the code that handles in the insert:
$maininsert = "INSERT INTO `camptest`
(`name`, `city`, `phone`, `photo`)
VALUES
('$_POST[name]', '$_POST[city]', '$_POST[phone]', '$photoinfo')
SET #lid = LAST_INSERT_ID()
";
$classactinsert = "INSERT INTO `class_act`
(`cid`";
for($i = 0; $i < 3; $i++)
{
if(isset($_POST['classact'][$i]))
{
$temp = $i+1;
$classactinsert = $classactinsert . ",`act$temp`";
}
}
$classactinsert = $classactinsert . ")
VALUES
('#lid'";
for($i = 0; $i < 3; $i++)
{
if(isset($_POST['classact'][$i]))
{
$classactinsert = $classactinsert . ",'$_POST[classact][$i]";
}
}
$classactinsert = $classactinsert . ")";
$indata = $maininsert . $classactinsert;
$result = mysql_query($indata);
I realize thats alot of code, but upon filling out the form and submitting this is the query that gets generated:
INSERT INTO `camptest` (`name`, `city`, `phone`, `photo`) VALUES ('Multiple Activities', 'Nowhere', '555-555-1111', 'images/51127f6b06d1e.jpg') SET #lid = LAST_INSERT_ID() INSERT INTO `class_act` (`cid`,`act1`,`act2`,`act3`) VALUES ('#lid','Array[0],'Array[1],'Array[2])
The query is not inserting, but its not throwing back any errors either, even though I have them turned on.
My main question is, what am I doing wrong that is causing the values to act1, act2, and act3 to show up as Array[0], Array[1], and Array[2]?
My secondary question is, am I even going about this the right way? I'm a little new to php and I'm afraid I might be doing this the hard way?
Any help would be appreciated, let me know if you need any additional information.
It does not insert anything, because (among other things) your query string is not being built correctly.
('#lid','Array[0],'Array[1],'Array[2])
The apostrophes are messed up. I'd like to suggest a (in my opinion) cleaner and more structured way to perform your task:
Note: You are obviously working with the mysql_*-stack, so my example is also based on it. But be aware that this is deprecated. Please use mysqli or even better: PDO instead.
<?php
$maininsert = "INSERT INTO `camptest`
(`name`, `city`, `phone`, `photo`)
VALUES
('{$_POST['name']}', '{$_POST['city']}', '{$_POST['phone']}', '$photoinfo')";
//perform the main insert and fetch the insert id
mysql_query($maininsert);
$last_id = mysql_insert_id();
// Put the keys and values of the acts in arrays. We can already
// populate them with the one key-value-pair we already know
$act_keys = array('cid');
$act_values = array($last_id);
foreach($_POST['classact'] as $key => $value) {
//walk through the POSTed acts and add them to the corresponding array
$act_keys[] = 'act'.($key+1);
$act_values[] = $value;
}
//Now build the whole string:
$insert_acts = "INSERT INTO `class_act`
(`" . implode("`, `", $act_keys) . "`)
VALUES
('" . implode("', '", $act_values) . "')";
//and finally perform the query:
mysql_query($insert_acts);
Please also note that this code is highly vulnerable concerning SQL-Injection and should absolutely not be used in production!!! Make sure to either use prepared statements (like with PDO) or/and to sanitize your input properly.
Also, this solution is just my suggestion and one of many ways to do it. But hey, you asked for an opinion :) PHP is very flexible language, so it's easy to get stuff done, but there are many ways to get it done, so there are always chances to pick a hard an ugly one. Other, especially strong typed languages might prevent that by design. But PHP is really easy to learn and I'm sure your code will improve gradually :)
Another thing I've noticed: You don't need to specify the array-keys in your HTML, you just need to make clear that it's an array with [] behind the name. Also, I'm not sure if the id-attributes you using are valid, but you might want use something more simple:
<input type="text" name="classact[]" value="" id="classact1">
<input type="text" name="classact[]" value="" id="classact2">
<input type="text" name="classact[]" value="" id="classact3">
In the next step, you might want to refactor your code a little to make it even more structured and readable. Since you are performing one task, which is 'inserting something into a table', twice, we could also make a resusable function out of it:
<?php
function my_insert($table, $data) {
// We leverage the flexibility of associative arrays
$keys = "`" . implode("`, `", array_keys($data)) . "`";
$values = "'" . implode("', '", $data) . "'";
mysql_query("INSERT INTO `{$table}` ({$keys}) VALUES ({$values})");
return mysql_insert_id(); //This might come in handy...
}
//in order to use this function, we now put our data into associative arrays:
$class_insert = array(
'name' => $_POST['name'],
'city' => $_POST['city'],
'phone' => $_POST['phone'],
'photo' => $photoinfo
);
$class_insert_id = my_insert('camptest', $class_insert); //and pass it to the function
// You can either build the array while looping through the POSTed values like above,
// or you can pass them in directly, if you know that there will always be 3 values:
$activities_insert = array(
'cid' => $class_insert_id,
'act1' => $_POST['classact'][0],
'act2' => $_POST['classact'][1],
'act3' => $_POST['classact'][2]
);
$activities_insert_id = my_insert('class_act', $activities_insert);
There sure is enough room for improvement and optimization - just wanted to show you how awesome PHP can be :-P