I am coding a reoccurring sql select with a varying clause. In the clause i have a PHP variable (supposed to be replaced later within a WHILE.
My code:
$custaccount_id_clause = "(SELECT DISTINCT(custaccount_id) AS custaccount_id FROM accountcomms_def_tbl a WHERE subagent_def_id = " . '\'$interest_id\'' . " AND agentorder > (SELECT agentorder FROM accountcomms_def_tbl WHERE subagent_def_id = '$subagent_def_id' and custaccount_id = a.custaccount_id))";
$subagent_def_id works becuase its already defined.
$interest_id does NOT work because its not defined. I am trying to substitute it with $interest_id later on during a while loop in which I am calling $custaccount_id_clause as part of a while loop:
$allresidual_sql = mysql_query("SELECT SUM(txn_value) as txn_sum, COUNT(DISTINCT(custaccount_id)) AS accounts FROM account_stmnt_tbl WHERE txn_type IN ('Fixed Residual','Variable Residual','One Time Adjustment') AND custaccount_id IN ". $custaccount_id_clause)or die(mysql_error());
Within the $custaccout_id clause, I have the text '$interest_id' which I want PHP to replace the variable within. It is not replacing the variable.
This is a quick example app I am writing for a demo, please dont lecture me about which API I am using, as I wont be coding anything that goes into production! :)
A simple way to use the first variable you wanted to use ($interest_id) would be to test it and place a null inside instead of the variable in a direct fashion like this:
WHERE subagent_def_id = '" . ($interest_id ? $interest_id : null) . "' AND agentorder
This should protect you from getting errors about the variable/property not being defined.
The substitution part is what intrigues me... do you mean, at a given point in your structure, replacing $interest_id with, let's say, $my_other_variable? You could accomplish that if you model the whole SQL query as a string and, depending on a given condition, you re-write it.
Something like this could work (it's just a simple test, adapt it for your needs if you see it fit):
$query = ($a ? "SELECT * FROM `products` WHERE `price` > '{$a}';" : "SELECT * FROM `products` WHERE `date_added` < '{$b}' AND price > 20;");
That's if I have understood you correctly. Otherwise, I suspect you want to use the eval() function for parsing your encoded string and making PHP process your variable as you wish.
Hope that helps
Related
a quick question :), I wrote this because someone said that my codes are vulnerable to mysql injection and it is a requirement to learn prepared statement in web programming to avoid any user putting malicious data or statement into the database..What I have is a search function that search data from the database, if you type in a string like this "torres" then i search for torres but if you just put "tor" it won't search for datas that contain "tor" in their name..I don't know the correct format while using prepared statement, If you have advice I'm very happy to take it :)
<?php
if (isset($_POST['search'])) {
$box = $_POST['box'];
$box = preg_replace("#[^0-9a-z]#i","",$box);
$grade =$_POST['grade'];
$section = $_POST['section'];
$strand = $_POST['strand'];
$sql = "SELECT * FROM student WHERE fname LIKE ? or lname LIKE ? or mname LIKE ? or grade = ? or track = ? or section = ?";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)){
echo "SQL FAILED";
}
else {
//bind the parameter place holder
mysqli_stmt_bind_param($stmt, "ssssss",$box, $box, $box, $grade, $strand, $section);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while($row = mysqli_fetch_assoc($result))
{
echo "<tr>";
echo "<td>".$row['lname']."</td>";
echo "<td>".$row['fname']."</td>";
echo "<td>".$row['mname']."</td>";
echo "<td>".$row['grade']."</td>";
echo "<td>".$row['track']."</td>";
echo "<td>".$row['section']."</td>";
echo "</tr>";
}
}
As requested:
#ArtisticPhoenix I clearly prefer the king's way [compound full text index]. This should be your primary answer showing an example/explaination.
First make a full text index that includes all three fields (this is in PHPmyAdmin, it's a bit easier to explain with an image)
Then do a query like this:
#PDO version SELECT * FROM `temp` WHERE MATCH(fname,mname,lname)AGAINST(:fullname IN BOOLEAN MODE)
#MySqli version SELECT * FROM `temp` WHERE MATCH(fname,mname,lname)AGAINST(? IN BOOLEAN MODE)
SELECT * FROM `temp` WHERE MATCH(fname,mname,lname)AGAINST('edward' IN BOOLEAN MODE)
It seems simple but there are some things with full text to be aware of Min char count which is 3 (I think) anything smaller than that is not searched on. This can be changed but it requires repairing the DB and restarting MySql.
Stop words, these are things like and, the etc. These can also be configured in my.cnf.
Punctuation is ignored. This might not seem a big deal on names but think of hyphenated last names.
Usually I reduce the word min to 2 and point the stopwords to an empty file (disabling them).
The match against syntax is quite different, it's pretty powerful but it's not really used outside of full text. An example is: this is the wild card * and you use '"' double quotes for exact phrase match '"match exactly"', and + is logical AND, such as word+ word+ (default is or), - is do not match this etc... If I remember right, I used it a bunch a few years ago but haven't had to use it recently.
For example doing "begins with" on a partial word
SELECT * FROM `temp` WHERE MATCH(fname,mname,lname)AGAINST('edwar*' IN BOOLEAN MODE)
Same result matches one row. The obvious benefit is searching all 3 fields at the same time, but the full text syntax itself can be quite useful too.
For more information:
https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html
PS. I might add that using OR in a query can really kill performance, I've went as far as to replace simple OR with a UNION because of how bad the performance is on a large table. Logically the DB optimizer has to rescan the entire table for an OR, unlike AND where it can use the result of the previous expression to reduce the next expressions data set (or that is how I understand it). I can say the performance difference is very noticeable using OR vs UNION.
This is true for a compound full text index vs doing OR on each field separately. By default fulltext is faster, but it's even faster this way.
To fix your current query (for the sake of completeness)
You need whats known as an exclusive or, like this:
SELECT * FROM student WHERE ( fname LIKE ? OR lname LIKE ? OR mname LIKE ? ) AND grade = ? AND track = ? AND section = ?
What this does is group the OR's together so that they evalute as one expression to the "next level up" ( outside the parenthesis ). Basically order of operations. In English, you would have to match at least 1 of these columns fname, lname, mname AND you would also have to match all of the rest of the columns as well, to get a result returned for any given row.
If you use all OR (as you are now) and any single field matches, then the query comes back as true with matches. Which is the behaviour you are experiencing now.
If you simply change everything outside of the name fields to AND, Basically remove the parenthesis
Like this:
#this is wrong don't use it.
SELECT * FROM student WHERE fname LIKE ? OR lname LIKE ? OR mname LIKE ? AND grade = ? AND track = ? AND section = ?
Then you have to match this way.
(grade AND track AND section AND mname) OR lname OR fname
So if the last or first name match you get results regardless of any of the other fields. But the mname field you would find has to match with all the rest of the fields to get a result (but you would not likely notice this). Because, it would seem that the query works how you want but only when the mname is a match.
I hope that makes sense. It may be helpful to think of the WHERE clause as an IF condition the same logic rules apply.
Cheers!
I am trying to make a query that will take the inputted items and search the database. I know how I have done it several times, but this query just does not want to work.
This is the query
$getcamp = $db->query("SELECT * FROM `campaigns`
WHERE `requirements` LIKE '%$keyw%' OR `description` LIKE '%$keyw%' OR `name`
LIKE '%$keyw%' OR `countries` LIKE '%$country%' OR `id` LIKE '%$camp%' OR `category`
LIKE '%$cat%' AND `active` = '1' ORDER BY `added`")
or die($db->error);
There are a lot of OR breaks, and I have tried wrapping then in parenthesis in several different variations, but the query still will not work, and there are no errors, it just still shows everything in table instead of what was searched. I am not the best with these kinds of queries as normally I am only writing to search 1 or 2 items, this one is searching for a lot.
If I were to only be searching for the first 3 in that statement it will work fine, but once I start adding onto it is when it breaks, even if I put parenthesis around the first 3, I am just not sure what I am doing wrong.
Also just a side note my host doesn't have mysqlnd support that's why I am not using a prepared statement but my variables are escaped before hand.
If one of your variables is empty, it will select all the rows.
You should do the following (this is a basic example so you understand the idea):
$orArray = array();
$orQuery = "";
if (!empty($keyw) && strlen($keyw) > 2) { // and other SQL injection checks
$orArray[] = "`requirements` LIKE '%{$keyw}%' ";
}
if (!empty($orArray())) {
$orQuery = implode(' OR ', $orArray);
}
$query = "SELECT * FROM `campaigns` WHERE ( {$orQuery} ) AND active = 1 ";
// You also should check if $orQuery is empty, if it is, you need to remove AND.
// Well, in that case you wouldn't do the query at all.
Something like this should do, but you need to make the checks for every variable.
PS: I recommend to set a minimum for string search (3 is a good starting point).
PS2: This may not be the problem, but I'm pointing it out because it's a flaw in your scripts logic.
I believe that problem is in fact, that you have "and" after "ors". you should put all ors into extra parenthesis.
To better illustrate consider this php code:
<?php
var_dump(1 || 2 && 0);
var_dump((1 || 2 ) && 0);
and output:
xxx#www0 ~/sp $ php -q a.php
bool(true)
bool(false)
note || is or, && is and
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.
i need to select the variable 'duration' from a database where the eventID equals $idnumber. Im using the query bellow but am not having any luck. Can anyone see any flaws.
$duration = mysql_query("SELECT `bs_reservations`.`duration`FROM bs_reservations WHERE (`bs_reservations`.`eventID` '$idnumber')");
Small change :
$duration = mysql_query("SELECT `bs_reservations`.`duration`FROM bs_reservations WHERE (`bs_reservations`.`eventID` = " . $idnumber . ")");
UPDATE :
$data = mysql_fetch_array($duration );
Try to print this $data......
I assume you're missing an = when comparing the 2 IDs at the end.
$duration = mysql_query("SELECT `bs_reservations`.`duration`FROM bs_reservations WHERE (`bs_reservations`.`eventID` = '$idnumber')");
Try this:
SELECT `bs_reservations`.`duration`
FROM `bs_reservations`
WHERE `bs_reservations`.`eventID` = '{$idnumber}'
I've added whitespace before the from, added an = before idnumber, added a backtick after the where and for good measure also added the { and } though they are not really needed, but good practice.
While the obvious problem is the missing operator "=" (most adequately answered by #Dave IMO), perhaps you're having difficulty using the data once the MySql query has been properly executed. One would think you could then take your variable "$duration" and use it. Not true. $duration is now a resource, and you need to extract the information from it. If you know you're only going to get one piece of data back, consider the following code after your query:
list($duration)=mysql_fetch_array($duration);
This of course resets $duration to the value retrieved by the query and is no longer usable as a mysql resource, but it gets what you're looking for.
If this was not your problem, my answer would be the same as #Dave
Edit: Sorry, after reviewing the questions and answers again, my answer would be as follows:
$duration=mysql_query("select `duration` from `bs_reservations` where `eventID`='$idnumber'");
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?