我试图调用一个存储过程来返回一组按特定顺序排序的结果(order by),这是我的存储过程:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `getReadReportsPagingFinal`(startIndex INTEGER, pageSize INTEGER, sortingCol VARCHAR(255), sortingDir VARCHAR(255))
BEGIN
SET @Query = "SELECT * FROM reports
WHERE 'new'=0
ORDER BY ?, ?
LIMIT ?, ?";
SET @a = sortingCol;
SET @b = sortingDir;
SET @c = startIndex;
SET @d = pageSize;
PREPARE stmt1 FROM @Query;
EXECUTE stmt1 USING @a, @b, @c, @d;
DEALLOCATE PREPARE stmt1;
END
我知道占位符不能用于列名:
对于大多数驱动程序,占位符不能用于任何元素 声明会阻止数据库服务器验证 语句并为其创建查询执行计划。
所以我试图将sortingCol和sortingDir连接到查询:
@Query = CONCAT(@Query, sortingCol);
给出了语法错误。
有更好的方法吗?目前,参数通过调用存储过程的PHP脚本传递。
答案 0 :(得分:1)
您不能将列放在LIMIT子句之后的末尾。您排序的列必须在ORDER BY子句中。但是你没错,你不能在列名中使用参数。
SET @Query = CONCAT("SELECT * FROM reports
WHERE 'new'=0
ORDER BY ", sortingCol, " ", sortingDir,
" LIMIT ?, ?");
小心地在这些字符串片段中放置SQL关键字周围的空格。您不希望最终得到ORDER BY column1 ASCLIMIT ? ?
。
另外请记住,在进行PREPARE之前,通过将过程参数插入到查询中,您将面临SQL注入的风险。如果有人欺骗您的应用程序传递sortedCol:1 UNION SELECT * FROM information_schema.columns --
在将这些字符串连接到SQL之前,您需要采取措施白名单这些字符串。当您处理动态列名或SQL关键字时,这是防止SQL注入漏洞的最佳防御。