I have built one PHP page which sends virtually identical information to two different tables (one is accessible by all users of the site, the other is a user's individual table).
$post = "INSERT INTO `Alpha` (`number`, `field1`, `field2`,
`field3`, `field4`, `field5`, `field6`, `field7`, `field8`, `field9`,
`field10`) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, '0', '0')";
$dbh = new PDO( "mysql:dbname=essay;host=localhost", "root", "password" );
$selectStatement = $dbh->prepare( $post );
$selectStatement->bindValue(1, $name, PDO::PARAM_STR);
$selectStatement->bindValue(2, $id, PDO::PARAM_INT);
$selectStatement->bindValue(3, $head, PDO::PARAM_STR);
$selectStatement->bindValue(4, $text, PDO::PARAM_STR);
$selectStatement->bindValue(5, $topic1, PDO::PARAM_STR);
$selectStatement->bindValue(6, $topic2, PDO::PARAM_STR);
$selectStatement->bindValue(7, $topic3, PDO::PARAM_STR);
$selectStatement->bindValue(8, $date, PDO::PARAM_INT);
$selectStatement->execute();
This is the code for the first table, and it works. The code for the second table is literally copied and pasted from this - the only difference being that the table name is changed (since it is unique to the user it is also now in the prepared statement) and one of the field names is changed (and I've created a new PDO object), but for some reason it won't work.
I put together a string which represents what the SQL query ought to look like, having it echo out each time I make a query, and when I input it manually I'm getting error #1054.
The strange thing is that the error goes away if I alter the query such that all of my string values are wrapped in single quotes. This, of course, is quite confusing because the first query didn't demand single quotes - why then would the second, since they are almost identical? Do I have some kind of weird setting on my SQL table of which I am unaware? If I could make the database accept the query without single quotes that would be ideal.
Regardless, when I append single quotes to both ends of the variables in my prepared statement, the prepared statement seems to be stripping them out, so I'm not sure how to get the single quotes on, but if I could I suppose that solution would suffice.
Table (and column) names can't be provided as parameters in prepared statements, which your description leads me to believe you've done.
See this old SO question
Have you tried PDO::quote? Looks like it handles escaping strings and might help solve those issues that you're facing.
Related
I am using mysqli prepared statement to insert values into the database. I know that this extension handles characters escaping properly.
I have a file path : images/serveover/Bellini 83.png, what I am expecting to see after insert is the file path with escaped characters in the database, something like images\/serveover\/Bellini 83.png but I only see the image path as is.
How can I make sure that my string has been properly escaped? Is this view standard in phpMyAdmin where It does not show escaped characters or is it just hiding them on view?
Below is my insert prepared statement with params where all the values are being filled properly :
$insertQuery = $conn -> prepare("INSERT INTO images (image_id, image_date_created, image_date_modified, image_title, image_src, category_id, image_status, image_external_file, another_id) VALUES (null, NOW(), CURRENT_TIMESTAMP, ?, ?, ?,'A', ?, ?)");
if($insertQuery )
{
$insertQuery -> bind_param("ssisi", $title, $image, $row["category_id"], $file, $row["id"]);
$insertQuery -> execute();
$insertQuery -> close();
}
As long as you're dealing with strings, the escaping process simply instructs MySQL to ignore the special properties of a character and treat it like a normal character.
Bob\'s special string
Is entered into the database as
Bob's special string
It's important to note that prepared statements don't use escaping at all. Prepared statements send the query in one set and the data in another, so MySQL doesn't need to escape it, since it knows that's the actual value to store.
You can read more about the process in the MySQL manual
https://dev.mysql.com/doc/refman/5.0/en/string-literals.html
I'm getting the error: Column count doesn't match value count at row 1
I think, normally this error occurs if the count of the columns and the values aren't equal, but in my code they are...(3).
This is my php code:
$tempsongtitel = $_POST['songtitle'];
$tempinterpret = $_POST['interpret'];
$templink = $_POST['link'];
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel, $tempinterpret, $templink')") or die(mysql_error());
You missed some quotes. Should be:
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
Otherwise, you were trying to insert all three POST values into the first field.
Moreover, the mysql_ extension has been deprecated and is on the way out and is highly discouraged, especially if you are creating new software.
AND I'll presume you are first sanitizing your data? You're not really taking user input and placing it directly into the database, are you? Even if you don't do any data validation, you should escape your data in the query... easiest and most foolproof way to do that is by using parameterized queries.
The root cause is that your values are all in one set of quotes instead of quoted individually. I think this is a pretty common error, and in my experience it is an easy mistake to make, but not immediately obvious when scanning over your code. You can fix it like this (quick fix, still using deprecated mysql, but with post values escaped):
$tempsongtitel = mysql_escape_string($_POST['songtitle']);
$tempinterpret = mysql_escape_string($_POST['interpret']);
$templink = mysql_escape_string($_POST['link']);
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link)
values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
If you can, it would be much better to update your code to use PDO. You could use a prepared statement like this:
$stmt = $pdo->prepare("INSERT INTO tMusic (Songtitel, Interpret, Link) VALUES (?, ?, ?)");
$stmt->bindValue(1, $tempsongtitel);
$stmt->bindValue(2, $tempinterpret);
$stmt->bindValue(3, $templink);
$stmt->execute();
Among the many benefits of using this database extension rather than the old mysql functions it should not be possible to make an error like this in your code. In the prepared statement, there are no quotes around the parameter markers, so if you have VALUES ('?, ?, ?'), or even VALUES ('?', '?', '?') You would get bind errors when trying to bind the values, and the problem would become apparent pretty quickly.
I've found that, even though it's not 100% necessary and it's more time consuming, properly quoting and backticking EVERYTHING helps prevent this from happening.
$myQuery = "INSERT INTO `tMusic` (
`Songtitel`,
`Interpret`,
`Link`
) VALUES (
'$tempsongtitel',
'$tempinterpret',
'$templink'
);";
$runQuery = mysqi_query($DBi, $myQuery) or die(mysqli_error($DBi));
The formatting you use is up to you but this helps me make sure I have a one to one relationship and that I've quoted everything.
Of course that's using mysqli_* in place of the deprecated mysql_* functions AND that's assuming you've set $tempsongtitel, $tempinterpret and $templink properly.
I am trying to avoid SQL injection in my page.
// Connect to database server and select database
$connection = new PDO("mysql:dbname=tt8888;host=mysql.tt8888.com", "tt8888", "ttnopassword");
// Quote data to prevent SQL injection
$name = $connection->quote($name);
// Insert now
$connection->query("INSERT INTO Contact (name, eeeee, llll, mmmmm, iiiii) VALUES ('$name','$eeeee','$llll','$mmmmm','$iiiii');");
Without quote(), it inserts just fine. And using print $name;, the quote() part seems work fine. Why is there nothing inserted into database after using quote()?
PDO::quote will put single quotes around your values. So you don't need to do that yourself in your SQL.
Though I'd strongly recommend you switch to using prepare() with named parameters.
Do not use PDO::quote. It is much better to use parameterized queries.
$stmt = $connection->prepare("INSERT INTO Contact (name, e, l, m, i) VALUES (?,
?, ?, ?, ?)");
// This will quote all of the values for you
$stmt->execute(array($name, $eeeee, $llll, $mmmm, $iiiii));
You can also use bind methods (bindParam or bindValue) instead of passing the arguments directly to execute. This will allow you to specify the data types if it's necessary, but it seems like these are all supposed to be strings.
I'm passing a prepared sql insert statement (using placeholders ?, ?) into a mysql database. I'm then using ->execute($array) and passing a single array of the values in. It's working great (ie inserts) when there is data entered into every field of the form (the array is complete), however fails completly if just one single element is not completed.
With the older mysql_query, if a value was missing it would simply not insert that value into the database.
How do we deal with this in prepared statements?
Thanks!
They way you deal with it is to properly ensure you have entered all relevant values for your query. mysql_query() can be as lax as it wants because at the end of the day, it only has to support MySQL, but PDO is a generic interface for relational data storage and it does not take the job of making sure you've entered all your data.
I don't see the comparison because mysql_query doesn't take parameters?
The PDO object requires you to bind your elements to the parameters. This is the long-way:
$stmt->bindParam(":namedParam", 1, PDO::PARAM_INT);
This is short-hand, so internally PDO still should do the above with some extra work for itself:
$stmt->execute(array($value1, $value2, $etc));
If your query looks like this:
INSET INTO mytbl VALUES (?, ?, ?, ?, ?)
and your $data array looks like this:
$data = array($val1, $val2, $val3);
Where do you think the two NULL values should be inserted?
1st & 3rd ?'s ? How should PDO know that?
Furthermore, if you do know the answer to that question, you can still handle it in PHP:
function queryMyTable($val1, $val2, $val3, $val4 = null, $val5 = null) {
...
$stmt->execute(array($val1, $val2, $val3, $val4, $val5));
}
Prepared Statements
Okay, I've just started taking a look at MySQLi prepared statements. This was a big step for me as I'm very new to MySQL and PHP anyway, so I have an extremely tenuous grasp on the concept (perhaps about an hours worth), so your answers will have to be phrased similarly, sorry about this.
What I am wanting to know is if I am correctly writing a prepared statement. There's nothing worse than learning a method which is incorrect and getting used to it, therefore coding entire projects inefficiently.
To the point: I have a function which registers a user, and then returns the inserted id, which is therefore the referencing id of the user.
Previously, I was simply querying the database, which I was told had security risks despite the use of mysql_real_escape_string() and similar security measures.
Now, it looks something like this: (assume for the sake of this question that all referenced variables are defined, the bound parameters are strings, and all called functions exist and are working).
function registerUser($username, $fname, $email, $password, $region, $activation) {
$uniqueSalt = uniqueSalt();
$password = sha1($uniqueSalt . $password);
$mysqli = mysqli_connect('localhost', 'root', '', 'database');
if ($stmt = $mysqli->prepare("INSERT INTO `users` VALUES('', ?, ?, ?, ?, '$password', '$uniqueSalt', '$activation')") ) {
$stmt->bind_param("ssss", $username, $fname, $email, $region);
$stmt->execute();
$stmt->close();
} else {
echo 'error preparing statement';
}
return mysqli_insert_id($mysqli);
}
Questions
It seems to work, but:
1) Is this correct syntax for executing a prepared statement?
2) I had included the file this function was in (call it function.php) with another file called init.php which previously defined the variable $mysqli. I found if I didn't include
$mysqli = mysqli_connect('localhost', 'root', '', 'database');
I would receive an error. Why did I have to redefine it inside the function?
3) When I previously ended the function before I used prepped statements, with return mysql_insert_id() which worked fine, now I've found I have to use mysqli_insert_id($mysqli).
If I don't include $mysqli inside the parentheses I get the error mysqli_insert_id() expects exactly 1 parameter, 0 given. Why is this and why does it differ from what I had before?
Cheers,
Luke.
Your usage doesn't make a lot of sense. From the PHP Manual Example:
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
Compare this to your usage:
$stmt = $mysqli->prepare("INSERT INTO `users` VALUES('', ?, ?, ?, ?, '$password', '$uniqueSalt', '$activation')");
$stmt->bind_param("ssss", $username, $fname, $email, $region);
Notice anything strange? The Manual example is using ? as a placeholder, where you then use ->bind_param() to create the substitution set. So your example, I believe, should be:
$stmt = $mysqli->prepare("INSERT INTO `users` VALUES('', ?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("sssssss", $username, $fname, $email, $region, $password, $uniqueSalt, $activation);
Not knowing if $activation is a number or string value. (Also, I would suggest using the column names and not omitting them in the INSERT query.)
Now, what you did should work in many cases simply because you're creating a single use statement and using variable expansion to insert the $pass, $uniqueSalt, $activation into the query string that is being prepared. Cases where it won't is if you accidentally have a ' in one or more variables you're putting in the query, which should either be parametized (using ->bind_param()), or using mysqli_real_escape_string(). However, mixing these approaches is poor practice and defeats the purpose of using prepared statements. There is no reason to do the first few, but not the last few.
Your $mysqli variable is "out of scope" when you call it in the function if it's defined globally, hence when not available, you can't use it unless you import it or create another one locally (in the function). You can import it using the global $mysqli; syntax within the function (as long as it's created globally and not locally in another function).
This is the same issue as #2. See: http://php.net/manual/en/mysqli.insert-id.php
My recommendation is to use PDO instead of the mysql_/mysqli_ functions.
1) Is this correct syntax for executing a prepared statement?
No, not really. Just look at the PHP Manual which shows you a cleaner way for mysqli, for example not building the string with variables containing values to insert into the database. Next to these probably smaller issues which aren't any for a very good programmer who knows what to do, the syntax is actually correct and as long as the code executes like you want it to execute, then the syntax is correct for executing a prepared statement. Just test on your own and you will know.
2) I ...
... have no idea what you're concerned about. Please elaborate clearly and concise. What have you done when, what changed, what happens now? Please add code examples for all the different stages.
3) When I previously ended the function before I used prepped statements, with return mysql_insert_id() which worked fine, now I've found I have to use mysqli_insert_id($mysqli)...,
The function mysql_insert_id is different from the function mysqli_insert_id. Only the same function work exactly the same, so this is nothing special that both functions are different because those are different functions.