mysql stmt语法_mysql中SQL执行过程详解与用于预处理语句的SQL语法

mysql中SQL执行过程详解

9a47b0e8a641ae2650fc82a14bcf2c9b.png

客户端发送一条查询给服务器;

服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段。

服务器段进行SQL解析、预处理,在优化器生成对应的执行计划;

mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。

==============================华丽丽的分割线==================================

用于预处理语句的SQL语法

MySQL 5.1对服务器一方的预制语句提供支持。如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL 4.1中实施的高效客户端/服务器二进制协议的优势。候选界面包括MySQL C API客户端库(用于C程序)、MySQL Connector/J(用于Java程序)和MySQL Connector/NET。例如,C API可以提供一套能组成预制语句API的函数调用。请参见25.2.4节,“C API预处理语句”。其它语言界面可以对使用了二进制协议(通过在C客户端库中链接)的预制语句提供支持。有一个例子是PHP 5.0中的mysqli扩展。

对预制语句,还有一个SQL界面可以利用。与在整个预制语句API中使用二进制协议相比,本界面效率没有那么高,但是它不要求编程,因为在SQL层级,可以直接利用本界面:

·         当您无法利用编程界面时,您可以使用本界面。

·         有些程序允许您发送SQL语句到将被执行的服务器中,比如mysql客户端程序。您可以从这些程序中使用本界面。

·         即使客户端正在使用旧版本的客户端库,您也可以使用本界面。唯一的要求是,您能够连接到一个支持预制语句SQL语法的服务器上。

预制语句的SQL语法在以下情况下使用:

·         在编代码前,您想要测试预制语句在您的应用程序中运行得如何。或者也许一个应用程序在执行预制语句时有问题,您想要确定问题是什么。

·         您想要创建一个测试案例,该案例描述了您使用预制语句时出现的问题,以便您编制程序错误报告。

·         您需要使用预制语句,但是您无法使用支持预制语句的编程API。

预制语句的SQL语法基于三个SQL语句:

PREPARE stmt_name FROM preparable_stmt;

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

{DEALLOCATE | DROP} PREPARE stmt_name;

PREPARE语句用于预备一个语句,并赋予它名称stmt_name,借此在以后引用该语句。语句名称对案例不敏感。preparable_stmt可以是一个文字字符串,也可以是一个包含了语句文本的用户变量。该文本必须展现一个单一的SQL语句,而不是多个语句。使用本语句,‘?’字符可以被用于制作参数,以指示当您执行查询时,数据值在哪里与查询结合在一起。‘?’字符不应加引号,即使您想要把它们与字符串值结合在一起,也不要加引号。参数制作符只能被用于数据值应该出现的地方,不用于SQL关键词和标识符等。

如果带有此名称的预制语句已经存在,则在新的语言被预备以前,它会被隐含地解除分配。这意味着,如果新语句包含一个错误并且不能被预备,则会返回一个错误,并且不存在带有给定名称语句。

预制语句的范围是客户端会话。在此会话内,语句被创建。其它客户端看不到它。

在预备了一个语句后,您可使用一个EXECUTE语句(该语句引用了预制语句名称)来执行它。如果预制语句包含任何参数制造符,则您必须提供一个列举了用户变量(其中包含要与参数结合的值)的USING子句。参数值只能有用户变量提供,USING子句必须准确地指明用户变量。用户变量的数目与语句中的参数制造符的数量一样多。

您可以多次执行一个给定的预制语句,在每次执行前,把不同的变量传递给它,或把变量设置为不同的值。

要对一个预制语句解除分配,需使用DEALLOCATE PREPARE语句。尝试在解除分配后执行一个预制语句会导致错误。

如果您终止了一个客户端会话,同时没有对以前已预制的语句解除分配,则服务器会自动解除分配。

以下SQL语句可以被用在预制语句中:CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多数的SHOW语句。目前不支持其它语句。

以下例子显示了预备一个语句的两种方法。该语句用于在给定了两个边的长度时,计算三角形的斜边。

第一个例子显示如何通过使用文字字符串来创建一个预制语句,以提供语句的文本:

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';

mysql> SET @a = 3;

mysql> SET @b = 4;

mysql> EXECUTE stmt1 USING @a, @b;

+------------+

| hypotenuse |

+------------+

|          5 |

+------------+

mysql> DEALLOCATE PREPARE stmt1;

第二个例子是相似的,不同的是提供了语句的文本,作为一个用户变量:

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';

mysql> PREPARE stmt2 FROM @s;

mysql> SET @a = 6;

mysql> SET @b = 8;

mysql> EXECUTE stmt2 USING @a, @b;

+------------+

| hypotenuse |

+------------+

|         10 |

+------------+

mysql> DEALLOCATE PREPARE stmt2;

预制语句的SQL语法不能被用于带嵌套的风格中。也就是说,被传递给PREPARE的语句本身不能是一个PREPARE, EXECUTE或DEALLOCATE PREPARE语句。

