mysqli_multi_query function not updating all table rows in database - php

I have been attempting to use mysqli_multi_query to update multiple table rows at once. I have found that this function always leads to the update of all rows except for 1 row. For instance, if I had 5 rows of data that I designated to be updated, then only 4 rows are actually updated. Even when I increased the numbers of rows to 6 or 7 etc, there is only 'n-1' rows actually updated ('n' being the numbers that I designated to be updated).
some of the code is below:
<?php $jag = mysqli_connect($host, $user, $pass, $db); // connects to the database
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$query2 .= "UPDATE inst_prod_stor SET age_type = '2' WHERE payer_mail = '$pmail' AND file_name = '$fname';";
print_r($query2);
// execute the 'update' multi query
$result2 = mysqli_multi_query($jag, $query2) or die(mysqli_error($jag));
mysqli_close($jag); ?>
I have also checked the source code on my webpage after I execute the php file that cotains this code and it is fine. I receive no errors. I actually used the 'print_r' function to check that no data was being left out before the 'mysqli_multi_query' function executed. And in fact, no data was left out. The result of the function is almost perfect every single time I execute the code. The only imperfection is the fact that one row of the table is never of updated. And each time it's a different row.
I really need help on this one, it is pretty much the last leg of a 2 or 3 week coding journey before I finish up a project that I am currently working on. Thanks!

use mysql_real_escape_string and remove . near $query2
$pmail = mysql_real_escape_string($pmail);
$fname= mysql_real_escape_string($fname);
$query2 = "UPDATE inst_prod_stor SET age_type = '2' WHERE payer_mail = '$pmail' AND file_name = '$fname';";

$result2 = mysqli_multi_query($jag, $query2) or die(mysqli_error($jag));
will only die() if the first query in $query2 has an error.
I suggest that you use a do-while loop to establish a means to debug non-first query sql failures using mysqli_error() & mysqli_affected_rows().
Strict Standards: mysqli_next_result() error with mysqli_multi_query

Related

MySQL Update with select

I have a table with articles(articles) that have their contents to be updated by a team accessing them through the Internet(PHP) and assigning them automatically the articles to worked upon, based on the article status and id.
We have the id of the article(artid), its content(artcont) and its update status(artstat): Y(yes)/N(no)/B(blocked).
When one member of the team wants to work on updating articles, I want to automatically select for him the article that has its artstat "no" and the lowest articleid, setting at the same time artstat as "blocked" (to prevent it being edited at the same time by other team members).I want at the same time to return the artid that it's being edited.
For the moment, I have in PHP a select query followed immediately by an update one:
....(credentials for connecting to database)...
$conn = mysqli_connect($servername, $username, $password, $dbname);
$sql=SELECT * from articles where artstat='N' order by artid asc LIMIT 1;
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) == 1) {
// output data
$row = mysqli_fetch_assoc($result);
echo "id: " . $row["artid"]. "<br>";
$upd = "UPDATE articles SET artstat='B' where artid=" .$row["artid"];
mysqli_query($conn, $upd);
}
else {
echo "0 results";
}
Now, my question is: is it possible that a second team member (on another opened connection) who wants to work on an article makes his request exactly between the execution of the select and update statements, he will get the same article to work with (artstat is not 'B' yet), isn't it?
How to avoid this?
Thank you.
In Mysql , there are two type of locking to avoid such situation in innodb engine
table level locking
row level locking
You will need row level locking for this
You can read more about this from the below stack over flow post.
https://dba.stackexchange.com/questions/15854/innodb-row-locking-how-to-implement

commands are out of sync.. you cant run this command now in while loop

