unable to fetch data from mysql database - php

i have table where the patient test is stored and in another table the report result is saved by test_id defined in test table, now the test id is fixed and and i am fetching report result by the test_id but one can be more time by any user so the report resullt is updating in table but when i am trying to make report the old one report result is fetching, so, is there any solution for display only current result when the test_id is same in the table, this is my table image
i want to try fetch current result but it showing previous result.and here is code
function get_test_report( $test_id )
{
gri("report", "WHERE rep_te_id = '$test_id'", "", $report);
if($lab[lab_test_rl_id] == 4) # lab report
{
return get_lab_content( $report[rep_result], $lab[id] );
}
else # other report
{
return $report[rep_result];
}
}
hope you will understand becouse my english is not well, any idea will be very much appreciated

SELECT *
FROM report
WHERE rep_te_id = '$test_id'
ORDER by rep_date DESC
LIMIT 1
In your PHP, you're not using the proper syntax to access associative array elements. You need to quote the keys, so it should be $report['rep_result'] (the exception to this is when you're interpolating in a string, then you must leave the quotes out unless you wrap it with {}).

Related

Trying to understand php mysqli multi_query

I have a function that is designed to copy a product with all attributes with help of sql querys. My problem is to return new_product_id to php after completion.
If i run sql script in phpmyadmin all is working.
If i run sql script with php function all is working.
What i need help with is how to assign mysql-set-variable: #new_product_id from last query to php variable that I want to return.
----- sql query ------
CREATE TEMPORARY TABLE tmptable SELECT * FROM product WHERE id='19' AND site_id='1';
UPDATE tmptable SET id = 0,parent_id='19',status_id='1',name_internal=concat('NEW ',name_internal);
INSERT INTO product SELECT * FROM tmptable;
SET #new_product_id = LAST_INSERT_ID();
DROP TABLE tmptable;
CREATE TEMPORARY TABLE tmptable SELECT * FROM product_abcd WHERE product_id='19' AND site_id='1';
UPDATE tmptable SET product_id = #new_product_id,id=0;
INSERT INTO product_abcd SELECT * FROM tmptable;
DROP TABLE tmptable;
CREATE TEMPORARY TABLE tmptable SELECT * FROM product_efgh WHERE product_id='19' AND site_id='1';
UPDATE tmptable SET product_id = #new_product_id,id=0;
INSERT INTO product_efgh SELECT * FROM tmptable;
DROP TABLE tmptable;
(Here is more correct SQL insert statements)
SELECT #new_product_id AS new_product_id;
----- sql query ------
----- php function (not complete)------
This function is working making a new copy of product, code below is not complete but works so please only focus on multiquery part.
//return 0 for fail or new product_id (!=0) for success
public function copyProduct($data){
$res=0;
//if something, build sql-query as
$sql="sql from above";
//if we have a query to run
if(!empty($sql)){
//this is multi query, use correct function
if ($this->connect()->multi_query($sql) === TRUE) {
//loop it
while ($this->connect()->more_results()){
$result=$this->connect()->next_result();
}//while more results
}//if multiquery ok
return $res;
}//end function copy
----- php function (not complete)------
above code works, i get a nice copy of product with
result =0 for fail and
result 1 for success, (this works)
How i would like it to work is
result= 0 for fail and
result= new_product_id for success
so i can redirect user to the newly created product and therefore save user one click.
Results from query, same from phpmyadmin as from php (all good so far, no incorrect querys at this time)
Mysql returned empty results (no rows) (create temporary table)
1 row affected (update tmpt table)
1 row insert (insert into product)
mysql returned emtpy result (set $new_product_id)
mysql returened empty results (drop tmp table)
mysql returned empty result (create temporary table)
mysql x row affected (update tmp table)
mysql x row affected (insert into table)
mysql returned empty results (drop table tmptable)
mysql returned empty results (create temporary table)
.... N.....
last query "showing rows 0-0 ( 1 total) (select #new_product_id)
new_product_id=25
What have I tried?
I placed the select variable as my final query, i thought it was smart only check last query and assign variable there, but i failed due to php mysqli fetch_assoc is not possible on non object.
so next up was not so bright, i know i have 16 results from mysql and i only need the result from one of them, but anyway i places this inside multiquery
----- php function (not complete)------
This function is working making a new copy of product, NOT WORKING assigning new_product_id
//return 0 for fail or new product_id (!=0) for success
public function copyProduct($data){
$res=0;
//if something, build sql-query as
$sql="sql from above";
//if we have a query to run
if(!empty($sql)){
//this is multi query, use correct function
if ($this->connect()->multi_query($sql) === TRUE) {
//loop it
while ($this->connect()->more_results()){
//insert,update,drop will return false even if sql is ok, this would be sufficient for us now
if ($result = $this->connect()->store_result()) {
$row = $result->fetch_assoc();
if(isset($row["new_product_id"])){
//new return value of newly copied product
$res=$row["new_product_id"];
$result->free();
}
}
$result=$this->connect()->next_result();
}//while more results
}//if multiquery ok
return $res;
}//end function copy
----- php function (not complete)------
Checking other questions on stackoverflow recommended sending multiple normal querys, this seems like a bad solution when multi_query exists.
checking php library for multiquery did me no good, i cant understand how it works, as many others pointed out the documentation seems like a copy from another function.
Remember that multi_query() sends a clump of SQL queries to MySQL server but waits for the execution of only the first one. If you want to execute SQL using multi_query() and get only the result of the last query ignoring the previous ones then you need to perform a blocking loop and buffer the results into PHP array. Iterate over all results waiting for MySQL to process each query and once MySQL responds there are no more results you can keep the last fetched result.
For example, consider this function. It sends a bunch of concatenated SQL queries to the MySQL server and then waits for MySQL to process each query one by one. Every result is fetched into PHP array and the last available array is returned from the function.
function executeMultiQueryAndGetOnlyLastResult(mysqli $mysqli):array {
$mysqli->multi_query('
SELECT "a";
SELECT 2;
SELECT "val";
');
$values = [];
do {
$result = $mysqli->use_result();
if ($result) {
// process the results here
$values = $result->fetch_all();
$result->free();
}
} while ($mysqli->next_result()); // next_result will block and wait for next query to finish on MySQL server
$mysqli->store_result(); // Needed to fetch the error as exception
return $values;
}
Obviously it would be much easier to send each query separately to MySQL instead. multi_query() is very complicated and has very limited use. It can be useful if you have a number of SQL queries which you cannot execute separately via PHP, but most of the time you should be using prepared statements and send each query separately.
Another one bites the dust, I gave up and defined an array of sql querys from 0 to 14 and run it as mysqli->query() instead. Thank you all for comments and your time.
You could try using .multi_query() for all the queries in your operation except the last one, the SELECT that returns the id you want. Then run that SELECT as a single query.
This is a robust solution to your problem: #-variables belong to MySql connections and persist for the lifetimes of those connections.
And, it makes for clean and predictable operation of your software. When you need a result set returned to your program, use a single query.

function render makes website 500% slow! can anyone fix that please?

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.

SQL - change an existing row

I'm using PHP in order to create a website where managers have access and review forms that employees have submitted. In the reviewing PHP file, I have created two buttons which basically approve or disapprove the form. After they click on one of the buttons, they are being redirected to another PHP file which actually inserts into the MySQL Database a change in a column I named 'processed'. It changes 0 which is unprocessed to 1, which is processed. The table I am referring to has columns such as formid, fullname, department and other job related stuff, as well as the 'processed' column which allows the managers to see if there is a pending form to be reviewed.
My problem is that I have no idea how to actually allow MySQL to find the proper row and change only the cell with the name 'processed' from 0 to 1 without having to insert every cell again. Here's what I have tried till now:
$id = $_SESSION[id];
$fullname = $_SESSION[fullname];
$teamformid = $_SESSION[teamformid];
if (isset($_POST['approved'])) {
$sql = "INSERT INTO carforms (processed) where aboveid='$id' and processed='0' and teamformid=$teamformid
VALUES ('0')";
}
else if (isset($_POST['disapproved'])) {
//todo
}
How do I tell SQL to only find the specific row I want and change only one column which is processed?
Also, do I always have to type every column name when I use the INSERT INTO command?
Thanks in advance.
Use the Below code it'll work for you.
$id = $_SESSION[id];
$fullname = $_SESSION[fullname];
$teamformid = $_SESSION[teamformid];
if (isset($_POST['approved'])) {
$sql = "UPDATE `carforms` SET processed = '1' WHERE `aboveid` = '".$id."' AND `teamformid` = '".$teamformid."'";
}
Try:
"UPDATE carforms SET processed = 1 WHERE aboveid = $id AND teamformid = $teamformid"
From what I have interpreted from your question, it seems like you need to use the MySQL UPDATE command. This will update any existing rows.
For example, let's say you have a table called 'forms', consisting of a Primary Key 'form_id' and a field named 'processed'.
If we want to change the value of 'processed' to '1', we would run...
UPDATE forms SET processed = 1 WHERE form_id = [whatever number the form is];
Obviously this only works where the form (with a form_id) exists already
There is no "INSERT...WHERE" in SQL.
To change an existing record there are 2 options, REPLACE or UPDATE. The former will create the record if it does not already exist and has similar syntax to INSERT. UPDATE uses the WHERE clause to identify the record(s) to be changed.
Using REPLACE is tricky. It needs to work out whether it should INSERT a new record or UPDATE an existing one - it does this by checking if the data values presented already exist in a unique index on the table - if you don't have any unique indexes then it will never update a record. Even if you have unique indexes just now, the structure of these may change over time as your application evolves, hence I would recommend NOT using REPLACE for OLTP.
In your question you write:
where aboveid='$id' and processed='0' and teamformid=$teamformid
(it would have been helpful if you had published the relevant part of the schema)
'id' usually describes a unique identifier. So there shouldn't be multiple records with the same id, and therefore the remainder of the WHERE clause is redundant (but does provide an avenue for SQL injection - not a good thing).
If the relevant record in carforms is uniquely identifed by a value for 'id' then your code should be something like:
$id=(integer)$id;
$sql = "UPDATE carforms SET processed = $action WHERE aboveid=$id";
But there's another problem here. There are 3 possible states for a record:
not yet processed
declined
approved
But you've only told us about 2 possible states. Assuming the initial state is null, then the code should be:
$action=0;
if (isset($_POST['approved'])) {
$action=1;
}
$id=(integer)$id;
$sql = "UPDATE carforms SET processed = $action WHERE aboveid=$id";
if ($id &&
(isset($_POST['disapproved']) || isset($_POST['approved']))
) {
// apply the SQL to the database
} else {
// handle the unexpected outcome.
}

MySQL COUNT showing it's working out

I would expect the following to output the number "5", since there are 5 rows in the database with with item 68 and user 1. But instead I'm getting this output "12345".
$resultb4 = mysql_query("SELECT COUNT(comparedRating) FROM recComparedRating WHERE user1='1' AND itemID='68' GROUP BY itemID AND user1");
while($rowb4 = mysql_fetch_array($resultb4)){
$countcomparedratings=$rowb4['COUNT(comparedRating)'];
}
echo $countcomparedratings;
What am I doing wrong?
The reason you are getting 12345 is because your query is returning 5 results and your code to output the count is simply outputting the concatenation of the returned array from the query.
Without understanding your database structure, I'm guessing that the reason you're getting the '12345' has something to do with your GROUP BY clause. Use a program like MySQLWOrkbench to connect to your database and test out your query before you include it into your code. It is a time saving technique to debug your queries.
Also, I would alias the COUNT value so that you simply refer to the alias when you refer to your column names.
SELECT COUNT(comparedRating) as ratingCount FROM recComparedRating WHERE user1='1' AND itemID='68' GROUP BY itemID AND user1");

How to check if table is empty , Execute and FetchRow methods in php and mysql

$RSGetID = $this->MyDBObject->Prepare("SELECT FinalID FROM clothes
WHERE ClothID=:|1 AND PriceID = :|2 LIMIT 1");
$RSGetID->Execute(2, 199);
$ClothIDRow = $RSGetID->FetchRow();
return $ClothIDRow->FinalID;
This last line gives an error, because there are no rows in the table, so it says:
"the query did not return any records"
How do I put a condition, that if the table is empty then return 0 , else return the fetched FinalID from the database table?
You're using some custom DB layer (MyDBObject?) rather than straight-up PDO - it's impossible for us to know how this behaves. There's probably a method along the lines of ->RowCount() or ->NumRows() you can call to see if you got anything back after the ->Execute() - but this is just guessing, since I can't see the DB object you're using.

Categories