So I have two arrays, $gDatabaseKeyNames (list of column names) and $gDatabaseKeyValues (a list of variable names containing values from a script). The variable names are generated dynamically so I keep track of them for an insert.
Rather than listing all of the columns and value variables, I tried this
$cols = implode(", ", array_values($gDatabaseKeyNames));
$vals = implode(", ", array_values($gDatabaseKeyValues));
$query = "INSERT INTO pings (survey_id, $cols) VALUES ('$surveyID', $vals)";
mysql_query ($query) or die(mysql_error());
But none of my actual values show up in the database (they are inserted as 0s - all my columns are numeric).
If I echo $query, I see this, which is the correct formatting:
INSERT INTO pings (survey_id, latitude, longitude, pingTimestamp) VALUES ('15', '$Dlatitude', '$Dlongitude', FROM_UNIXTIME('$DtimeStamp'))
However, if I change $query to
$query = INSERT INTO pings (survey_id, latitude, longitude, pingTimestamp) VALUES ('$surveyID', '$Dlatitude', '$Dlongitude', FROM_UNIXTIME('$DtimeStamp'));
It works perfectly!
Why isn't PHP interpreting the variables in the implode? How can I fix this?
I suspect that $cols has the literal value '$Dlatitude', '$Dlongitude', etc.... PHP does not "double-interpolate" strings. It'll replace $cols with its values, but will NOT replace $Dlatitude with that variable's value. In other words, you're literally inserting some strings-that-look-like-PHP-variable-names into your numeric fields.
What is in the $gDatabaseKeyValues/Names arrays?
It's probably caused because of string/number problems. You should consider changing the database engine (Consider PDO) and use prepared statements to bind the parameters to your query the right way.
Related
I have a search bar that passes data to the server. I am taking the sentence sent and breaking it into individual words.
I am then comparing a column against each word in the sentence.
$term = filter_var($input['term'], FILTER_SANITIZE_STRING);
$terms = explode(" ", $term);
$size = sizeof($terms);
$posts = DB::select('SELECT * FROM cars
WHERE color = ?',
$terms[0] || $terms[1] || $terms[2] || $terms[3] || $terms[4] );
What is the proper way to bind with multiple parameters on one bind?
This way would get messy, as I would want to search additional columns.
for ($i=0; $i < $size ; $i++) {
$posts = DB::select('SELECT * FROM cars
WHERE color = ? AND
WHERE model =?',
$terms[$i], $terms[$i],);
}
What is the proper way to bind with multiple parameters on one bind.
Think of this rule: You can use a parameter in an SQL query in place of one single scalar value.
That is, where you would normally use in your SQL statement one numeric constant, one quoted string constant, or one quoted date constant, you can replace that one query element with one parameter.
Parameters can not be used in place of:
Lists of multiple values
SQL expressions
SQL keywords
Identifiers like table names, column names, or database names
If you want to compare your color column to multiple values, you need multiple parameter placeholders.
$posts = DB::select('SELECT * FROM cars
WHERE color IN (?, ?, ?, ?)');
It doesn't work to pass a string containing a comma-separated list of values to a single placeholder. You end up with a query that works as if you had written it this way:
SELECT * FROM cars WHERE color IN ('12,34,56,78');
This query will run without error, but it won't give you want you want. In a numeric context, the string '12,34,56,78' has a numeric value of 12. It ignores all the rest of the characters in the string after the first non-numeric character ,. So it will succeed in searching for color 12, but it will fail to find the other colors.
PDO makes it easy to deal with lists of values, because when it is time to supply the values for a parameterized query, you can simply pass an array to the PDOStatement::execute() function.
If you don't know how many color values you need to search for, you can use PHP builtin functions to make a list of question mark placeholders that is the same length as your array of color values:
$list_of_question_marks = implode(',', array_fill(1, count($color_values), '?'));
$sql = "SELECT * FROM cars WHERE color IN ($list_of_question_marks)"
$stmt = $pdo->prepare($sql);
$stmt->execute($color_values);
You should use In to search between various items, and if it's a search, a OR operator would work better:
$posts = DB::select('SELECT * FROM cars
WHERE color in (?) or
model in (?)',
implode(',', $terms), implode(',', $terms));
I'm running a PDO query, something like:
$inputArr = array(val1, val2, val3, ...);
$qMarks = str_repeat('?,', count($inputArr) - 1) . '?';
$stmt = $db->prepare("SELECT id, name, type, level
FROM table
WHERE name IN ($qMarks)");
$stmt->execute($inputArr);
... parse the rows that have been returned
And this works exactly as expected, no hang-ups or anything.
My problem is that I need to know which value from $inputArr was used to get each row returned.
I've tried
WHERE name IN ($qMarks) AS inputVal
and
WHERE name IN ($qMarks AS inputVal)
but those crash the query.
How can I determine which input array value was used to return each row in the output?
EDIT 1
Yes, I understand that the input search value would be name, for this particular case, but the query above is only for demonstration purposes of how I am putting the search values into the query.
The actual is much more complex, and returns any name value with is close (but not always identical).
The AS keyword is not going to work as you expect it. It's mainly used for aliasing subqueries. You can't (to my knowledge) use it in a WHERE clause.
The scenario you've outlined should have the 'name' in $row['name']. If it was a different variable that you wanted to see, you'd simply add it in your SELECT clause.
Great question, and simple answer:
The WHERE name IN $qMarks)"); part of your code is only obtaining the values in your database that are matching your array, so what you can do is see which values of name are present in the row you fetched. For example:
$rows_fetched = $stmt->fetchAll(PDO::FETCHASSOC);
$inputArray = array();
foreach($rows_fetched as $value)
{
$inputArray[] = $value['name'];
}
print_r($inputArray);//printing the results
Now you have the array $inputArray with all the values used to return each row in the output. Let me know if that worked for you!
for some odd reason php statement work fine when i only have on item in the array but everytime i add a second one i get an error "Column count doesn't match value count at row 1" I clearly have the correct column count. please help
$form_array=implode(",",array("james","brown"));
$db_array=implode(",",array('firstname','lastname'));
$query="INSERT INTO application ($db_array)
Value('$array')";
$dbquery=mysql_query($query);
if(!$dbquery){
echo mysql_error();
}
Your values are not quoted correctly. (and you're using $array instead of $form_array).
Note $form_array after imploding = 'james,brown'.
Putting that (and $db_array) into your query string, you end up with:
$query = "INSERT INTO application (firstname, lastname) VALUE ('james,brown');
Notice "james" and "brown" are quoted together in a single string - hence column count not matching value count.
You really should use a query string escaping function on your inputs - e.g. mysql_real_escape_string:
Wrote this off the top of my head so might have a minor syntax error somewhere, but the below example should push you in the right direction:
$form_array = implode(',', array_map('mysql_real_escape_string', array('james', 'brown')));
$db_array = implode(',', array('firstname','lastname'));
$query = "INSERT INTO application ($db_array) VALUES ($form_array)";
Note you should also take some more precautions if your $db_array is provided by user input in some way.
I have an array stored in a variable $contactid. I need to run this query to insert a row for each contact_id in the array. What is the best way to do this? Here is the query I need to run...
$contactid=$_POST['contact_id'];
$eventid=$_POST['event_id'];
$groupid=$_POST['group_id'];
mysql_query($query);
$query="INSERT INTO attendance (event_id,contact_id,group_id) VALUES ('$eventid','$contactid','$groupid')";
Use a foreach loop.
$query = "INSERT INTO attendance (event_id,contact_id,group_id) VALUES ";
foreach($contactid as $value)
{
$query .= "('{$eventid}','{$value}','{$groupid}'),";
}
mysql_query(substr($query, 0, -1));
The idea here is to concatenate your query string and only make 1 query to the database, each value-set is separated by a comma
Since no one hasn't stated that yet, you actually cannot do this:
$query = '
INSERT INTO [Table] ([Column List])
VALUES ([Value List 1]);
INSERT INTO [Table] ([Column List])
VALUES ([Value List 2]);
';
mysql_query($query);
as this has been prevented to prevent sql injections in the mysql_query code. You cannot have semicolon within the given query param with mysql_query. With the following exception, taken from the manual comments:
The documentation claims that "multiple queries are not supported".
However, multiple queries seem to be supported. You just have to pass
flag 65536 as mysql_connect's 5 parameter (client_flags). This value
is defined in /usr/include/mysql/mysql_com.h:
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
Executed with multiple queries at once, the mysql_query function will
return a result only for the first query. The other queries will be
executed as well, but you won't have a result for them.
That is undocumented and unsupported behaviour, however, and easily opens your code to SQL injections. What you can do with mysql_query, instead, is
$query = '
INSERT INTO [Table] ([Column List])
VALUES ([Value List 1])
, ([Value List 2])
[...]
, ([Value List N])
';
mysql_query($query);
so you can actually insert multiple rows with a one query, and with one insert statement. In this answer there's a code example for it which doesn't concatenate to a string in a loop, which is better than what's suggested in this thread.
However, disregarding all the above, you're probably better of still to use a prepared statement, like
$stmt->prepare("INSERT INTO mytbl (fld1, fld2, fld3, fld4) VALUES(?, ?, ?, ?)");
foreach($myarray as $row)
{
$stmt->bind_param('idsb', $row['fld1'], $row['fld2'], $row['fld3'], $row['fld4']);
$stmt->execute();
}
$stmt->close();
Use something like the following. Please note that you shouldn't be using mysql_* functions anymore, and that your code is suseptible to injection.
for ($i = 0; $i < count($contactid); $i++) {
$query="INSERT INTO attendance (event_id,contact_id,group_id) VALUES ('$eventid','$contactid[$i]','$groupid')";
mysql_query($query);
}
I'm not sure running multiple queries is the best thing to do, so won't recommend making a for loop for example, that runs for each element of the array. I would rather say, make a recursive loop, that adds the new elements to a string, that then gets passed to the query. In case you can give us a short example of your DB structure and how you'd like it to look like (i.e. how the array should go into the table), I could give you an example loop syntax.
Cheers!
What about:
$contactIds = $_POST['contact_id'];
$eventIds = $_POST['event_id'];
$groupIds = $_POST['group_id'];
foreach($contactIds as $key => $value)
{
$currentContactId = $value;
$currentEventId = $eventIds[$key];
$currentGroupId = $groupIds[$key];
$query="INSERT INTO attendance (event_id,contact_id,group_id) VALUES ('$currentEventId','$currentContactId','$currentGroupId')";
mysql_query($query);
}
Well, you could refactor that to insert everything in a single query, but you got the idea.
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.