I am using mysql as my database and php as server side language.
As we know that we can select data from database using select query.
Below example is important!!
select * from table
select name from table
select name,salary from table where salary > 10000
etc..........
now, for different select query of a table we need different select method. because every time select * is not good because it takes a huge time.
Now, My Question is how write dynamic single get method of a single table by which we can achieve our requirement (shown in example...)?
I will pass the array of parameters in the argument of the function.. for ex. in php
public get($arr)
{
//code goes here
}
I want to fetch the $arr and want to change the sql dynamically..
Don't want any join query just simple select as shown in above..
Depending on how you want to do it, you can do something like this:
public get($arrfield, $arrtable, $arrwhere)
{
$str = "SELECT " . $arrfield . " FROM " . $arrtable . " WHERE " . $arrwhere;
return $str;
// You can return the query string or run the query and return the results
}
Trust me, to write all three queries is not that too hard a job that have to be avoided at any cost.
Please, do not obfuscate a precious SQL language into unreadable gibberish. Not to mention innumerable security breaches of your approach.
What you should think of is a function that lets you to use parameters. Thus, better make our function like this
function mysqli($mysqli, $query, $params, $types = NULL)
{
$statement = $mysqli->prepare($select);
$types = $types ?: str_repeat('s', count($params));
$statement->bind_param($types, ...$params);
$statement->execute();
return $statement;
}
and run your every query as is, only providing placeholders instead of variables
select * from table:
you'll never need a query like this
select name from table
$names = mysqli($db, "select name from table")->get_result->fetch_all();
`select name,salary from table:
$stmt = mysqli($db, "select name from table where salary > ?", [10000]);
$names = $stmt->get_result->fetch_all();
See - the query itself is the least code portion. Your concern should be not SQL but useless reprtitive parts of PHP code used to run a query and to fetch the data.
Here is the structure of the dynamic query.Please add required validation.You can add 'Or' clause also.On the basis of parameter or data type you can do it. Like
public SelectTable($arrfield, $table, $arrwhere, $arrgroup)
{
if(!empty($arrfield))
{
$fields = implode('`,`',$arrfield);
}
else
{
$fields = '*';
}
if(!empty($arrwhere))
{
foreach($arrwhere as $fieldName=>$fieldValue)
{
if(is_array($fieldValue))
{
$cond .= "`fieldName` in (". implode(',',$fieldValue) );
}
else
$cond .= "`fieldName` = '" . addslashes($fieldValue)."'";
}
}
else
{
$cond = '1';
}
if(!empty($arrgroup))
{
$groupBy .= " group by ";
foreach($arrgroup as $field=>$value)
{
$groupBy .= $field . " " . $vale;
}
}
}
$str = "SELECT " . $fields . " FROM " . $table . " WHERE " . $cond . $groupBy;
return $str;
// You can return the query string or run the query and return the results
}
Related
I have a web application and I'm trying to modify one of the queries. The query fetches information (from a table named voyage_list) and returns various fields.
I want to modify the query so that it is based on certain filters the user applies (which will be placed in the URL).
I can't get the query to work in the web application, but if I copy the query and execute it directly within PHPMyAdmin, it works fine.
$vesselFilter = $_GET['vesselFilter'];
$vesselArray = explode(',', $vesselFilter);
$arrayCount = count($vesselArray);
$sqlExtend = ' status = 1 AND';
foreach ($vesselArray as $value) {
$i = $i + 1;
$sqlExtend .= " vesselID = '$value'";
if ($i < $arrayCount){
$sqlExtend .= " OR";
}
}
$newQuery = "SELECT * FROM voyage_list WHERE" . $sqlExtend;
echo $newQuery;
$query = $db->query($newQuery)->fetchAll();
I appreciate the above is pretty messy, but it's just so I can try and figure out how to get the query to work.
Any help would be greatly appreciated!
Thanks
That query probably doesn't return what you think it does. AND takes precedence over OR, so it will return the first vessel in the list if the status is 1, and also any other vessel in the list, regardless of status.
You'd do better to create a query with an IN clause like this:
SELECT * FROM voyage_list WHERE status = 1 AND vesselID IN(8,9,10)
Here's some code to do just that:
$vesselFilter = $_GET['vesselFilter'];
// Validate data. Since we're expecting a string containing only integers and commas, reject anything else
// This throws out bad data and also protects against SQL injection.
if (preg_match('/[^0-9,]/', $vesselFilter)) {
echo "Bad data in input";
exit;
}
// filter out any empty entries.
$vesselArray = array_filter(explode(',', $vesselFilter));
// Now create the WHERE clause using IN
$sqlExtend = 'status = 1 AND vesselID IN ('.join(',', $vesselArray).')';
$newQuery = "SELECT * FROM voyage_list WHERE " . $sqlExtend;
echo $newQuery;
$query = $db->query($newQuery)->fetchAll();
var_dump($query);
In the form, none of the inputs are mandatory. So, I want to have a dynamic "where" clause inside the wpdb query.
Presently this is the query:
$data = $wpdb->get_results($wpdb->prepare("SELECT * FROM
`wp_gj73yj2g8h_hills_school_data` where
`school_zipcode` = %d AND `school_type` = %s AND `school_rating` = %s
;",$selectedZip,$selectedType,$selectedRating));
if a user enters only school_zipcode then the where clause should have only "school_zipcode" column.
Same way for other combinations.
I would not make things complicated with dynamic where clauses... I would write PHP code which creates the query. For example...
NOTE!! THIS CODE IS NOT TESTED ON SERVER, IT'S JUST AN IDEA HOW TO SOLVE THE PROBLEM!
<?php
$where_query = array();
// Make sure to escape $_POST
if (!empty($_POST['school_zipcode')) {
$where_query[] = "school_zipcode='" . $_POST['school_zipcode'] . "'";
}
// Make sure to escape $_POST
if (!empty($_POST['school_type')) {
$where_query[] = "school_type='" . $_POST['school_type'] . "'";
}
// Should result in WHERE school_zipcode='123' AND school_type='text'
$where_query_text = " WHERE " . implode(' AND ', $where_query);
$data = $wpdb->get_results($wpdb->prepare("SELECT * FROM `wp_gj73yj2g8h_hills_school_data` " . $where_query_text . ";"));
I'm trying to run a SQL query, and it is working correctly in phpMyAdmin, but whe running it in PHP, the query comes back very wonky. The following query yields two different results:
SELECT `stock_ticker`, `stock_simpleName`, `stock_logo`
FROM `stocks`
WHERE stock_simpleName REGEXP'^c'
I get the following results in phpMyAdmin (Which is correct):
stock_simpleName
----------------------
Coca-Cola
Campbell's
ConAgra Foods
However, in PHP it comes out really weird:
stock_simpleName
-----------------------
Coca-Cola
MasterCard
Campbell's
Microsoft
The Walt Disney Company
PepsiCo
The Hershey Company
Proctor & Gamble
ConAgra Foods
...etc...
Why is this happening? This doesn't make any sense. Is it due to a server setting in PHP or some form of encoding or whatnot?
EDIT:
Here is my PHP Code:
The sub-model class (the creator of the pieces):
public function allOtherSearchResults($query, $dontQuery = null) {
$name = "stocks";
$where = "stock_simpleName REGEXP'^" . $query . "'";
$cols = array("stock_ticker", "stock_simpleName", "stock_logo");
$limit = 5;
return $this->select($name, $cols, $where, $limit);
}
The main-model class (this runs the query):
public function select($tableName, $columns, $where = null, $limit = null) {
global $purifier;
// Make columns SQL friendly
$cols = "`";
$cols .= implode("`, `", $columns);
$cols .= "`";
$table = "`" . $tableName . "`";
if (!empty($where)) {
$where = " WHERE " . $where;
}
// Check limit
if (!empty($limit)) {
$limit = " LIMIT $limit";
}
// SQL CODE
$sql = "SELECT " . $cols . " FROM " . $table . $where . $limit;
// SQL DEBUGGING IF CODE RETURNS BOOLEAN ERROR
echo $sql . "<br>";
$query = $this->conn->query($sql);
// Store the value in a variable called table with an array of that table's name followed by it's values
// EX: $model->table["bands"]["band_name"]
//
// Accessible by the individual page/directory's controller's
while($row = $query->fetch_assoc()){
// Store values as $model->table["tableName"]["columnName"]["index (usually 0)"]
foreach ($row as $key => $val) {
$this->data[$tableName][$key][] = $row[$key];
}
}
// Loop through results to clean them
// Foreach loops through each column
// Make sure the table isn't empty (i.e. login returns an error)
if (!empty($this->data[$tableName])) {
foreach ($this->data[$tableName] as $key => $tableArray) {
// For loop goes through each value in a certain row
for ($i = 0; $i < count($tableArray); $i++) {
// Convert from data variable to table after HTML PURIFIER
$this->table[$tableName][$key][$i] = $purifier->purify($tableArray[$i]);
}
}
}
// Declare the array after loop has finished for use in view
$this->table;
if (!empty($this->table)) {
return true;
}
}
And it gives me the same SQL output as above. I am not sure if there is a different interpretation of certain characters in PHP versus the standard MySQL in phpMyAdmin. Has anyone even had this problem before?
I'm guessing, that there is a problem wiht ^ character.
Try to set proper connection & result encoding, eq.
$this->conn->query("MYSQL SET NAMES utf8");
$this->conn->query("MYSQL SET CHARACTER SET utf8");
Also, check if your php script file is saved in UTF-8 encoding.
Moreover, you should consider of using prepared statement (even to prevent SQL Injection):
$this->conn->prepare("SELECT * FROM `stocks` WHERE `stock_simpleName` REGEXP ?");
$this->conn->bind_param("s", "^c");
$this->conn->execute();
$query = $this->conn->get_result();
I have a MYSQL full text search, matching against items in my database, which works great.
$select = "SELECT * from menu WHERE MATCH(item) AGAINST('$this->food') ";
From there I refine the query dependent on what the user wants to filter by. I have 2 filters, vegetarian and breadtype
if(isset($this->vegetarian)) {
echo $select .= " AND vegetarian='$this->vegetarian'";
}
if(isset($this->bread)) {
echo $select .= " AND bread='$this->bread'";
}
Which appends the fulltext statement, now this works perfectly, although my issue is that
if the user doesn't search anything (empty string) I want it to returns all results in the database.
if(empty($this->food)) { $select = "SELECT * from menu"; }
Which now means I can't append the $select statement with the above if statements, and would have to use a WHERE statement instead - but that would mean adding 2 extra if statements to compensate for that. Is there anyway for MYSQL to do it instead.
if(isset($this->vegetarian) && empty($this->food)) {
echo $select .= " WHERE vegetarian=$this->vegetarian";
}
You can simply use WHERE 1=1 and then append the rest. MySQL will simply ignore this part if there's no additional ANDs or ORs.
$select = "SELECT * from menu WHERE MATCH(item) AGAINST('$this->food') ";
if(empty($this->food)) {
$select = "SELECT * from menu WHERE 1=1"; // if food is empty we overwrite the $select variable
} else {
if(isset($this->vegetarian)) {
$select .= " AND vegetarian='$this->vegetarian'";
}
if(isset($this->bread)) {
$select .= " AND bread='$this->bread'";
}
}
Or am i missing something ?
I have a form that is going to be used to search through a table of support tickets.
the user can search from a few difficult optional fields.
Date (to/from)
Ticket Status
Engineer
Ticket Contact
I'm wondering what is the best way to deal with optional search filters. So I have a query that takes in parameters from the user. So if the user searches using both the from and to dates then the query would want to include BETWEEN. So do I have to write a different query for if the user searches for only from. or another query when the user has not added any date parameters? Then what if the status dropdown is blank? Is that another query?
Any help to clear this up would be great!
Jonesy
Build your query in parts. Start with whatever is constant in your query, and add on more SQL depending on what extra conditions:
$query = "SELECT ...
FROM ...
WHERE [where conditions that are always going to be present]";
if (isset($_POST['date_from']) && isset($_POST['date_to']))
{
$query .= ... // query code for dealing with dates
}
if (isset($_POST['status']))
{
$query .= ... // deal with status
}
// etc.
// Once you have your query fully built, execute it
$result_set = mysql_query($query);
This code is obviously just a skeleton, but that's how I would construct my query.
Hard to say without knowing what sort of DB abstraction you're using, but assuming you're hand-writing the SQL, it's fairly simple, just build up sections of your where clause individually for each variable. (Assuming here that your vars are already escaped/quoted.)
$where_clause = array();
if (!empty($date_from)) {
$where_clause[] = "table.date >= $date_from";
}
if (!empty($date_to)) {
$where_clause[] = "table.date <= $date_to";
}
if (!empty($status)) {
$where_clause[] = "status = $status";
}
$query = 'select * from table where ' . join(' and ', $where_clause);
This is an elegant way that I use alot and wish will help you too:
$q = 'SELECT * FROM Users';
$buildQ = array();
if (empty($idOrName) === false) {
$buildQ[] = '(userid = "' . $idOrName . '" OR username LIKE "%' . $idOrName. '%")';
}
if (empty($nickname) === false) {
$buildQ[] = 'nickname="' . $nickname . '"';
}
if (empty($salary) === false) {
$buildQ[] = 'salary="' . $salary . '"';
}
// ... any other criterias like above if statements
if (count($buildQ) === 1) {
$q .= ' WHERE ' . $buildQ[0];
} else if (count($buildQ) > 1) {
$count = 0;
foreach ($buildQ as $query) {
if ($count === 0) {
$q .= ' WHERE ' . $query;
} else {
$q .= ' AND ' . $query;
}
$count++;
}
}
I think it would be better if You generate query dynamically at runtime based on which fields are filled. So You could make some helper which appends specific query fragments if only one date is passed and the other one is null, or when both are passed and so on.