mySQL创建一个未知数量值的INSERT存储过程

时间:2013-07-20 15:03:02

标签: php mysql stored-procedures mysqli sql-injection

在我的mySQL数据库中,我创建了一个API,用于使用存储过程从外部使用数据库。

我为这项任务设计了一个特殊用户,只有EXECUTE权限 - 以防止SQL注入。

我有一个用户id连接的表,我需要创建一个包含未知数量参数的过程 - 该过程应该将他收到的所有id插入到表中。

现在我正在使用PHP与mysqli,我正在创建我自己的查询 - 这是非常不安全的 - 它看起来像这样:

/**
 * Add new rows to the invited users tables
 * @param $invitingUser string the inviting user facebook's Id
 * @param $invitedUsers array the invited users facebook's Id
 */
function addInvitedUsers($invitingUser, $invitedUsers)
{
    //check if all the parameters are set
    if (isset($invitingUser) && isset($invitedUsers))
    {
        //create the basic query for insert
        $query = "Insert Into Invited_Users (Inviting_id,Invited_Id) Values ";
        //for each invited users - add it to the query
        foreach($invitedUsers as $invitedUser)
            $query . "('$invitingUser','$invitedUser') ";

        if ($this->queryDb($query));
            echo "added new invited users";
    }
    //if parameters are not set - message
    else
        echo "parameters can't be null";
}

我想创建一个能给我相同能力的程序..

我知道我不能将数组或未定义数量的参数发送到存储过程,但我确信在安全模式下我还有其他方式可以使用相同的能力。

1 个答案:

答案 0 :(得分:0)

没有简单的方法可以将多个值传递给MySql存储过程。最好的办法是传递逗号分隔的值字符串,然后将其拆分到SP中,而MySql不提供开箱即用的方法。

话虽如此,我相信你真正需要的是prepared statements。这很快,而且很安全。

function addInvitedUsers($invitingUser, $invitedUsers)
{
    //check if all the parameters are set
    if (isset($invitingUser) && isset($invitedUsers))
    {
        // create a prepared statement for insert
        $query = "INSERT INTO Invited_Users (Inviting_id, Invited_Id) VALUES (?, ?)";
        $stmt = $this->prepare($query); // you need to implement prepare method in your class
        // bind parameters
        $stmt->bind_param("ii", $invitingUser, $invitedUser);
        //for each invited user execute insert
        foreach($invitedUsers as $invitedUser) {
            if ($stmt->execute()) {
                echo "added a new invited user";
            }
        }
    }
    //if parameters are not set - message
    else
        echo "parameters can't be null";
}

您显然可以将插件封装到sp中并使用预准备语句来调用它

CREATE PROCEDURE addInvitedUser(IN invitingUser INT, IN invitedUser INT)
  INSERT INTO Invited_Users (Inviting_id, Invited_Id) 
  VALUES (invitingUser, invitedUser);

然后在你的函数中改变

$query = "INSERT INTO Invited_Users (Inviting_id, Invited_Id) VALUES (?, ?)";

$query = "CALL addInvitedUser (?, ?)";