connect1($db_host,$db_username,$db_password,$db_name1);
$q="SELECT DISTINCT
bizinfo.dbiz_id,
bizinfo.company_name,
bizinfo.company_industry,
bizinfo.company_sub_industry
FROM
bizinfo
Inner Join biz_feedback ON bizinfo.dbiz_id = biz_feedback.biz_id AND biz_feedback.on_industry = bizinfo.company_industry
ORDER BY
bizinfo.dbiz_id ASC";
$rs_q=mysql_query($q);
while($row=mysql_fetch_assoc($rs_q))
{
$dbiz_id=$row['dbiz_id'];
$company=$row['company_name'];
$company_industry=$row['company_industry'];
$company_sub_industry=$row['company_sub_industry'];
connect2($db_host,$db_username,$db_password,$db_name2);
$sql_livedb=mysql_query("UPDATE bizinfo set bizinfo.company_industry='$company_industry', bizinfo.company_sub_industry='$company_sub_industry'
WHERE bizinfo.dbiz_id='$dbiz_id'");
}
When this code is run, all rows in the company_industry and company_sub_industry columns are filled with the same data (for the first biz_id).
Somewhere a join needs to happen, but I thought I had it covered here WHERE bizinfo.dbiz_id='$dbiz_id'.
It isn't at all obvious what your problem is, but I would guess that there is a value in one of the variables (probably $company_sub_industry) which has a single quote embedded in it, and consequently results in the WHERE clause being ignored.
Change your code to remove the update statement and instead dump the values so you can check them. Perhaps some error checking after/in mysql_query would help.
If this is the cause, the real solution is to not generate SQL by concatenating strings and variables. Research "php avoid SQL injection" for more info.
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.
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 am trying to track pageviews on my site whether a user is logged in or not and so I'm capturing the sessionId in my log. I only want to show tracking results for session ids that have at some point logged in and so my flow is as follows:
$pagestats = $wpdb->get_results("SELECT * FROM wp_user_stats WHERE uid=".$_GET['viewstats']);
$sessionArray = array();
foreach($pagestats as $checkSession)
{
if( !(in_array($checkSession->sessionId, $sessionArray)))
{
$sessionArray[] = $checkSession->sessionId;
}
}
Next, I am trying to gather all of the stats concerning any session Ids generated by this particular user ...
$sessions = join(',',$sessionArray);
$pagestats = $wpdb->get_results("SELECT * FROM wp_user_stats WHERE `sessionId` IN($sessions)") or die(mysql_error());
This is the part that throws the error. The error is:
Unknown column 'sjhntmqhltknks8pbhr750voe7' in 'where clause'
I don't understand why it's trying to find a column that matches the session Id instead of a result within that column.
The session IDs probably aren't getting quoted so the query looks like WHERE sessionID IN(abc, def, ...).
One way to fix that would be to change a line in the first loop:
$sessionArray[] = "'".$checkSession->sessionId."'";
Or you could create a second array with the quoted values.
The problem is that the session id is not numeric and needs to be wrapped in quotes. Something like the following would add proper quote to your $sessions string:
$sessions = "'" . implode("', '", $sessionArray) . "'";
You should also make sure you are escaping any user supplied input (e.g. $_GET['viewstats']) before using them to help avoid SQL injection attacks. It wouldn't hurt to escape $checkSession->sessionId as you are adding it to the $sessionArray array either.
If you are using a framework (it looks like you may be using WordPress) read the manual for the database component as it may provide functions to handle some of this for you.
I think you need to put quote around your session values
$sessions = "'".join("','",$sessionArray)."'";
Right now it's like WHERE IN (a,b,c) instead of WHERE IN ('a','b','c').
$pagestats = $wpdb->get_results("SELECT * FROM wp_user_stats WHERE `sessionId`=$sessions") or die(mysql_error());
This isn't an answer to the specific issue, but isn't the second SELECT statement unnecessary? If it is all stored in one table (unless there is a typo...) then SELECT * FROM wp_user_stats WHERE uid=$_GET['view_stats'] would retrieve all sessions for that user. Perhaps you need it done for multiple users? Even at that, you could simply do a GROUP BY clause.
Maybe I'm missing something though -- if so, sorry.
My query below updates a record using variables to identify the data in the DB. I think my syntax is correct although it might be wrong. Also, I am absolutely sure that the variables have legitimate values in them. Why won't this query work?
UPDATE `databasename`.`".$tablename."` SET `stock` = '".$f."' WHERE `myerspark`.`item_id` ='".$g."' LIMIT 1
Thanks guys. Tom, yes I have tried that and it works fine. But it is frustrating because I echo all three variables at the end of the script and they all display legitimate values.
Hamish, how do I view these errors?
Jon_Darkstar, these variables are assigned in previous lines of code. Here is my entire code block:
//variables $f, $g, and $tablename assigned from POST variables in previous lines
mysql_select_db($database_Yoforia, $Yoforia);
mysql_query("UPDATE `yoforiainventory`.`".$tablename."` SET `stock` = '".$f."' WHERE `".$tablename."`.`item_id` ='".$g."' LIMIT 1 ");
mysql_close($Yoforia);
echo ($f);
echo ($tablename);
echo ($g);
Again, when i echo these variables, they all come out with good values.
I'm kind of confused what belongs to SQL, what belongs to PHP, where that string comes from, etc. What you have might be fine (if there is a double quote in front and end that i dont see.
I'd probably write it like this:
$sql = "UPDATE databasename.$tablename SET stock = '$f' WHERE myerspark.item_id = '$g' LIMIT 1"
$res = mysql_query($sql, $conn).....
you can backtick more stuff (and/or do mysql_real_escape) for 'extra safety;, but that covers the idea.
What is myerspark? i dont see how it relates to the query, that is probably you're real meaningful error, whether there is a syntax error or not. If myerspark is a seperate table from tablename then you've got an issue here, maybe a JOIN you ought to have?
I have a function that I use called sqlf(), it emulates prepared statements. For instance I can do things like:
$sql = sqlf("SELECT * FROM Users WHERE name= :1 AND email= :2",'Big "John"','bj#example.com') ;
For various reasons, I cannot use prepared statements, but I would like to emulate them. The problem that I run into is with queries like
$sql = sqlf("SELECT * FROM Users WHERE id IN (:1)",array(1,2,3) );
My code works, but it fails with empty arrays, e.g. the following throws a mysql error:
SELECT * FROM Users WHERE id IN ();
Does anyone have any suggestions? How should I translate and empty array into sql that can be injected into an IN clause? Substituting NULL will not work.
Null is the only value that you can guarantee is not in the set. How come it is not an option? Anything else can be seen as part of the potential set, they are all values.
I would say that passing an empty array as argument for an IN() clause is an error. You have control over the syntax of the query when calling this function, so you should also be responsible for the inputs. I suggest checking for emptiness of the argument before calling the function.
Is there a possibility that you could detect empty arrays withing sqlf and change the SQL to not have the IN clause?
Alteratively, you could postprocess the SQL before passing it to the "real" SQL executor so that "IN ()" sections are removed although you'd have to do all sorts of trickery to see what other elements had to be removed so that:
SELECT * FROM Users WHERE id IN ();
SELECT * FROM Users WHERE a = 7 AND id IN ();
SELECT * FROM Users WHERE id IN () OR a = 9;
would become:
SELECT * FROM Users;
SELECT * FROM Users WHERE a = 7;
SELECT * FROM Users WHERE a = 9;
That could get tricky depending on the complexity of your SQL - you'd basically need a full SQL language interpreter.
If your prepare-like function simply replaces :1 with the equivalent argument, you might try having your query contain something like (':1'), so that if :1 is empty, it resolves to (''), which will not cause a parse error (however it may cause undesirable behavior, if that field can have blank values -- although if it's an int, this isn't a problem). It's not a very clean solution, however, and you're better off detecting whether the array is empty and simply using an alternate version of the query that lacks the "IN (:1)" component. (If that's the only logic in the WHERE clause, then presumably you don't want to select everything, so you would simply not execute the query.)
I would use zero, assuming your "id" column is a pseudokey that is assigned numbers automatically.
As far as I know, automatic key generators in most brands of database begin at 1. This is a convention, not a requirement (auto-numbered fields are not defined in standard SQL). But this convention is common enough that you can probably rely on it.
Since zero probably never appears in your "id" column, you can use this value in the IN() predicate when your input array is empty, and it'll never match.
The only way I can think to do it would be to make your sqlf() function scan to see if a particular substitution comes soon after an "IN (" and then if the passed variable is an empty array, put in something which you know for certain won't be in that column: "m,znmzcb~~1", for example. It's a hack, for sure but it would work.
If you wanted to take it even further, could you change your function so that there are different types of substitutions? It looks like your function scans for a colon followed by a number. Why not add another type, like an # followed by a number, which will be smart to empty arrays (this saves you from having to scan and guess if the variable is supposed to be an array).