`$sql = "call geodist(".$_SESSION['This'].",500)";` //get the ids near you
$result=mysqli_query($GLOBALS['link'],$sql) or die(mysqli_error($GLOBALS['link']));
while($row=mysqli_fetch_assoc($result)) // insert them into nerby table
{
$sql = "INSERT INTO `nearby`(`userid`, `strangerid`) VALUES (".$_SESSION['This'].",".$row['id'].")";
mysqli_close($GLOBALS['link']);
mysqli_query($GLOBALS['link'],$sql)
or die("akash".mysqli_error($GLOBALS['link']));
}
when i remove the '//*' statements i get out of sync error.... keeping those two lines help me run my code but code becomes slow since for every loop iteration the database connection is closed and reopened. pls tel me an alternate.... i will really be grateful to you
What happens is you have data in the buffer between mysql and PHP when you try to fill it with new data (the query inside the loop).
What you need to do is
either fetch all data from the buffer before you use it for other query
See how u set this mysqli connection to fetch data unbuffered.
Read more here
http://dev.mysql.com/doc/apis-php/en/apis-php-mysqlinfo.concepts.buffering.html
DROP TEMPORARY TABLE IF EXISTS near;
CREATE TEMPORARY TABLE near
i added these 2 lines in my geodist() procedure.
it creates a temporary table named "near" and stores the result set in it.
now this table could be used as follows
$sql = "call geodist(".$_SESSION['This'].",".$GLOBALS['RADIUS'].")"; // get the ids near you
$result=mysqli_query($GLOBALS['link'],$sql) or die(mysqli_error($GLOBALS['link']));
$sql = "SELECT m.`id`\n"
. " FROM `members` m , `already_assigned` a\n"
. " WHERE a.`id`=m.`id` and m.`id` <> ".$_SESSION['This']."\n"
. " and m.`gender`=".$_SESSION['wants']." and m.`interested_in`=".$_SESSION['gender']." and a.`status`='free'\n"
. " and m.`id` IN (SELECT * from `near`)\n" /*see this line*/
. " ORDER BY RAND( ) \n"
. " LIMIT 1";
you can see that now i have removed the while loop... now its not required
How 'bout not closing the database connection until you're actually done with it?
You should only ever establish ONE connection to any given database server (so basically, one connection in your script unless you're working with a complex multi-DB-server setup)

sqlite3 - efficient way to count rows returned from SELECT statement in PHP without using COUNT()

I'm an SQL noob and learning how to use PDO. I'm doing a course which introduces basic user login functions. In an example of a login page, they check the username/password against a MySQL database. I edited their code slightly to be able to simultaneously check whether the user/pass combo exists and also grab the user's first name:
$sql = sprintf("SELECT firstname FROM users WHERE username='%s' AND password='%s'",
mysql_real_escape_string($_POST["username"]),
mysql_real_escape_string($_POST["password"]));
// execute query
$result = mysql_query($sql);
if (mysql_num_rows($result) == 1) {
$_SESSION["authenticated"] = true;
// get contents of "firstname" field from row 0 (our only row)
$firstname = mysql_result($result,0,"firstname");
if ($firstname != '')
$_SESSION["user"] = $firstname;
}
What I want to do is use SQLite instead and do the same thing. Searching around has only resulted in people saying you should use a SELECT COUNT(*) statement, but I don't want to have to use an extra query if it's possible. Since I'm SELECTing the firstname field, I should only get 1 row returned if the user exists and 0 if they don't. I want to be able to use that number to check if the login is correct.
So far I've got this:
$dsn = 'sqlite:../database/cs75.db';
$dbh = new PDO($dsn);
$sql = sprintf("SELECT firstname FROM users WHERE username='%s' AND password='%s'",
$_POST["username"],
$_POST["password"]);
// query the database and save the result in $result
$result = $dbh->query($sql);
// count number of rows
$rows = sqlite_num_rows($result);
if ($rows == 1) { ...
But this is returning Warning: sqlite_num_rows() expects parameter 1 to be resource, object given.
Is there a way I can do this efficiently like in MySQL, or do I have to use a second query?
EDIT:
I found this, not sure if it's the best way but it seems to work: How to get the number of rows grouped by column?
This code let me do it without the second query:
// query the database and save the result in $result
$result = $dbh->query($sql);
// count number of rows
$rows = $result->fetch(PDO::FETCH_NUM);
echo 'Found: ' . $rows[0];
$rows is an array so I can just count that to check if it's > 0.
Thanks to everyone who commented. I didn't know until now that there were 2 different approaches (procedural & object oriented) so that helped a lot.
Normally, you can use PDOStatement::rowCount(), however, SQLite v3 does not appear to provide rowcounts for queries.
You would need to seperately query the count(*), or create your own counting-query-function.
The documentation comments have an example of this
A bit late, but i tried this with SQLite3 successful:
$result = $db->query('SELECT * FROM table_xy');
$rows = $result->fetchAll();
echo count($rows);

MySqli not rolling back appropriately

I have a database listed as $db under mysqli. This database is contains into two tables, I listed them below as table and table2 (just for this example). Table2's rows requires an id from table. This is fine, but there might be a problem adding the columns into table2 thus requiring a rollback routine. However, it doesn't seem to be working.
I started with turning off the auto-commit. I then tried to put in the rollback command even though I am using the die command to signal a failure. As far as I am concerned the transaction could be blasted into oblivion in mid operation and the database should still be stable. So I am not sure what is going on here unless the database is completely ignoring the fact that I am trying to turn off auto-commit.
The basic structure of my code is listed below:
function problem($str)
{
global $db;
mysqli_rollback($db);
die($str);
}
mysqli_autocommit($db,false);
//Basic check if exists
$sqlstr = "SELECT * FROM table WHERE name = '$name';";
$r = mysqli_query($db,$sqlstr);
if (mysqli_num_rows($r)>0){problem("A row already exists under that id");}
//Insert the row
$sqlstr = "INSERT INTO table (name,v1,v2,v3) VALUES ('$name','$v1','$v2','$v3');";
$r = mysqli_query($db,$sqlstr);
if (!$r){problem("Could not insert into the table. $sqlstr");}
//Get the generated id part 1
$sqlstr = "SELECT id FROM table WHERE name = '$name';";
$r = mysqli_query($db,$sqlstr);
if (!$r){problem("Could not add into the table. $sqlstr");}
//Get the generated id part 2
$row = mysqli_fetch_assoc($r);
$eid = $row['id'];
//A simple loop
$count = count($questions);
for ($i=1;i<=$count;$i++)
{
//This is where it typically could die.
$r = mysqli_query($db,"INSERT INTO table2 VALUES (...);");
if (!$r){problem("Could not add to the table2. $sqlstr");}
}
mysqli_commit($db);
Is there something I am missing? I tried to follow the examples I found for the auto-commit as closely as I could.
Transactions only work if the table engine supports them, e.g. InnoDB.

mysql_query returns nulls

I've got a php script which queries mysql for a certain row based on it's id.
This works fine for the first 3 rows , but on the 4th it returns nulls on all fields.
Here's the query:
mysql_query("SELECT ind,title,body,img,tags,live FROM project WHERE ind = '".$curid."' ")
let me know if you need to see more code.
I'm going to take a guess that the forth row doesn't have the id you think it does. Return them all (remove the where statement) and output them to the screen to check, or use a database browsing tool, if you have one.
Try some debugging..
$q = "SELECT ind,title,body,img,tags,live FROM project WHERE ind = '".$curid."' ";
$rs = mysql_query($q) or die("MySQL error in Query: ". $q ."<br><br>The error is:<br>".mysql_error());
when you execute query, change $curid by value that you consider is correct. verify result, if yet get null values, you can do it:
mysql_query("SELECT ind,title,body,img,tags,live FROM project WHERE ind = '".$curid."' " and
ind IS NOT NULL and title IS NOT NULL
)
for example

Categories