Can you check to see if there will be any results - mysql

I'm displaying Spotlight post on search page.
When a user enters a keyword to search for a post I like to bring a Spotlight post using that keyword. If there is no post with that keyword then I would want to just bring any Spotlight post from database.
My questions is, can I check this in a MySQL query to see if they will be any results with this keyword, if not then ignore this keyword?
My query
SELECT id, title, desc
FROM post
WHERE isActive = 1
AND title = 'keyword'
but if I'm getting 0 results with this query I would like to ignore this and run this instead
SELECT id, title, desc
FROM post
WHERE isActive = 1

desc is MySQL's reserved keyword (used for ordering results in a *desc*ending order). To use it as a column name, you need to put it in backticks
$select = " SELECT id, title, `desc` ";
$from = ' FROM post';
$where = 'WHERE isActive=1 and title="%$keywords%"';
$sql = $select.$from.$where;

This is what I have done to solve my problem.
$select = " SELECT id, title, desc ";
$from = ' FROM post';
$where = 'WHERE isActive=1 and title="%$keywords%"';
$sql = $select.$from.$where;
if no result then overwrite
$where = 'WHERE isActive=1';
$sql = $select.$from.$where;
If anyone know anyother way please let me know.

Related

Converting MYSQL to Codeigniter

I am trying to convert a MYSQL query to codeigniter and going no wheres real fast. I am trying to convert this query
$conn->prepare("SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = (SELECT MAX(mix_number) FROM podcasts) order by track asc");
This is in my model:
//$where = '(SELECT MAX(mix_number)from podcasts)';
$this->db->select('id,song,artist,album,track,mix_name,date, link');
//$this->db->where('mix_number', '(SELECT MAX(mix_number)from podcasts)');
$this->db->order_by('track', 'asc');
$query = $this->db->get('podcasts');
return $query->result();
My problem area is in the where statement. When I comment out the where statement I get the data. Obviously not in the manner I want it.
I am doing it this way becuase my next query(s) will be
("SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = **(SELECT MAX(mix_number) FROM podcasts) - 1** order by track asc")
And on down to (SELECT MAX(mix_number) FROM podcasts) - 3
Any thoughts on the proper way of writing the where statement? Thank you for yout time.
Set the third argument of where() to false to prevent CI from altering the string you pass in to the second argument, then you can do the subquery:
return $this->db
->select('id,song,artist,album,track,mix_name,date, link')
->where('mix_number', '(SELECT MAX(mix_number) from podcasts)', false)
->order_by('track', 'asc')
->get('podcasts')
->result();
https://www.codeigniter.com/userguide2/database/active_record.html$this->db->where() accepts an optional third parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks.
For me this produces the following query:
SELECT `id`, `song`, `artist`, `album`, `track`, `mix_name`, `date`, `link`
FROM (`podcasts`)
WHERE mix_number = (SELECT MAX(mix_number) from podcasts) ORDER BY `track` asc
If you are not too particular about using CodeIgniter's Active Record syntax, you can simply use your query as is:
$sql = "SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = (SELECT MAX(mix_number) FROM podcasts) order by track asc";
$this->db->query($sql);
and then use $query->result() to get your results.

Use Multiple keywords with mysql Like

I want to write mysql query to display all records if text field value = "All" or else display records similar to keyword value. I have written code below to just to give an idea.
if (keyword = 'All' )
select * from ItemMain
else if (keyword like %itemname%)
select * from ItemMain
Ok, assuming PHP as the front-end language you can put it all in one query like this (forgive the curly braces; I'm never sure when they're needed or not so I tend to over-use them):
$query = <<< ENDSQL
SELECT *
FROM ItemMain
WHERE ('{$keyword}' = 'All') OR (your_textfield like '%{$keyword}%')
ENDSQL;
... execute the query
But really I'd go with the suggestion from #cjg and use two different queries:
$query = "";
if ($keyword == 'All') {
$query = "SELECT * FROM ItemMain";
} else {
$query = "SELECT * FROM ItemMain WHERE your_textfield LIKE '%{$keyword}%'";
}
... execute the query
If itemname is your column name, and your search string parameter replaces the ? in your code. Then your statement should look something like this if you are searching for all itemnames containing your search string:
SELECT *
FROM ItemMain
WHERE ? = 'All' OR itemname LIKE '%?%'
Or this if you are looking for an exact match:
SELECT *
FROM ItemMain
WHERE ? = 'All' OR itemname = ?

MySQL order by IN array

