📜  MySQL准备语句

📅  最后修改于: 2020-11-19 02:18:43             🧑  作者: Mango

MySQL准备语句

在MySQL 4.1版之前,每个查询都以文本格式发送到MySQL服务器,并使用文本协议将查询返回的数据返回给客户端。在将结果返回给客户端之前,MySQL已完全解析了查询并将结果集转换为字符串。在这里,解析意味着对提交的查询进行语法和语义上的验证,并且特权也得到验证。

将数据返回给客户端的文本协议存在严重的性能问题。为了克服这个问题,MySQL从4.1版本开始提供了一种称为“预处理语句”的新功能。

准备的语句或参数化的语句用于高效重复执行相同的语句。它利用了客户端/服务器二进制协议。 Prepared语句将包含占位符(?)的查询传递给MySQL Server。请参见以下示例:

mysql> SELECT * FROM student WHERE studentId = ?; 

当MySQL使用不同的studentId值执行上述语句时,它无法完全分析该语句。结果,MySQL将更快地执行该语句,尤其是当它多次执行相同的查询时。

准备好的语句包含占位符(?),它有助于避免许多SQL注入变体,并使我们的应用程序更安全。

预备报表的优点

以下是MySQL中预处理语句的优点:

  • 我们可以重复执行多次准备好的语句。
  • 每次执行时,都会评估绑定变量的当前值并将其发送到服务器。该语句不会再次解析。语句模板不会再次传输到服务器。

预备报表的基本工作流程

准备好的语句的基本工作流程主要包括两个阶段。但是,它具有一个可选阶段,总结如下:

  • 准备
  • 执行
  • 取消分配(可选)

准备阶段

在准备阶段,一个语句模板被发送到数据库服务器。服务器执行语法检查并初始化内部服务器资源以供以后使用。简而言之,它准备执行语句。

句法

以下是准备阶段的语法:

PREPARE stmt_name FROM preparable_stmt;

执行阶段

在执行阶段,客户端绑定参数值,并将其发送到服务器。服务器根据语句模板和绑定值创建一条语句,以使用先前创建的内部资源执行该语句。简而言之,一旦准备好的语句准备好查询,我们就准备执行该查询。

句法

以下是执行准备好的语句的语法:

EXECUTE stmt_name [USING @var_name [, @var_name]....]

取消分配/删除阶段

这是最后一个可选阶段,用于释放准备好的语句。

句法

以下是取消分配准备好的语句的语法:

{DEALLOCATE | DROP} PREPARE stmt_name;

与准备陈述有关的要点

  • 在一个会话中创建的准备好的语句不适用于其他会话。这意味着准备好的语句是特定于会话的。
  • 会话结束时,无论是正常会话还是异常会话,其准备好的语句在内存中都不再存在。
  • 在程序完成执行之后,在存储的程序中创建的准备好的语句将继续存在,并且可以稍后在程序外部执行。

MySQL预备语句示例

让我们通过一些例子来了解如何使用MySQL预处理语句。

在这里,我们将借助PREPARE语句直接创建一个语句,如下所示:

mysql> PREPARE stmt1 FROM 'SELECT ?+? AS SUM';

接下来,我们将两个值分配给两个可用于占位符(?)的变量:

mysql> SET @a = 20;
mysql> SET @b = 30;

现在,我们可以借助EXECUTE语句执行查询:

mysql> EXECUTE stmt1 USING @a, @b;

执行后,我们将得到结果的总和。请参见下图以了解结果:

以下示例将使用示例数据库中的employee表,该表包含以下数据。

首先,我们将准备一条语句,该语句返回由员工ID指定的员工姓名和职务:

mysql> PREPARE stmt1 FROM 
'SELECT Name, Designation FROM employee 
WHERE Emp_id = ?';

接下来,我们需要声明一个名为id的变量并将其值设置为“ 1”:

mysql> SET @id = 1;

现在,我们可以在EXECUTE语句的帮助下执行准备好的语句:

mysql> EXECUTE stmt1 USING @id;

执行后,我们将得到包含雇员姓名和职务的结果。请参见下图以了解查询执行:

同样,我们将为变量id分配另一个值:

mysql> SET @id = 3;

现在,使用新的员工ID执行准备好的语句。我们将看到如下输出:

最后,我们可以手动释放准备好的语句。但是,它们将在会话关闭时自动删除。

mysql> DEALLOCATE PREPARE stmt1;

如果在执行上述查询后尝试执行预处理语句,则会收到如下错误:

我们如何在存储过程中使用准备好的语句?

通过将准备好的语句写入到BEGIN和END块中,可以在存储过程中使用它。我们可以通过创建一个示例来理解它,该示例通过将表名作为存储过程的参数传递来返回表中的所有记录。

创建存储过程,如下所示:

DELIMITER $$  
CREATE PROCEDURE tbl_detail(tab_name Varchar(40))  
BEGIN  
SET @A:= CONCAT('Select * from',' ',tab_name);
Prepare stmt FROM @A;
EXECUTE stmt;
END$$  
DELIMITER ;  

请参见下图执行存储过程:

创建成功后,我们可以通过将表名称指定为其参数来调用此过程。

mysql> CALL tbl_detail('employee');

它将显示表的所有记录。见下图:

陈述与准备陈述

以下是MySQL中的语句和预准备语句之间的主要区别:

Statement Prepared Statement
It is used when we want to execute the SQL query only once. It is used when we want to execute the SQL query multiple times.
It is used for DDL statements. It can be used for any SQL query.
It cannot be used to read and write binary data. It can be used to read and write binary data.
It is static, which means we cannot pass parameters at runtime. It is dynamic, which means we can pass parameters at runtime.
The performance of execution is slow. The performance of execution is fast.
It does not prevent SQL injection. It helps to prevent SQL injection attacks.
It uses a textual protocol for communication. It uses a binary protocol for communication.

存储过程与准备好的语句

以下是存储过程和MySQL中的prepared语句之间的主要区别:

Stored Procedure Prepared Statement
Stored procedures are a sequence of SQL statements that access the relational database management system. Prepared statements are queries that contain the placeholders instead of actual values.
It can be stored in the database server. It cannot be stored in the database.