我正在努力了解如何最好地利用mysqli预处理语句,而且我也是面向对象PHP的新手。
据我所知,准备一个语句然后多次执行它比简单地重复相同的查询更有效。
下面的类通过主键获取声音对象。如果我需要在同一个脚本中有这个类的几个实例,我是否会从准备好的语句中获益?
这是否适合存储过程?
class sound {
public $id;
public $name;
public $musickey;
public function __construct($id) {
$this->id = $id;
$sqli = new mysqli();
if($stmt = $con->prepare("SELECT name, musickey FROM sounds WHERE id = ?")) {
$stmt->bind_param("i", $this->id);
$stmt->execute();
$stmt->bind_result($name, $musickey);
}
我希望我的问题不重复。我一直试图找到关于这个主题的东西,但有时形成正确的问题可能与找到答案一样困难。
答案 0 :(得分:2)
据我所知,准备一个语句然后多次执行它比简单地重复相同的查询更有效。
正确。因为服务器端预处理语句(mysqli使用的语句)仅在后续执行时将绑定参数发送到数据库而不是整个查询。此外,数据库服务器不必重新解析查询,但可以重用已准备好的查询。因此,这可以在检索数据方面发挥作用。所以从理论上讲,这样更有效。
见http://php.net/manual/en/mysqli.quickstart.prepared-statements.php。
在实践中,不要指望那么大的差异。这当然取决于您打算为此调用的查询的数量和复杂性,以产生显着差异。如有疑问,请以基准为准。
它还具有protecting you from SQL Injection的附加好处。
下面的类通过主键获取声音对象。如果我需要在同一个脚本中有这个类的几个实例,我是否会从准备好的语句中获益?
没有。因为每次创建新实例以准备该语句时,mysqli都会向服务器发出查询。除了执行调用。所以你什么都没赢。那么使用像
这样的东西会更直接$query = sprintf('SELECT name, musickey FROM sounds WHERE id = %d', $id);
然后执行整个查询,如果你真的想要每个ID一个实例。
如果要使用预准备语句执行此操作,则只需要一个准备一次但可以多次传递ID的实例。
这是否适合存储过程?
如果将应用程序逻辑放入存储过程,则会降低应用程序的可移植性。如果要在某一点更改数据库系统,则需要重新创建存储过程。由您自己做出明智的选择。如果您不需要更改数据库系统,那么它可能是可行的。我更喜欢将逻辑保留在应用程序中。
来自客户的我也是面向对象PHP的新手。
One aspect of OOP is about encapsulating and hiding information(和复杂性)。所以拥有公共财产并不是最好的主意。此外,doing work in the constructor is not what the constructor is for.构造函数应该只将对象置于有效状态。而且,由于准备进行查询,您希望将其推迟到需要之前。
尽管如此,请考虑
interface FindById
{
public function findById($id);
}
class SoundFinder implements FindById
{
private $mysqli;
private $statement;
private $query = "SELECT name, musickey FROM sounds WHERE id = ?";
public function __construct(mysqli $mysqli)
{
$this->mysqli = $mysqli;
}
private function prepare()
{
$this->statement = $mysqli->prepare($this->query)
}
public function findById($id)
{
if (!$this->statement) {
$this->prepare();
}
$this->statement->bind_param("i", $this->id);
$this->statement->execute();
$this->statement->bind_result($name, $musickey);
$this->statement->free_result();
return array($name, $musickey);
}
}
然后你可以像这样使用它:
$connection = new mysqli(/* your connection data */);
$soundFnder = new SoundFinder($connection);
$sound42 = $soundFinder->findById(42);
$sound314 = $soundFinder->findById(314);
答案 1 :(得分:-1)
比简单地重复相同的查询更有效率。
你理解错了。
Dunno告诉过你,但根本没有“更多”
这种差异几乎不可察觉,往往不值得一塌糊涂。特别是在这种直接主键查找的情况下。
我会从准备好的声明中获益吗?
我对此表示怀疑。
如果这样的地方成为瓶颈(唯一的理由打扰任何优化,请注意),最好选择一个查询中的所有数据