I made a while loop that will tell if there are items in the transaction history and will put it back in the inventory as the transaction ends but the problem is. It fetches an error called
Uncaught Error: Call to a member function fetch_assoc() on bool in
So I tried the query's one by one and it works.
I tried to experiment and comment the other query and adding a counter++; to tell if the loop works. The problem I found is that after the first if else the counter only add's 1 Where as if I only try this it loops 4 which is right
Query I tried to check the number of loops
$counter=0;
$sql="SELECT * FROM brb_backtransaction WHERE trans_uk='$curr_trans' ";
if($rs=$con->query($sql)){
while ($row=$rs->fetch_assoc()){
$counter++
}
}
It echoes 1234 so it's correct but when the first if else happen it only echo'es 1
$counter =0;
$sql="SELECT * FROM brb_backtransaction WHERE trans_uk='$curr_trans' ";
if($rs=$con->query($sql)){
while ($row=$rs->fetch_assoc()){
$item = $row['trans_item'];
$quan = $row['trans_quantity'];
$sqlsitem="SELECT itmQuantity FROM brb_inventory WHERE itmName='$item'";
if($rs=$con->query($sqlsitem)){
$quanrow = $rs->fetch_assoc();
$currquan = $quanrow['itmQuantity'];
$counter++;
}
I remove other query's as I think this is the problem I ran a total of 3 queries in the while loop.
For your while loop to work it needs access to your original data stream as stored in the $rs variable.
However, further down in your code you are replacing the contents of the $rs variable with a totally new data stream. Therefore, the while loop no longer has access to the original data stream as it is basically throw away.
To solve this, change the second instance to another variable name such as $rs2. That way you have two completely different variables for two different data streams.
With that said, your code is also open to injection attacks. I would recommend looking into PDO and prepared statements.
Also, Tangentially Perpendicular is correct in using SQL JOINS
Related
Function render makes website 500% slow! Can anyone fix that please ?
Someone told me :
because it sends a database request on each iteration of the loop (it's not the only problem with this chunk of code but it's the most taxing one)
Yes I understand what that means. His way is:
you need to get all of the data before you start building the menu,
then you just insert the data instead of requesting more data on each
iteration
But i don't know how i must do it!
<?php
$menu_html='';
function render_menu($parent_id,$actmenuid)
{
$obj = new Database();
$con = $obj->dbconnectt();
global $menu_html;
$result=mysqli_query($con, "select * from tbl_menu where parent_id='$parent_id'");
if(mysqli_num_rows($result)==0) return;
if($parent_id==0){
$menu_html.='<ul class="topnav">';
}else{
$menu_html.='<ul>';
}
while($row=mysqli_fetch_array($result)) {
$childnum = $obj->recordcount("SELECT * FROM tbl_menu WHERE parent_id='".$row['id']."'");
if($childnum == 0){
$linkvalue='/category/'.$row['id'].'.html';
} else{
$linkvalue='#';
}
if($row['id']==$actmenuid && $actmenuid !=NULL){
$actv='class="active"';
}else{
$actv='';
}
$menu_html.='<li '.$actv.'>'.$row['title'].'';
render_menu($row['id'],$actmenuid);
$menu_html.='</li>';
}
$menu_html.='</ul>';return $menu_html;
}
if($isDsh==false){
echo render_menu(0,$actmenuid);
}
?>
Depending on how many records you have, try removing this query from inside the loop since it's running for every record on the first query.
$childnum = $obj->recordcount("SELECT * FROM tbl_menu WHERE parent_id='".$row['id']."'");
Change it a single query like this where it returns counts for each parent idea, and place it outside of the loop:
$parentcount = mysqli_query($con, ("SELECT parent_id, count(*) FROM tbl_menu GROUP BY parent_id");
There may be other issues, so please post the database structure and number of records that you're working with too.
Don't make recursive queries.
Having "more than 1000" rows is not too big. You can simply call everything from the table into php, then perform the recursive html build in php this will have a memory overhead, but far less processing overhead because you only ever make one trip to the db.
Alternatively (when your db table is prohibitively large), you should avoid gathering rows unnecessarily by adding a new column. The new column will store all "descendants" for the respective row when the row is INSERTed or update it when it is UPDATEd. Then you only need to reference this column when needing to call specific rows. In other words, do the recursive processing only once (when writing to the db) AND not when needing to display the data. This will, again, produce a finite result set in one query which can then be recursively traversed to build the desired output.
basically you need to do what #spudly has suggested.
But there is a small catch in his solution which depending on the number of the rows in yous tbl_menu table you may use a big chunk of memory to fetch all the records.
you can optimise it more with using his solution but changing the query to:
select
parent_tbl_menu.id,
count(child_tbl_menu.id) as cnt
from
tbl_menu as parent_tbl_menu
left join
tbl_menu as child_tbl_menu
on parent_tbl_menu.id = child_tbl_menu.parent_id
where
parent_tbl_menu.parent_id = ?
group by
parent_tbl_menu.id
This way you will only fetch the child records of a specific parent.
And please consider using prepared statements as your code has sql injection vulnerability.
Connect (from PHP to MySQL) only once for the entire web page.
Don't put a SELECT inside a loop if you can do all the work in a single SELECT, such as with a JOIN. (Exception: A "hierarchical" table needs the nested SELECT. Exception to the exception: MySQL 8.0 and MariaDB 10.2 can do it with a "recursive CTE".)
Don't fetch all the columns (SELECT *) when all you want it is a recordcount. Instead, SELECT COUNT(*) ... and use the number returned.
1000 of anything is probably excessive for a web page. Re-think the UI.
num_rows works only if I use mysqli->store_result(). Which means it works only with buffered result. Can someone explain why is this happening?
in the below code when I use mysqli->store_result() then num_rows works. otherwise it says 0.
function retrievearticle($mysqli, $articleid)
{
echo $articleid;
$query="select ArticleText,ArticleTitle from article where ArticleId=?";
$stmt=$mysqli->stmt_init();
$stmt->prepare($query);
$stmt->bind_param('i', $articleid);
$stmt->execute();
$stmt->store_result();
echo "here 2";
$stmt->bind_result($ArticleText, $ArticleTitle);
$stmt->fetch();
echo $stmt->num_rows;
}
As per this comment in the PHP manual, here's an explanation of what you are facing :
Please be advised, for people who sometimes miss to read this important Manual entry for this function:
If you do not use mysqli_stmt_store_result( ), and immediatley call this function after executing a prepared statement, this function will usually return 0 as it has no way to know how many rows are in the result set as the result set is not saved in memory yet.
mysqli_stmt_store_result( ) saves the result set in memory thus you can immedietly use this function after you both execute the statement AND save the result set.
If you do not save the result set but still want to use this function you have to actually loop through the result set one row at a time using mysqli_stmt_fetch( ) before using this function to determine the number of rows.
A thought though, if you want to determine the number of rows without storing the result set and after looping through it, why not just simply keep an internal counter in your loop every time a row is fetched and save the function call.
In short, this function is only really useful if you save the result set and want to determine the number of rows before looping through it, otherwise you can pretty much recreate its use like I suggested.
I'm using PHP and MySQLi and following a tutorial-type example and have some basic behavioral questions. A php code sample follows (hm, hope I format it correctly, 1st post here):
<?php
$db = new mysqli('hostLiteral', 'userLiteral', 'passwordLiteral', 'people');
$results = $db->query("SELECT * FROM people")
if($results->num_rows) {
while($row = $results->fetch_object()) {
$records[] = $row;
}
$results->free();
}
?>
I used a DBMS many, many years ago and perhaps it's that behavior that's keeping me from understanding this.
My perception is that when the 'SELECT * FROM people' is executed, MySQL would scan the entire database, get all the pertinent data, and end up 'pointing' at the last record in the database. So when the 'while' loop begins, I would think that's where it's starting, it would only get the last record or row and be done.
But even if it did somehow start at the top of the database at the first row, how does it know to move through the database unless 'fetch_object()' is somehow telling it to move to the next row?
I'm certain I'm missing basic SQL behavior here. But I've not found a good explanation to dispel these concepts that were placed in my head years back.
Thanks for any aid in understanding!
The query leaves the cursor pointing at the first row of your result set rather than the last. Since the general use case is to move forward through the rows, it would make little sense to leave the cursor at the last row.
In addition, fetch_object does exactly what you surmise. It gets the current row and advances the cursor to the next row. It's interesting that the documentation doesn't state that explicitly (like it does with fetch_row, but the example given makes it clear enough that that's what it does:
/* fetch associative array */
while ($obj = mysqli_fetch_object($result)) {
printf ("%s (%s)\n", $obj->Name, $obj->CountryCode);
}
I can not get an SQL update statement to subtract a variable from a table value. Here is my code:
$_SESSION_Job101=mysql_fetch_array(mysql_query("SELECT * FROM job_101 WHERE job_101.username='$_SESSION_User'"));
mysql_query("UPDATE characters SET currenergy=currenergy-$_SESSION_Job101['ecost'] WHERE username='$_SESSION_User'");
$_SESSION_Job101 is a perfectly valid result, as I pull from it on another page; I even pull the 'ecost' on said page. I also update currenergy this way in another script, except I use the number 1 instead of the variable. So I've narrowed it down to that variable.
It wouldn't matter that $_SESSION_Job101 is the result from a second table (job_101), and that query is updating to the table characters, would it?
We don't have enough information, but since you don't perform ANY error handling or validation that SQL resultset is returned, it could be an error caused by issues such as:
no rows returned in first query
some other parsing issue not directly evident
I would propose that you use temporary strings and echo the actual SQL queries.
Continue by actually testing them with MYSQL (through workbench, queryviewer, or console) in order to see where and what the error is.
Also, it's not recommended to skip error checking and try to combine so many lines/steps into 2 lines.
Imagine the first query does not return any results for example...
Debugging:
$query1 = "SELECT * FROM job_101 WHERE job_101.username='$_SESSION_User'";
echo $query1."<br/>";
$_SESSION_Job101=mysql_fetch_array(mysql_query($query1 ));
$query2 = "UPDATE characters SET currenergy=currenergy-$_SESSION_Job101['ecost'] WHERE username='$_SESSION_User'";
echo $query2."<br/>";
mysql_query($query2);
Update
Based on your comment I suggest you try the following two options:
1) Add a space between the - and $_SESSION_Job101['ecost'].
2) If that doesn't work, change your string to:
mysql_query("UPDATE characters SET currenergy=currenergy-".$_SESSION_Job101['ecost']." WHERE username='".$_SESSION_User."'";`
I'd like to do different operations on the data returned from a single sql query, something like this:
$sql = "SELECT * FROM mandant";
$res = pg_query($_db,$sql);
while ($mandant_list = pg_fetch_object($res))
{
# do stuff
}
while ($mandant = pg_fetch_object($res))
{
# do other stuff
}
But this doesn't work. The first loop gets the data, the second one not.
Is it possible to reuse the result returned from the query without running it again?
If not, why? What happens to the $res variable?
Yes, you can "rewind" the result resource by using pg_result_seek().
It is possible.
The reason the second loop breaks is because every time you are fetching a row from the data set it is being decremented until there are no rows left in the object.
You'll need to make 2 copies of $res and then run the second while() on the second $res.