在过程中将2个字符串作为查询加入

时间:2011-10-14 16:16:10

标签: mysql sql stored-procedures

如何根据收到的参数构建查询?我想添加到查询的末尾。

我尝试了类似的东西,但它不起作用:

DELIMITER $$
CREATE PROCEDURE `get_users`(IN sortstring TEXT)
BEGIN
PREPARE statement FROM
 "SELECT username, password FROM users ?";
SET @param = sortstring;
EXECUTE statement USING @param;
END$$

我会传递给sortstring,例如:

ORDER BY username DESC

我可以使用concat或其他东西更简单吗?

1 个答案:

答案 0 :(得分:2)

您需要解构sortstring并根据允许的术语白名单检查其所有部分。

请参阅以下伪代码。我还没有对它进行过全面的测试,但我们可以说这个想法非常重要。

DELIMITER $$

CREATE PROCEDURE `get_users`(IN sortstring TEXT)
BEGIN
  //check sortstring against a whitelist of allowed sortstrings
  DECLARE sortpart VARCHAR(255);
  DECLARE done BOOLEAN DEFAULT false;
  DECLARE allok BOOLEAN DEFAULT true; 
  DECLARE i INTEGER DEFAULT 1;

  WHILE ((NOT done) AND allOK) DO
    SET sortpart = SUBSTRING_INDEX(sortstring,',',i);
    SET i = i + 1;
    SET done = (sortpart IS NULL);
    IF NOT DONE THEN
      SELECT 1 INTO allok WHERE EXISTS 
        (SELECT 1 FROM whitelist 
         WHERE allowed_sort_claused = sortpart AND tablename = 'users');
    END IF
  END WHILE;
  IF allOK THEN     
    PREPARE statement FROM 
      CONCAT('SELECT username, passhashwithsalt FROM users ',sortstring);
    EXECUTE statement;
    DEALLOCATE PREPARE statement;
  ELSE SELECT 'error' as username, 'error' as passhashwithsalt;
  END IF; 

END$$

请参阅:How to prevent SQL injection with dynamic tablenames?

代码中的错误
您不能使用列名或SQL关键字作为参数。您只能将值用作参数。因此,您的查询永远不会通过准备 ?中的SELECT x FROM t1 ?将被SELECT x FROM t1 'ORDER BY field1, field2'取代,这是没有意义的。