预准备语句是一种非常好的方法,用于以高安全性和高效率将变量传递给查询。一切都很好。只是有一件小事有时让我感到不舒服。
实际上有时我的查询是动态的。而且我不知道我应该传递多少次变量。假设这个查询:
UPDATE user
SET reputation = reputation + (CASE id WHEN :op THEN 2 WHEN :user THEN 15 END)
WHERE id in (:user, :op);
我应该传递2个变量($user
,$op
),我必须将它们绑定两次:
$sth->bindValue(":op", $op, PDO::PARAM_INT);
$sth->bindValue(":user", $user, PDO::PARAM_INT);
$sth->bindValue(":user", $user, PDO::PARAM_INT);
$sth->bindValue(":op", $op, PDO::PARAM_INT);
有时候,查询会是这样的:
UPDATE user
SET reputation = reputation + (CASE id WHEN :op THEN 2 WHEN :user THEN 15 END)
WHERE id in (:user, :op),
fee = fee +
(CASE id WHEN :op THEN (SELECT SUM(op_val) FROM money WHERE id = :post_id)
WHEN :user THEN (SELECT SUM(user_val) FROM money WHERE id = :post_id)
END)
WHERE id in (:user, :op);
对于上面的查询,我应该再传递1个变量($post_id
)。换句话说,4更多绑定值:
$sth->bindValue(":op", $op, PDO::PARAM_INT);
$sth->bindValue(":user", $user, PDO::PARAM_INT);
$sth->bindValue(":op", $op, PDO::PARAM_INT);
$sth->bindValue(":post_id", $post_id, PDO::PARAM_INT);
$sth->bindValue(":user", $user, PDO::PARAM_INT);
$sth->bindValue(":post_id", $post_id, PDO::PARAM_INT);
$sth->bindValue(":user", $user, PDO::PARAM_INT);
$sth->bindValue(":op", $op, PDO::PARAM_INT);
请参阅?我很难将变量传递给动态查询。我的意思是我必须多次传递一个变量。那么有没有其他方法来验证变量而不是预处理语句?
答案 0 :(得分:3)
一般来说,可以:
定义一些user variables,然后由同一会话中的后续查询使用:
$set = $pdo->prepare('SET @op = :op, @user = :user, @post = :post');
$set->bindValue('op' , $op , PDO::PARAM_INT);
$set->bindValue('user', $user, PDO::PARAM_INT);
$set->bindValue('post', $post, PDO::PARAM_INT);
$set->execute();
$sth = $pdo->query('
UPDATE user
SET reputation = reputation + CASE id
WHEN @op THEN 2
WHEN @user THEN 15
END,
fee = fee + CASE id
WHEN @op THEN (SELECT SUM(op_val) FROM money WHERE id = @post)
WHEN @user THEN (SELECT SUM(user_val) FROM money WHERE id = @post)
END
WHERE id in (@user, @op)
');
创建一个包含变量的实体化表格,并将其加入查询:
$sth = $pdo->prepare('
UPDATE user
JOIN (SELECT :op AS op, :user AS user, :post AS post) AS variables
SET reputation = reputation + CASE id
WHEN variables.op THEN 2
WHEN variables.user THEN 15
END,
fee = fee + CASE id
WHEN variables.op THEN (SELECT SUM(op_val) FROM money WHERE id = variables.post)
WHEN variables.user THEN (SELECT SUM(user_val) FROM money WHERE id = variables.post)
END
WHERE id in (variables.user, variables.op)
');
$sth->bindValue('op' , $op , PDO::PARAM_INT);
$sth->bindValue('user', $user, PDO::PARAM_INT);
$sth->bindValue('post', $post, PDO::PARAM_INT);
$sth->execute();
但是,在这种特定情况下,可以将UPDATE
分成两部分:
$sth1 = $pdo->prepare('
UPDATE user
SET reputation = reputation + 2,
fee = fee + (SELECT SUM(op_val) FROM money WHERE id = :post)
WHERE id = :op
');
$sth1->bindValue('op' , $op , PDO::PARAM_INT);
$sth1->bindValue('post', $post, PDO::PARAM_INT);
$sth2 = $pdo->query('
UPDATE user
SET reputation = reputation + 15,
fee = fee + (SELECT SUM(user_val) FROM money WHERE id = :post)
WHERE id = :user
');
$sth2->bindValue('user', $user, PDO::PARAM_INT);
$sth2->bindValue('post', $post, PDO::PARAM_INT);
$sth1->execute();
$sth2->execute();
答案 1 :(得分:2)
您可以在Execute中绑定变量。你仍然会准备声明。您可以在execute语句中将变量作为数组插入而不是bindParam()。
$stmt->execute(array(':var1'=>$var1, ':var2'=>$var2));