I have a checkbox list and I want to insert each item checked into the database. Since it is a checkbox, I only have one value to pass to the database, but I am also passing a variable (primary key) grabbed from a previous database insertion.
My problem is that I can't get it to post to the database. I have tried multiple ways to do this through posts here and nothing seems to work. I am at a loss. I am also fairly new to PHP and mysqli, so I am sure there are better ways to do what I am trying to do, so please help me out.
The table consists of three columns (school_id, graduate_id, schoolName). The school_id is the AI primary key and graduate_id will be populated with the variable $graduateID grabbed from the previous query.
Here is what I have:
if (isset($_POST['school'])) {
$school=$_POST['school'];
$schoolQuery="";
foreach($school as $value) {
if(!$schoolQuery) {
$schoolQuery="INSERT INTO schoolReunion (graduate_id, schoolName) VALUES ($graduateID, '$value')";
} else {
$schoolQuery .= ", ($graduateID, '$value')";
mysqli_store_result($schoolQuery);
}
}
$schoolQuery .=";";
if (mysqli_multi_query ($schoolQuery)) {
echo "Files have been updated successfully.";
} else {
echo "Error: " . $schoolQuery . "<br/>" . mysqli_error($dbc);
}
}
When the error code prints out, it looks fine, but it just won't post anything and gives me no errors. Can you help me?
#Maximus & #Eko Junaidi Salam, while you may be right, I don't see any evidence that there are issues with the front-end/form.
#jeroen, you are totally correct.
CarR is dealing with a single concatenated query, so mysqli_query is suitable.
I recommend wrapping the user-supplied variable in mysqli_real_escape_string() to cover the query vulnerability.
mysqli_store_result() is to be used on queries that return a result set; mysqli_affected_rows() is the function that yields a measure of success with INSERT/UPDATE/DELETE type queries.
Lastly, you are right to correct MrTechie. I don't think he realized the query concatenation.
Assuming the form is delivering the necessary values, I'll suggest a new query build section:
$schoolQuery="";
foreach($school as $value){
if(!$schoolQuery) {
$schoolQuery="INSERT INTO schoolReunion (graduate_id,schoolName) VALUES ";
}else{
$schoolQuery.=",";
}
$schoolQuery.="('$graduateID','".mysqli_real_escape_string($dbc,$value)."')";
}
$schoolQuery.=";";
$graduateID IS NOT escaped because I am assuming it comes from a safe place; $value IS escaped because it comes from user input.
Now to deliver the built query. Your code has syntax and logic errors, so try this:
if($schoolResult=mysqli_query($dbc,$schoolQuery)){
$total_rows=mysqli_affected_rows($dbc);
echo $total_rows," file",($total_rows!=1?"s have":" has")," been added.";
// if($total_rows<1){echo "Query Logic Error, # $schoolQuery";}
}else{
// echo "Query Syntax Error # $schoolQuery<br>".mysqli_error($dbc);
}
Uncomment the error lines while you are testing, then re-comment or delete for production.
This should sufficiently fix all the issues that are apparent in your snippet of code. Beyond that are the assumed issues...
Since you mention that you are employing a previous query to declare $graduateID, I will assume you have acquired the value via a SELECT query. Be sure to check that you have used
mysqli_free_result($graduateResult); // I assumed this variable name
to avoid any conflicts with subsequent queries. This is sometimes overlooked.
mysqli_multi_query() is best used when you are dealing with queries that are dependent on a prerequisite query. It seems your $schoolQuery is dependent on the success of what I will call "$graduateQuery". If you wish, you could use mysqli_multi_query() to run $graduateQuery then $schoolQuery. To help you with this implementation, I would need to see more of your code. If you wish to go down that road, it might be best to message me directly or start a new post (after you've had a try at it yourself.) Here is half of your job done: Strict Standards: mysqli_next_result() error with mysqli_multi_query
Related
I have a function that collects data and puts it into an object. It then converts this object into a json string, and places it into a table. It takes about 30 seconds to do it.
Now, this json string is fairly big (roughly 36mb or so).
But when I execute the query, nothing gets put into the table, and I don't get any errors.
So I did some debugging, and the code now looks like this:
function __construct($total, $allActions, $employees, $branches, $companies, $departments, $lastUpdated, $update = false)
{
echo "Made it to constructor. Update: ".json_encode($update);
global $conn;
$this->Total = $total;
$this->AllActions = $allActions;
$this->Employees = $employees;
$this->Branches = $branches;
$this->Companies = $companies;
$this->Departments = $departments;
$this->LastUpdated = $lastUpdated;
if($update) {
try {
$query = $conn->prepare("INSERT INTO actionplansummarydata_new (json, last_updated) VALUES (?, ?)");
echo "Prepared query.";
if($query->bind_param('ss', json_encode($this), $this->LastUpdated->format("Y-m-d H:i:s"))) {
echo "Bound parameters.";
if ($query->execute()) {
echo "Executed query.";
} else {
echo "Error inserting summary: " . $query->error;
}
} else {
echo "Error binding query: " . $query->error;
}
} catch(Exception $ex) {
echo "Exception: ".$ex->getMessage();
}
}
}
Now, when this is executed, this is the response I get on the page:
Made it to constructor. Update: truePrepared query.Bound parameters.
But I have an if statement here:
if ($query->execute()) {
echo "Executed query.";
} else {
echo "Error inserting summary: " . $query->error;
}
Neither of these gets echoed to the page, nor do I get any exceptions.
I'm completely baffled.
The server is MariaDB 10.4, the json field in the database is longtext, so it should be able to store it.
If your error reporting is at E_ALL, you should not be facing a silent fail with the query execution... In any case, first of all, some steps in troubleshooting the point of failure.
Move json_encode($this) out of the bind, assign to a variable, and var_dump to see what you're actually feeding the binder. So too with $this->LastUpdated->format; presuming it's a DateTime object, but who knows. Easier to debug when fail-points are outside conditional statements.
Can you confirm whether it works as expected if you insert strings of dummy data instead? E.g.:
if($query->bind_param('ss', '{}', '2020-05-19 01:01:01')); {
One problem here is with the fact that bind_param binds variables by reference, not by value. Therefore, you can't feed it with functions. You have to assign the values to variables and only then bind them (because a function doesn't return a usable reference). Meaning, change to:
$json = json_encode($this);
$updated = $this->LastUpdated->format("Y-m-d H:i:s");
if($query->bind_param('ss', $json, $updated)) {
You can assign the bind result (true/false) into a variable, then var_dump. (We'd rather not var_dump from inside the conditional statement, right?) The bind would fail === false for reasons above. Likewise, var_dump the prepared query to ensure it succeeds, tracing each step.
A fatal error might be triggered by the database engine acting up, quite possible with the size of your insert query. You may want to look up MariaDB error logs for more clues, in case you're hitting a limit somewhere. I'd guess with max_allowed_packet, default 16MB, you're well over it. (Also see mysqli_stmt::send_long_data for sending long data in blocks.)
In other issues, json is a reserved word in MySQL 8.0 (not listed as such for Maria 10.4?!). You may want to rename the column to ensure it doesn't become a problem (even if it works here).
As far as how this scenario is possible, what you describe (no output from the if/else) only makes sense if there's a fatal error triggered by the $query->execute() that's never displayed. Unless there's a bug in PHP error reporting with certain MySQL failures. Do triple-check your PHP error reporting configuration, including anywhere in your code/.htaccess that might override php.ini.
Check the setting of max_allowed_packet; this may be stopping you. Set it to 1G.
If that does not work, there may be timeout issues, or some other size limitation.
For large text strings, I sometimes like to compress them, and stored the string into a MEDIUMBLOB.
what data type that you are using to store the 36MB of JSON string ? you probably need to change the data type to LONGTEXT that can store up to 4GB of data or JSON data type that can store up to 1GB of data
or
you can store it individually as columns in a table and change it back to JSON on your code when needed
Try to check if prepared
if($query = $conn->prepare("INSERT INTO actionplansummarydata_new (json, last_updated) VALUES (?, ?)")){
$query->bind_param('ss', json_encode($this), $this->LastUpdated->format("Y-m-d H:i:s"));
if($query->execute()){
// code here
}
}
Okay, so I have some code here:
<?php
$rt = 'abc'; $imdb = 'defg';
if ($con = mysqli_connect($a,$b,$c,$d)) {
if (mysqli_query($con,"DELETE FROM blah WHERE a = '{$imdb}'")){
echo 'Deleted!';
if (mysqli_query($con, "INSERT INTO foo (c,d) VALUES ('{$rt}','{$imdb}')")){
echo 'Inserted after deletion!'
if (mysqli_query(...)) {
if (mysqli_query(....)) {
}
}
}
}
}
Some of my programs have many queries in a row, each of which is dependent on the result of a previous query. However, creating error handling for every single query and making sure that the logic of the code stays the same (not to mention staying readable) throughout can be a somewhat tedious and error prone process.
I would like to know a bit more about what is going on behind the scenes when a query is sent, because it would help me a lot with some of my questions. Namely, is it really necessary to write if (mysqli_query()) all the time for correct error handling, or is simply checking if the so-called 'master' connection exists enough?
That is, after I check mysqli_connect(), do I have to check every subsequent query within that connection to see if it went through (connection-wise, not logic-wise), or is it simply enough to check mysqli_connect() once, at the beginning of the program? It would sure make things a lot easier.
Also, while I'm looking at mysqli_multi_query() for more practical query management, I would prefer not to use it until I can fully understand the simpler query functions.
Thanks for your help!
Only few things for you to get it right
You have to distinguish an error from a query result. If your query depends on the result of the another one - it's all right to check the result. But if you want to check for the error - there are better ways.
In a properly written application a query error is a highly exceptional event, and there shouldn't be code written to handle it in place. It have to be done somewhere else.
mysqli can throw an exception in case of error, which is actually a Holy Grail you are looking for.
So, if you want to stop your code if one of queries failed, just set mysqli in exception mode and then pile your queries one after another.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$con = mysqli_connect($a,$b,$c,$d);
$rt = 'abc'; $imdb = 'defg';
mysqli_query($con,"DELETE FROM ...");
mysqli_query($con, "INSERT INTO ...");
mysqli_query(...);
mysqli_query(...);
...
And two additional notes
if you want to undo a previous query if following one failed, then use transactions
you should NEVER write a query like you do, interpolating a variable directly into it. You ought to use prepared statements, substituting every variable with placeholder in the query.
Here's the code i am using withing a for loop which run 10 times:
$query = "UPDATE fblikes SET likes = '$var[$i]' WHERE link = '$web[$i]'";
if(mysql_query($query))
{
echo $query;
}
else
{
echo mysql_error();
}
The code runs, I do get ok! printed 10 times but nothing happens in the table. I also checked the 2 arrays i.e. $var and $web, they contain the correct values.
The query looks okay to me. Here's what i got (one of the 10 outputs) : UPDATE fblikes SET likes = '5' WHERE link = 'xxxxxxx.com/xxxx/iet.php';
I don't know what the problem exactly is, and to figure out you should print the value of $query, and show us what you get. More, please tell us the value of mysql_affected_rows() after the call to mysql_query().
However, your code implements some wrong patterns.
First of all, you are not escaping $var[$i] and $web[$i] with two potential effects:
You can produce wrong queries
You don't sanitize the input to the database, thus exposing your application to security issues
Moreover, you perform several similar queries that differ only on the inputs provided.
The solution, for both issues, is the use of prepared statements that will give you more control, security and performance. Consider abandoning mysql_* functions and switching to mysqli_* or PDO, and read about prepared statements.
I'm trying to loop data from a api and then post these values to a MySQL db.
something like this:
$values = json_decode(file_get_contents("my-json-file"));
$SQL = new mysqli(SQL_HOST, SQL_USER, SQL_PASS, DB_NAME);
$SQL->autocommit(FALSE);
foreach($values As $item)
{
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";)";
$SQL->query($query);
if(!$SQL->commit())
{
echo "ERROR ON INSERT: [" . $query . "]<hr/>";
}
}
$SQL->close();
Since the loop is too fast, the SQL can't catch up. (Yea!)
I would then need something like this:
foreach($values As $item)
{
/**** STOP/PAUSE LOOP ****/
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";");
$SQL->query($query);
if($SQL->commit())
{
/**** START THE LOOP AGAIN ****/
}
else
{
echo "ERROR ON INSERT: [" . $query . "]<hr/>";
}
}
Or how should I do this the right way?
EDIT: It inserts random posts every time.
EDIT 2: This is just example code. It does escape and all that, and yes the semi colon is wrong here but since so many commented on it i will not change it. This was not the problem in the real case.
I tried to run it on another server and there it worked. The problem was fixed by restarting MAMP.
Firstly, your idea that the loop runs too fast for MySQL to keep up is completely totally wrong. The $SQL->query() call will wait for the MySQL to return a response before proceeding, so the loop won't run any faster than MySQL is responding.
Now onto the actual problem.... your query:
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";)";
There's a semi-colon in there at the end, after value2 which is invalid. I guess you intended to type a quote mark there? The semi-colon will be causing all your queries to fail and throw errors.
This may be the cause of your problem but you haven't got any error checking in there, so you won't know. Add some error checking to your code after calling the query; even if the query is right, it's still possible to get errors, and your code should check for them. See the examples on this manual page: http://www.php.net/manual/en/mysqli-stmt.error.php
Finally, since you're using the mysqli API, it's worth mentioning that your code would be a lot better and probably more secure if you used prepared statements. See the examples in PHP manual here: http://www.php.net/manual/en/mysqli-stmt.bind-param.php
[EDIT]
Another possible reason your query is failing is that you're not escaping the input values. If any of the input values contains a quote character (or any other character that is illegal in SQL) then the query will fail. In addition, this problem makes your code vulnerable to a SQL injection hacking attack.
You need to escape your input using $SQL->real_escape_string() OR by changing your query to use prepared statements (as recommended above).
Your query is inside the loop, which means that the loop will wait until your query finished executing before it continue, php code is processed in order...
Has #phpalix said, PHP goes in order, and waits for the previous action to finish.
I think you SQL is wrong. Try replacing your INSERT with this:
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2."');";
And don't forget to run at least mysql_real_escape_string for each variable, for security measures.
As many of the answers and comments say, it does not continue until the SQL is done. The problem was in my local apache/mysql server. It was fixed by restarting it. Yes, stupid post.
i am inserting day value to database,i want validation like if the day already exist it should say day already exist else it should innsert..please can anyone check the following code... thanks in advance
$dexist=$_POST['ext'];
$res=mysql_query("select Day from mess where Day='".$dexist."' ");
while($row=mysql_fetch_array($res))
{
$dy=$row['Day'];
}
if($dy==$dexist)
{
echo "<script language=\"javascript\">";
echo "window.alert ('File already exist');";
echo "//--></script>";
}
else
{
mysql_query("insert into mess (Date,Day,Breakfast,StartTimeb,EndTimeb,Lunch,StartTimel,EndTimel,Dinner,StartTimed,EndTimed) values('".$date."','".$day."','".$bre."','".$bres."','".$bree."','".$lun."','".$luns."','".$lune."','".$dinn."','".$dins."','".$dine."')");
}
Your script screams "SQL INJECTION!" Please pwn my site!
Also: your code is vulnerable to synchronization issues. For example, a file might be created AFTER you ran a select statement, but BEFORE you ran the INSERT statement. This will cause weird failures. That's why you should do the "select and insert" as a single stored proc (read up on atomic operations - more specifically, this is an instance of a "compare and swap").
Firstly never, ever pass unchecked POST/GET data into a MySQL query, it's a massive security hole. Use mysql_real_escape_string instead:
$res=mysql_query("select Day from mess where Day='" . mysql_real_escape_string($dexist) . "' ");
And similar for the latter call.
Secondly, it's not clear what you're asking... please tell us if the code is not working somewhere, and any errors you're getting. I think you have a problem with this line:
if(file_exists($dy==$dexist))
That is passing a boolean value ($dy==$dexist will evaluate to true or false) into the file_exists function. You need to pass the filename in.
Don't do that in PHP, it's difficult (impossible?) to do safely. Do it in MySQL by adding a unique index on the Day column:
ALTER TABLE mess ADD UNIQUE (Day);
You can then catch failures of that kind by looking for ER_DUP_UNIQUE from MySQL.
Use PHP's mysql_errno to check for error 1169 to catch unique constraint failure.
$query_result = mysql_query("insert into mess (Date,Day,Breakfast,StartTimeb,EndTimeb,Lunch,StartTimel,EndTimel,Dinner,StartTimed,EndTimed) values('".$date."','".$day."','".$bre."','".$bres."','".$bree."','".$lun."','".$luns."','".$lune."','".$dinn."','".$dins."','".$dine."')");
// 1169 means a unique constraint failure
if (!$query_result && mysql_errno() == 1169) {
echo "Oh noes, you tried to insert a value twice!";
}
This is a repost of your question.
searching for the original..
found it..
Want to check day already exist