I have the following code that has stopped working since MySQL 5.7 upgrade:
$myDB->contentArray = $myDB->executeAssoc("
SELECT DISTINCT(YEAR(displayDate)) as year FROM
`inlineItemData_standardList`
WHERE `inlineItemGroupID` = $inlineItemGroupID
ORDER BY `displayDate` desc");
Could anyone show me how I would replace the DISTINCT part in this? I have searched around and can find others with the same issue but without a lot of PHP knowledge, I can't seem to implement the correct thing. I tried using GROUP BY 'YEAR(displayDate)) as year' but can't seem to get it to work. Thanks in advance.
The ORDER BY clause of a SELECT DISTINCT query must be consistent with the SELECT clause.
So:
SELECT DISTINCT YEAR(displayDate) as year
FROM inlineItemData_standardList
WHERE inlineItemGroupID = ?
ORDER BY YEAR(displayDate) DESC
-- Or: ORDER BY `year` DESC
Side note: use prepared statements! Do not concatenate variables in the query string: this is both inefficient and unsafe. Recommended reading: How can I prevent SQL injection in PHP?
Related
How can I change the order by time either in MySQL or in the While Loop?
I have a query like
`"SELECT `start-time` from `table_name`"`
and my start-time will be in format 02:00pm, 02:00am, 05:00am, in likewise. If that's just number without am/pm I can use order by.
Or, if the above way not possible, can I use PHP to order the start time in while loop?
I am using the following way to retrieve the data
$doquery = mysql_query("SELECT `start-time` FROM `table_name`");
while($fetch_query = mysql_fetch_array($doquery)){
echo $fetch_query['start-time'];
}
Thanks
Are you storing your times as TIMESTAMP in MySQL? If not, you should be. The most efficient way to sort the results is going to be by adding an ORDER BY clause to your SQL statement. For instance, to sort so that the most recent times occur first in the result set, try this:
SELECT `start-time` FROM `table_name` ORDER BY `start-time` DESC;
To order so that the most recent times occur last in the result set, change the query to:
SELECT `start-time` FROM `table_name` ORDER BY `start-time` ASC;
The other thing that I would encourage you to explore is PDO. All of the mysql_* PHP functions are deprecated. Prepared queries are a lot more secure and flexible. There are a lot of tutorials out there... this one looks alright: http://www.phpro.org/tutorials/Introduction-to-PHP-PDO.html Anyway hope that helps. Happy coding.
If it is simply a string you could use STR_TO_DATE or CASE WHEN, like:
Using STR_TO_DATE
SELECT `start-time` from `table_name`
ORDER BY STR_TO_DATE(start-time,'%h.%i%p')
Using CASE
SELECT `start-time` from `table_name`
ORDER BY
CASE WHEN start-time LIKE '%am%'
THEN 0
ELSE 1
END, start-time
Bu I agree with others you could probably store this as TIMESTAMP and use mySQLi or PDO for your database handling in php.
im making a simple admin module to query the database to show the results. Im using this query via php:
SELECT
*
FROM myTable
WHERE id in(SELECT
id_registro
FROM myOtherTable
where id_forma='".$id_club."' and fecha_visita Like '%".$hoy."%'
)
order by id DESC
The result shows, however, it takes very long like 2 minutes..Anyone can help me out?
Thanks!
Without seeing your database, it is hard to find a way to make it faster.
Maybe you can try to turn your WHERE IN to INNER JOIN. To something like this
SELECT * FROM myTable INNER JOIN myOtherTable
ON (myTable.id = myOtherTable.id_registro)
WHERE myOtherTable.id_forma = '$id_club'
AND myOtherTable.fecha_visita LIKE '%$hoy%'
ORDER BY myTable.id DESC
Noted that you should sanitize your variable before putting it SQL query or using PDO prepare statement.
Sub Queries takes always time, so its better to ignore them as much as possible.
Try to optimize your query by checking its cardinality,possible keys getting implemented by DESC or EXPLAIN , and if necessary use FORCE INDEX over possible keys.
and I guess you can modify your query as:
SELECT
*
FROM myTable
inner join id_registro
on (id = id_forma )
where
id_forma='".$id_club."' and fecha_visita Like '%".$hoy."%'
order by id DESC
LIKE in mysql may take a long time ,with or without index.
Do u have a very large DB?
I am attempting to get the latest result from two different tables (forum_posts and forum_replies)...I'm not sure of the best way of doing this, so I am attempting to use a UNION ALL to do this...
I did a test result to try to make sure the code worked; however, it doesn't appear to be working correctly. Even though there is data matching the requirements in the database, it is echoing out No Posts. So something about the query isn't processing correctly.
$latest = "(SELECT * FROM forum_posts WHERE post_subcat = '1' ORDER BY post_id) UNION ALL (SELECT * FROM forum_replies WHERE reply_subcat = '1' ORDER BY reply_id) LIMIT 1";
if(!$getlatest = $con->query($latest)){ echo 'No Posts'; }
if($getlatest = $con->query($latest)){ echo 'Post'; }
I'm new to unions, so I have a few questions.
1) I've seen a union work in mysql, but do they also work in mysqli?
2) Are there any restrictions to using unions (union/union all/ etc.)? Do columns have to be the same for comparison?
3) Did I do something wrong in my above code? I am probably overlooking something minor just from working too long, just not sure at this point.
You generally have to (overly flexible DBMS' notwithstanding) have the same column types and identifiers in the two queries you're unioning together and the order by applies to the final result set, not the interim one (although you can use sub-queries to order interim results if needed, not something that seems to be required in this specific case).
So something like this:
SELECT post_id as id,
post_date as dt
FROM forum_posts
WHERE post_subcat = '1'
UNION ALL
SELECT reply_id as id,
reply_date as dt
FROM forum_replies
WHERE reply_subcat = '1'
ORDER BY dt DESC
LIMIT 1
In terms of the mysql/mysqli distinction, that shouldn't matter, both methods end up doing the relevant work at the server side.
You usually use union all if you know there's no chance of duplicates so as to avoid any unnecessary sorting for the duplicate removal. Otherwise, use union if you do want duplicates removed.
As to whether you have a problem with your code, if the query function returns false, you should be checking the error functions for the specific failure reason. See mysqli_error for details.
And keep in mind it doesn't return false if there were no posts, it only returns false if there was an error. If the query worked and there were no posts, you'd end up with an empty result set.
1) I've seen a union work in mysql, but do they also work in mysqli?
It should work on mysqli also because mysqli is another extension to access Mysql 4.1 onwards
2) Are there any restrictions to using unions (union/union all/ etc.)? Do columns have to be the same for comparison?
Yes. All the columns from two tables needs to be of same data type and the no of columns also should match. I suspect this is your problem.
3) Did I do something wrong in my above code? I am probably overlooking something minor just from working too long, just not sure at this point.
If I've understood what you're after correctly, I believe the following will work:
SELECT * FROM forum_posts fp WHERE fp.post_subcat = (SELECT MAX(fp1.post_subcat) FROM forum_posts fp1)
UNION
SELECT * FROM forum_replies fr WHERE fr.reply_subcat = (SELECT MAX(fp.post_subcat) FROM forum_posts fp)
Did I do something wrong in my above code?
Sure.
First, you are running your query two times.
Second, you are checking wrong value to see if there were any posts. http://php.net/mysqli_query
Im writing a module for an e-commerce platform that modifies the ORDER BY clause of an MySQL query.
I only have access to anything after the ORDER BY statment.
Im wanting to execute ORDER BY statements on calculated columns as such.
" ORDER BY (SELECT (shop_product.price - shop_product.sale_price) as pSavings) ASC "
Although i have no idea how i would go about this or if its even possible as i dont have access to the SELECT statement to generate the calculated columns?
If you mean this (then it is possible):
ORDER BY (shop_product.price - shop_product.sale_price) ASC
You can Try with this.
SELECT (shop_product.price - shop_product.sale_price) as pSavings ORDER BY pSavings ASC;
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 2 years ago.
The sql injection will work only when my query looks like below sample
SELECT * FROM login WHERE id = $my_id_va;
Assume if my query is
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
Than I will get following error
#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'order by id desc' at line 1
So, this 1 or 1=1; SHOW TABLES will not work, correct?
My site was hacked successively many times.
I want one quick answer: When my query looks like the following one, what ways or which types of query can they use to hack my site?
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
What are the ways to execute the show table in the following query
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
I am also using escaping function to handle the query string values, like mysql_real_escape_string($my_id_va). Yes, obviously this for single related hack, but not sure.
Added some more
SELECT EventActuallyCharged, EventDate FROM tblevent WHERE EventDate between '2011-07-21 or 1=1; SHOW TABLES --' and '2011-07-31' ORDER BY EventDate DESC
but show table not worked
If you are using PHP5, use parametarized query, use PDO.
Int cast
If id is a number, you can int-cast your variable as well. Integers are safe to use:
$x = (int)$yourInputVar;
$s = "select * from Table where id = $x";
mysql_real_escape_string
If you want to pass a string, you can, and should, use mysql_real_escape_string, but this function escapes only those characters that are inside the string. You will still need to add quotes around the string, so:
$x = mysql_real_escape_string('hello');
$s = "select * from Table where id = $x";
.. will result in the query: select * from Table where id = hello. This is obiously not a valid query, since hello should be in quotes.
Change the query to:
$x = mysql_real_escape_string('hello');
$s = "select * from Table where id = '$x'";
.. and everything works fine. You add the quotes around, and mysql_real_escape_string takes care of special characters inside the string, if any.
Parameters
Another solution is to use parameterized queries. This can by done using MySQLi or PDO. The advantage is that you only tell your database where a variable should be inserted, and the database takes care of the escaping yourself.
It also may add a performance benefit, because these queries could be cached without their parameters, make a more efficient use of the query cache. This doesn't really work yet in current versions of MySQL, though.
You are right that 1 or 1=1; SHOW TABLES will give a syntax error but this will work:
1 or 1=1 --
The -- comments out the rest of the query.
In your case the value is an integer so instead of using mysql_real_escape_string you can use intval.
If you set $my_id_va to:
1 or 1=1; SHOW TABLES --
The -- will comment out the rest of the command, effectively terminating it.
I'm not sure what effect mysql_real_escape_string will have on the query. What you should be doing is parameterized queries.
1. First query somehow secured
$sql = sprintf('SELECT * FROM login WHERE id = %d ORDER BY id DESC', mysql_real_escape_string($my_id_va));
2. Second query somehow secured
$sql = sprintf("SELECT EventActuallyCharged, EventDate FROM tblevent WHERE EventDate BETWEEN '%s' AND '%s' ORDER BY EventDate DESC",
mysql_real_escape_string($start_date),
mysql_real_escape_string($end_date));
Read the docs about sprintf if you don't understand it.
However, as others have said, it would be very very secure if you would use parameterized queries with a class such as PDO or MySQLi.