预制语句的SQL语法与使用预制语句API调用不同。例如,您不能使用mysql_stmt_prepare() C API函数来预备一个PREPARE, EXECUTE或DEALLOCATE PREPARE语句。

预制语句的SQL语法可以在已存储的过程中使用,但是不能在已存储的函数或触发程序中使用。

<think>好的,我现在需要详细解释MySQL中的PREPARE语句的用法,并且给出示例。首先,我得回想一下PREPARE的基本概念。用户可能已经知道预处理语句可以提升性能,但具体怎么用可能不太清楚。 首先,应该先介绍PREPARE的作用,比如防止SQL注入,动态生成SQL语句。然后要分步骤说明,从PREPARE到EXECUTE再到DEALLOCATE的流程。可能需要提到用户变量和本地变量的区别,用户变量用@符号,而本地变量在存储过程中使用。 接下来,给出一个基础示例,比如动态查询用户表,根据不同的条件执行。这时候需要用PREPARE ... FROM来准备语句,用USING传递参数。同时要注意字符串拼接的方式,比如用户输入的表名可能需要用CONCAT函数处理。 然后,可能需要一个存储过程内的示例,展示如何在过程中使用预处理语句。比如动态创建临时表,或者在循环中执行不同的SQL语句。这时候要注意变量作用域的问题,比如在存储过程中声明变量需要使用DECLARE。 还要提到一些注意事项,比如预处理语句的作用域仅限于当前会话,不能跨连接使用。同时,预处理语句的参数占位符只能用于数据值,不能用于表名或列名,这时候需要用字符串拼接来处理动态对象名,但要注意SQL注入的风险,可能需要额外的验证。 然后,根据用户提供的引用内容,引用[1]提到了临时表的问题,所以在示例中可能需要避免这种情况,或者在动态SQL中正确使用临时表。引用[2]提到了查询结果集的返回,可能在EXECUTE后处理结果集的方式需要注意。 最后,生成相关问题的时候,要考虑用户可能进一步想知道的内容,比如预处理语句和普通语句的性能差异,或者如何在其他编程语言中使用预处理语句,或者如何防止SQL注入的具体方法。这些都可以作为相关问题提出。 检查一下是否有语法错误,比如PREPARE的语法是否正确,EXECUTE的用法,以及DEALLOCATE的顺序。确保示例中的SQL语句是正确可运行的,比如表名和变量是否正确使用。同时,确保使用中文回答,数学公式如果有的话要用$符号,不过这个问题里可能用不上数学公式,但需要注意其他格式要求,比如代码块用反引号包裹。 总结一下,回答的结构应该是先概述,然后详细步骤,接着基础示例和存储过程示例,注意事项,最后相关问题。需要确保每个部分都清晰,并且覆盖用户可能遇到的问题。</think>### MySQL PREPARE语句详解 #### 1. 基本概念 `PREPARE`语句用于创建**动态SQL预处理语句**,支持参数占位符(`?`)实现安全高效的数据操作。预处理语句可重复执行不同参数值,有效防止SQL注入攻击[^1]。 #### 2. 使用流程 ```sql -- 1. 准备语句 PREPARE stmt_name FROM 'sql_template'; -- 2. 执行语句(可多次调用) EXECUTE stmt_name [USING @var1, @var2...]; -- 3. 释放资源 DEALLOCATE PREPARE stmt_name; ``` #### 3. 基础示例 **动态查询用户表:** ```sql SET @table_name = 'users'; SET @user_id = 100; -- 准备含占位符的语句 PREPARE select_stmt FROM CONCAT('SELECT * FROM ', @table_name, ' WHERE id = ?'); -- 执行并传入参数 EXECUTE select_stmt USING @user_id; DEALLOCATE PREPARE select_stmt; ``` #### 4. 存储过程应用 ```sql DELIMITER $$ CREATE PROCEDURE dynamic_query(IN col_name VARCHAR(64)) BEGIN SET @query = CONCAT('SELECT ', col_name, ' FROM products'); PREPARE dynamic_stmt FROM @query; EXECUTE dynamic_stmt; DEALLOCATE PREPARE dynamic_stmt; END$$ DELIMITER ; -- 调用示例 CALL dynamic_query('product_name, price'); ``` #### 5. 关键特性 | 特性 | 说明 | |-----------------------|--------------------------------------------------------------------| | 参数限制 | 占位符仅适用于数据值,表/列名需字符串拼接(需注意注入风险) | | 作用域 | 预处理语句仅在当前会话有效 | | 性能优势 | 重复执行时减少SQL解析开销 | #### 6. 安全实践 ```sql -- 验证表名合法性 SET @table = 'user_input_table'; SET @allowed_tables = 'users,products'; PREPARE validate_stmt FROM 'SELECT IF(FIND_IN_SET(?, ?) > 0, "VALID", "INVALID") AS result'; EXECUTE validate_stmt USING @table, @allowed_tables; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值