I have a MySQL script like this: SELECT id, name FROM users WHERE id IN (6,4,34)
The sequence in the IN(...) array is very important. Is it possible to get them in the given sequence?
You can use the MySQL FIELD function to keep it compact;
SELECT id, name
FROM users
WHERE id IN (6, 4, 34)
ORDER BY FIELD(id, 6, 4, 34);
Try
SELECT id, name FROM users WHERE id IN (6,4,34) order by FIELD(id,6,4,34)
You can use any expression in the ORDER BY clause, including a 'CASE':
ORDER BY CASE id
WHEN 6 THEN 1
WHEN 4 THEN 2
WHEN 34 THEN 3
END ASC
If your list comes from the application programming layer, you might build this with the following (PHP here):
$sortVal = 1;
foreach($ids as $id_val) {
$cases[] = sprintf('WHEN %i THEN %i', $id_val, $sortVal++);
}
$order_by = 'ORDER BY CASE id ' . implode($cases) . ' END ASC';
However, I'll mention that Joachim's answer is quite elegant :-)
A complete example based on Chris Trahey answer.
$ids = array("table1", "table2", "table3");
$sortVal = 1;
foreach ($ids as $id_val) {
$cases[] = sprintf("WHEN '%s' THEN %u ", $id_val, $sortVal++);
}
$order_by = 'ORDER BY CASE `tableName` ' . implode($cases) . ' END ASC';
$result = mysqli_query( $con, "
SELECT DISTINCT tableName
FROM `table`
$order_by");

Is there a more efficient way to write this MySQL query?

I'm a newbie to mysql, I managed to scrape this together to get the result I wanted. Can it be coded better? Are there any security risks? Its being output in php.
$qwe = $product->virtuemart_product_id;
$id = mysql_real_escape_string($qwe);
$result = mysql_query('SELECT * FROM virtuemart_product_medias where virtuemart_product_id = ' . $id . ' LIMIT 1');
$row = mysql_fetch_assoc($result);
$matched = $row['virtuemart_media_id'];
$result2 = mysql_query('SELECT * FROM virtuemart_medias where virtuemart_media_id = ' . $matched . ' LIMIT 1');
$row2 = mysql_fetch_assoc($result2);
$matched2 = $row2['file_url_thumb'];
echo $matched2;
I don't know whether or not there is a security hole in the specific code you provided - that depends on what other validation exists elsewhere in your program, and what you consider to be a security hole. But the way you are coding means that there definitely could be security holes. Let's look at your first query:
$id = mysql_real_escape_string($qwe);
$result = mysql_query('SELECT *
FROM virtuemart_product_medias
WHERE virtuemart_product_id = ' . $id . ' LIMIT 1');
Imagine if $qwe is the string 0 OR 1=1 --. The mysql_real_escape_string only escapes certain characters such as quotes and backslashes.
mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \\, ', " and \x1a.
The string 0 OR 1=1 -- that I mentioned above does not contain any of these characters so it will not be affected at all by mysql_real_escape_string. After you substitute in the value of $id, the resulting SQL query will look something like this:
SELECT *
FROM virtuemart_product_medias
WHERE virtuemart_product_id = 0 OR 1=1 -- LIMIT 1
As you can see, this will return all rows.
Long story short: Use PDO and parameterized queries.
Related
How can I prevent SQL injection in PHP?
Firstly, never use the mysql_* functions. They are deprecated and relying on them is highly discouraged. Use either MySQLi or PDO
The above query could be rewritten as
SELECT file_url_thumb FROM virtuemart_medias where virtuemart_media_id = (SELECT virtuemart_media_id FROM virtuemart_product_medias where virtuemart_product_id = ' . $id . ' LIMIT 1) LIMIT 1
Never do a SELECT *. Include only those fields in your query which you need in your code.
Use one query instead of two, and select only the fields you're using, like so:
SELECT `file_url_thumb` FROM virtuemart_medias where virtuemart_media_id = (SELECT `virtuemart_media_id` FROM virtuemart_product_medias where virtuemart_product_id = ' . $id . ' LIMIT 1) LIMIT 1
You can always use a join;
SELECT a.virtuemart_media_id, b.file_url_thumb
FROM virtuemart_product_medias a
LEFT JOIN virtuemart_medias b
ON a.virtuemart_media_id = b.virtuemart_media_id
WHERE virtuemart_product_id = $id
LIMIT 1
That'll always get you the virtuemart_media_id and, if it exists file_url_thumb.
Your query has a problem also, mysql_real_escape_string only escapes strings, since you're not quoting the $id in the query, it won't be handled as a string and the escaping will not help you. As other replies point out, you should really be using mysqli or PDO.
How about this:
SELECT a.file_url_thumb
FROM virtuemart_medias a
LEFT JOIN virtuemart_product_medias b on a.virtuemart_media_id=b.irtuemart_media_id
WHERE a.virtuemart_product_id=' . $id . ' LIMIT 1

how to translate a very long mysql query with select and join to zend framework 1.11 model

I have this mysql query:
SELECT
freeAnswers.*,
(SELECT `districtCode`
FROM `geodatas`
WHERE `zipCode` = clients.zipCode
GROUP BY `zipCode`
LIMIT 0, 1) as districtCode,
clients.zipCode,
clients.gender,
clients.startAge,
clients.endAge,
clients.mail,
clients.facebook,
surveys.customerId,
surveys.activityId,
surveys.name as surveyName,
customers.companyName,
activities.name as activityName
FROM freeAnswers,
clients,
surveys,
customers,
activities
WHERE freeAnswers.surveyId = surveys.id
AND surveys.customerId = customers.id
AND activities.id = surveys.activityId
AND clients.id = freeAnswers.clientId
AND customers.id = 1
ORDER BY activityName asc
LIMIT 0, 10
the query is correct on my mysql server but when I try to use it in Zend Framework 1.11 model
I get this error: Mysqli prepare error: Operand should contain 1 column(s)
Please, could anyone help me to make it run well?
Best Regards,
Elaidon
Here is some code that should work. Zend_Db_Select doesn't really provide a way to select from multiple tables in the FROM clause without using a JOIN so this feels a bit hackish to me in regards to one small part of the query. Your best bet will probably be to rewrite the query using JOINs where appropriate.
$subselect = $db->select()
->from('geodatas', 'districtCode')
->where('zipCode = clients.zipCode')
->group('zipCode')
->limit(1, 0);
$from = $db->quoteIdentifier('freeAnswers') . ', ' .
$db->quoteIdentifier('clients') . ', ' .
$db->quoteIdentifier('surveys') . ', ' .
$db->quoteIdentifier('customers') . ', ' .
$db->quoteIdentifier('activities');
$select = $db->select()
->from(array('activities' => new Zend_Db_Expr($from)),
array('freeanswers.*',
'districtCode' =>
new Zend_Db_Expr('(' . $subselect . ')'),
'clients.zipCode', 'clients.gender', 'clients.startAge',
'clients.endAge', 'clients.mail', 'clients.facebook',
'clients.customerId', 'clients.activityId',
'surveyName' => 'surveys.name', 'customers.companyName',
'activityName' => 'activities.name'))
->where('freeAnswers.surveyId = surveys.id')
->where('surveys.customerId = customers.id')
->where('activities.id = surveys.activityId')
->where('clients.id = freeAnswers.clientId')
->where('customers.id = ?', 1)
->order('activityName ASC')
->limit(10, 0);
The only reason I say it is hackish is because of the line:
->from(array('activities' => new Zend_Db_Expr($from)),
Since from() really only works with one table, I create a Zend_Db_Expr and specify the correlation as the last table name in the expression. If you don't pass a Zend_Db_Expr, it will either quote your comma separated table name incorrectly, or if you pass an array of table names, it just uses the first. When you pass a Zend_Db_Expr with no name, it defaults to use AS t which also doesn't work in your case. That is why I put it as is.
That returns the exact SQL you provided except for the last thing mentioned. Here is actually what it returns:
SELECT
`freeanswers`.*,
(SELECT `geodatas`.`districtCode`
FROM `geodatas`
WHERE (zipCode = clients.zipCode)
GROUP BY `zipCode`
LIMIT 1) AS `districtCode`,
`clients`.`zipCode`,
`clients`.`gender`,
`clients`.`startAge`,
`clients`.`endAge`,
`clients`.`mail`,
`clients`.`facebook`,
`clients`.`customerId`,
`clients`.`activityId`,
`surveys`.`name` AS `surveyName`,
`customers`.`companyName`,
`activities`.`name` AS `activityName`
FROM `freeAnswers`,
`clients`,
`surveys`,
`customers`,
`activities` AS `activities`
WHERE (freeAnswers.surveyId = surveys.id)
AND (surveys.customerId = customers.id)
AND (activities.id = surveys.activityId)
AND (clients.id = freeAnswers.clientId)
AND (customers.id = 1)
ORDER BY `activityName` ASC
LIMIT 10
So that will work but eventually you will want to rewrite it using JOIN instead of specifying most of the WHERE clauses.
When dealing with subqueries and Zend_Db_Select, I find it easy to write each subquery as their own queries before writing the final query, and just insert the subqueries where they need to go and Zend_Db handles the rest.
Hope that helps.