上下文:
我正试图通过将令牌绑定到数据的PDO方法,使用通常的update语法,在MySQL数据库中用一组值更新记录。
问题:
要更新的字段数是动态的,并根据已粘贴到页面的数据进行调整。使用if(isset($_POST[]))
来过滤可能已经有数据的字段的更新,但我不想被空数据覆盖。
这意味着我创建的令牌数量各不相同,但我将数据绑定到令牌的语法是静态的,我不知道如何调整它
这当然会导致:SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
我的代码:
请注意$data是数据库中所有列名的数组。它也是可以发布的变量的名称属性集,因此$_POST[x]应该更新到给定记录中的列x,并且x是$data的成员。
$sql_b = "UPDATE `temp_data` SET ";
foreach($data as $value)
{
if(isset($_POST[$value]))
$sql_b .="$value = :$value, ";
}
$sql_b = rtrim($sql_b,', ');
$sql_b .=" WHERE UID = '$uid'";
try
{
$pdo = new PDO('mysql:host=localhost; dbname=db01', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare($sql_b);
foreach($data as $value)
{
$stmt->bindParam(":$value", $_POST[$value]);
}
$stmt->bindParam(":sv_215_hidden", $_POST[sv_215_hidden]);
$stmt->bindParam(":sv_216_hidden", $_POST[sv_216_hidden]);
$stmt->execute();
#受影响的行?echo$stmt->rowCount();//1.}catch(PDOException$e){echo"错误:"$e->getMessage();}
要突出这方面的问题:
此代码:
foreach($data as $value)
{
if(isset($_POST[$value]))
$sql_b .="$value = :$value, ";
}
创建可能的UPDATE请求的子集
此处代码为:
foreach($data as $value)
{
$stmt->bindParam(":$value", $_POST[$value]);
}
始终在所有可能的令牌之间创建一组完整的绑定。
中心问题:
如何调整绑定数以仅与正在更新的字段匹配?
您已经在那里了;您正在检查生成SQL语句时设置了哪些字段:
foreach($data as $value)
{
if(isset($_POST[$value]))
$sql_b .="$value = :$value, ";
}
因此,当您调用bindParam()
:时,可以使用完全相同的逻辑
foreach($data as $value)
{
if(isset($_POST[$value]))
$stmt->bindParam(":$value", $_POST[$value]);
}
我认为您需要做几个额外的步骤:
$keys = array('foo', 'bar', 'baz', 'foobar');
$updates = array();
$bound = array();
foreach($keys as $key){
if (isset($_POST[$key])){
$updates[] = $key . '= :' . $key;
$bound[':' . $key] = $_POST[$key];
}
}
$sql = 'UPDATE table SET ' . implode(',', $updates) . ' WHERE etc'; //add your where clause
$stmt = $pdo->prepare($sql);
$stmt->execute($bound);
换句话说,您可以将绑定参数的数组传递给PDOStatement::execute,而不是预先单独绑定它们;并且按照上面的操作可以确保绑定的参数与SQL中的参数相匹配。