我是php和MySQL的新手,我在尝试解决这个问题时遇到了问题。
我有这个查询
SELECT * FROM comments, supps
WHERE supps.tutorialid = comments.tutorialid
AND category='1'
ORDER BY $orderby $sort
LIMIT $startrow, $limit
哪个工作正常,但问题是我还要在评论表中包含列的AVG,而我似乎无法使用此查询。任何人都可以帮助我
答案 0 :(得分:1)
要使用聚合函数,您需要使用'GROUP BY'子句。通常在'ORDER BY'之前。注意:如果要使用group by,则需要在SELECT子句中定义属性,否则事情会变得有点粘。
例如:
SELECT id, avg(value) FROM comments c
INNER JOIN supps s
on c.tutorialid = s.tutorialid
WHERE category = 1
GROUP BY id
etc...
答案 1 :(得分:0)
是的,有可能。请查看SQL Wikibooks tutorial上的示例,其中列出了在两个不同表格中使用AVG()
的以下示例:
/* Without INNER JOIN */
SELECT AVG(Price), Manufacturers.Name
FROM Products, Manufacturers
WHERE Products.Manufacturer = Manufacturers.Code
GROUP BY Manufacturers.Name;
/* With INNER JOIN */
SELECT AVG(Price), Manufacturers.Name
FROM Products INNER JOIN Manufacturers
ON Products.Manufacturer = Manufacturers.Code
GROUP BY Manufacturers.Name;
答案 2 :(得分:0)
隐式SQL加入被认为是有害的
首先请不要使用隐式连接语法。它属于1989年,请把它埋葬在那里。
看起来你有一个SQL注入泄漏
如果你使用php并且你没有将注入的变量放在单引号中'
mysql_real_escape_string()
将不起作用!
最后,您要在查询中注入列名。这样做时mysql_real_escape_string()
不会保护您,也不会使用PDO或其他任何东西。您需要针对预先提交的白名单检查列名称,以免成为SQL注入攻击的受害者。 See here for more info:
如果将$ vars注入限制子句mysql_real_escape_string()
不起作用,因为MySQL不会将这些视为值,而是作为文字,您需要将它们转换为整数以使其安全。
将查询重写到PHP代码中并在其前面执行:
//stricly speaking not needed here, because we only accept integers
//but I would use them anyway, just in case you change the query and the
//role of these vars change.
$limit = mysql_real_escape_string($_POST['limit']);
$startrow = mysql_real_escape_string($_POST['startrow']);
//Check injected column, table and database names against a whitelist!
$allowed_columns = array('column1', 'column2');
$orderby = $_POST['orderby'];
$sort = $_POST['sort'];
if !(in_array($orderby, $allowed_columns)) {die ("no way Jose");}
if !(in_array($sort, $allowed_columns)) {die ("no way Jose");}
//Make 100% sure injected limit parameters are integers.
if !((int) $startrow == $startrow) {die ("no way Jose");}
if !((int) $limit == $limit) {die ("no way Jose");}
$query = "SELECT s.*, c.* ,AVG(c.field1) as average
FROM comments c
INNER JOIN supps s ON (s.tutorialid = c.tutorialid)
WHERE category = '1'
GROUP BY s.id
ORDER BY `$orderby`, `$sort` //surround injected column names with `
LIMIT '$startrow', '$limit' ";
SQL注入保护概述
1.始终使用mysql_real_escape_string()
来转义来自外部的数据。 (甚至更好地使用PDO)
2.使用'
单引号在您的查询中为Surround注入$ var值;如果您没有使用mysql_real_escape_string()
转义不工作。
3.根据白名单检查注入的表,列和数据库名称
4.环绕$ vars用于反引号`
中的表,列和数据库名称;这不是一个安全措施,但如果你使用保留字,(颤抖)字段名称和空格,你的查询将失败,反引号修复此问题。
5.测试你的限制条款中注入$ vars是否为整数。
没有做任何这些事情,你的服务器将被计划!。
回到你的问题
我的手指受伤了,但其他人也很友好地回答了你的问题。
<强>链接强>
一般的SQL注入:How does the SQL injection from the "Bobby Tables" XKCD comic work?
注入列名称的白名单:How to prevent SQL injection with dynamic tablenames?