我需要在MySQL表中插入很多行(介于150到300之间),我想知道以下方法在性能方面更好:
方法1:
foreach( $persons as $person ){
$stmt = $dbLink->prepare( "INSERT INTO table SET id = :ID,
name = :name,
email = :email,
mobile = :mobile");
$stmt->execute( array( ':ID'=>$person->getID(),
':name'=>$person->getName(),
':email'=>$person->getEmail(),
':mobile'=>$person->getMobile(),
) );
}
方法2:
$stmt = $dbLink->prepare( "INSERT INTO table SET id = :ID,
name = :name,
email = :email,
mobile = :mobile");
$stmt->bindParam( ':ID', $person->getID(), PDO::PARAM_STR );
$stmt->bindParam( ':name', $person->getName(), PDO::PARAM_STR );
$stmt->bindParam( ':email', $person->getEmail(), PDO::PARAM_STR );
$stmt->bindParam( ':mobile', $person->getMobile(), PDO::PARAM_STR );
foreach( $persons as $person ){
$stmt->execute();
}
答案 0 :(得分:3)
对数据库的调用量是有什么不同的。尽可能减少通话量。
而不是:
insert (a,b,c) values (d,e,f);
insert (a,b,c) values (g,h,i);
insert (a,b,c) values (j,k,l);
insert (a,b,c) values (m,n,o);
这样做:
insert (a,b,c) values (d,e,f),(g,h,i),(j,k,l),(m,n,o);
这样可以在一个电话中进行4次电话会议。
答案 1 :(得分:1)
要回答您的问题,这是您应该构建准备/绑定/执行阶段的方式:
//prepare the query only the first time
$stmt = $dbLink->prepare( "INSERT table (id, name, email, mobile)
VALUES (:ID, :name, :email, :mobile)" );
//bind params and execute for every person
foreach( $persons as $person ){
$stmt->bindValue( ':ID', $person->getID(), PDO::PARAM_STR );
$stmt->bindValue( ':name', $person->getName(), PDO::PARAM_STR );
$stmt->bindValue( ':email', $person->getEmail(), PDO::PARAM_STR );
$stmt->bindValue( ':mobile', $person->getMobile(), PDO::PARAM_STR );
$stmt->execute();
}
如果你有PDO::ATTR_EMULATE_PREPARES = false
,那么第一次只能通过mysql编写查询。
在第一种情况下,它将为每个循环周期重新准备
正如其他用户所说的那样,请记住,更好的性能改进是在for循环中只进行一次插入而不是多次插入
编辑:如何使用参数绑定和一个查询
使用参数'绑定,解决方案只能是一个查询:
$placeholders = ""; //this will be filled with placeholders : ( :id_1, :name_1, :email_1, :mobile_1),( :id_2 ... )
$parameters = array(); //this will keep the parameters bindings
$i = 1;
foreach( $persons as $person )
{
//add comma if not first iteration
if ( $placeholders )
$placeholders .= ", ";
//build the placeholders string for this person
$placeholders .= "( :id_$i, :name_$i, :email_$i, :mobile_$i )";
//add parameters for this person
$parameters[":id_$i"] = $person->getID();
$parameters[":name_$i"] = $person->getName();
$parameters[":email_$i"] = $person->getEmail();
$parameters[":mobile_$i"] = $person->getMobile();
$i++;
}
//build the query
$stmt = $dbLink->prepare( "INSERT INTO table (id, name, email, mobile)
VALUES " . $placeholders );
//execute the query passing parameters
$stmt->execute( $parameters );
在循环的第一部分中,我们使用一组占位符为每个人构建字符串$placeholders
,在循环的第二部分中,我们将占位符值的绑定存储在{{1数组
在循环结束时,我们应该设置所有占位符和参数,并且我们可以执行将$parameters
数组传递给$parameters
方法的查询。这是使用execute
/ bindValue
方法的替代方法,但结果应该相同
我认为这是使用参数绑定并且只使用一个查询的唯一方法
答案 2 :(得分:1)
您可以使用以下代码来避免多个SQL调用并在Single SQL调用中插入数据
$first_string = "INSERT INTO table (id, name, email,mobile) VALUES ";//Basic query
foreach( $persons as $person )
{
$first_string .="(".$person->getID().",".$person->getName().",".$person->getEmail().",".$person->getMobile()."),";//Prepare the values
}
$final_query_string = substr($first_string, 0,-1);// This will remove the extra , at the end of the string
$stmt = $dbLink->prepare($final_query_string);
$stmt->execute();
现在执行准备好的最终查询字符串。
这种方式将查询准备为字符串,您需要一次执行它。 这将进行单个SQL调用
答案 3 :(得分:0)
//declare array of values to be passed into PDO::Statemenet::execute()
$values = array();
//prepare sql string
$sql = 'INSERT INTO students ( id, name, email, mobile ) VALUES ';
foreach( $students as $student ){
$sql .= '( ?, ?, ?, ? ),'; //concatenate placeholders with sql string
//generate array of values and merge with previous values
$values = array_merge( $values, array( $student->getID(),
$student->getName(),
$student->getEmail(),
$student->getMobile(),
)
);
}
$sql = rtrim( $sql, ',' ); //remove the trailing comma (,) and replace the sql string
$stmt = $this->dbLink->prepare( $sql );
$stmt->execute( $values );
对所有激励我达成此解决方案的人充分肯定。这似乎简洁明了:
特别是,JM4在PDO Prepared Inserts multiple rows in single query的回答确实有帮助。我也在这个页面上认出了Moppo。