产品概述
应用场景
产品架构
实例类型
兼容性说明
使用规范建议
PREPARE 语句创建一个预处理语句。SQL 模板中使用英文半角问号 ? 作为参数占位符。PREPARE stmt_name FROM preparable_stmt;
参数 | 说明 |
stmt_name | 预处理语句的名称,用于后续引用该语句。名称在当前会话中必须唯一,不区分大小写 |
preparable_stmt | SQL 语句模板,可以是一个字符串字面量或用户变量。使用 ? 作为参数占位符 |
id 查询员工信息的预处理语句:PREPARE stmt_query FROM 'SELECT * FROM employees WHERE id = ?';
SET @sql = 'SELECT * FROM employees WHERE id = ?';PREPARE stmt_query FROM @sql;
EXECUTE 语句执行已创建的预处理语句,并通过 USING 子句传递参数值。参数值必须通过用户变量传递。EXECUTE stmt_name [USING @var_name [, @var_name] ...];
参数 | 说明 |
stmt_name | 要执行的预处理语句名称,必须是已通过 PREPARE 创建的语句 |
@var_name | 用户变量,用于向预处理语句传递参数值。变量的数量必须与 SQL 模板中 ? 占位符的数量一致 |
id 为1的员工信息:SET @id = 1;EXECUTE stmt_query USING @id;
+----+----------+------------+--------+| id | name | department | salary |+----+----------+------------+--------+| 1 | Zhang San| R&D | 15000 |+----+----------+------------+--------+1 row in set (0.00 sec)
SET @id = 2;EXECUTE stmt_query USING @id;
DEALLOCATE PREPARE 语句释放已创建的预处理语句,回收服务端资源。{DEALLOCATE | DROP} PREPARE stmt_name;
参数 | 说明 |
stmt_name | 要释放的预处理语句名称 |
DEALLOCATE PREPARE stmt_query;
DEALLOCATE PREPARE 释放资源,避免占用服务端内存。books 表中指定 id 的书籍信息。PREPARE stmt_select_book FROM 'SELECT * FROM books WHERE id = ?';
SET @book_id = 1;EXECUTE stmt_select_book USING @book_id;
SET @book_id = 5;EXECUTE stmt_select_book USING @book_id;
DEALLOCATE PREPARE stmt_select_book;
books 表中插入一条数据。PREPARE stmt_insert_book FROM 'INSERT INTO books (title, type, stock, price, published_at) VALUES (?, ?, ?, ?, ?)';
SET @title = 'TDSQL Boundless 实战指南';SET @type = 'Technology';SET @stock = 100;SET @price = 89.00;SET @published_at = '2026-01-01';EXECUTE stmt_insert_book USING @title, @type, @stock, @price, @published_at;
DEALLOCATE PREPARE stmt_insert_book;
books 表中指定书籍的库存。PREPARE stmt_update_stock FROM 'UPDATE books SET stock = ? WHERE id = ?';
SET @new_stock = 200;SET @book_id = 1;EXECUTE stmt_update_stock USING @new_stock, @book_id;
DEALLOCATE PREPARE stmt_update_stock;
books 表中指定 id 的书籍记录。PREPARE stmt_delete_book FROM 'DELETE FROM books WHERE id = ?';
SET @book_id = 10;EXECUTE stmt_delete_book USING @book_id;
DEALLOCATE PREPARE stmt_delete_book;
-- 动态构造查询语句SET @query_str = 'SELECT COUNT(*) INTO @result FROM performance_schema.session_variables WHERE VARIABLE_NAME = ?';PREPARE stmt_check FROM @query_str;-- 设置参数并执行SET @var_name = 'rocksdb_bulk_load';EXECUTE stmt_check USING @var_name;-- 查看结果SELECT @result;-- 释放语句DEALLOCATE PREPARE stmt_check;
mysqldump 工具在导出数据时,即使用了类似的 PREPARE...FROM @variable 方式动态构造 SQL 语句,用于检测目标服务器是否支持特定存储引擎功能。SELECTINSERTUPDATEDELETEREPLACECALLDOCREATE DATABASE、CREATE TABLE、CREATE TEMPORARY TABLE、CREATE INDEX、CREATE USERDROP DATABASE、DROP TABLE、DROP TEMPORARY TABLE、DROP INDEX、DROP USER、DROP VIEWALTER USERRENAME TABLE、RENAME USERTRUNCATE TABLEANALYZE TABLE、CHECKSUM TABLE、OPTIMIZE TABLE、REPAIR TABLEGRANT、REVOKE ALL PRIVILEGESSHOW CREATE TABLE、SHOW CREATE PROCEDURE、SHOW CREATE FUNCTION、SHOW CREATE VIEW、SHOW CREATE EVENTSHOW BINLOG EVENTS、SHOW MASTER STATUS、SHOW BINARY LOGS、SHOW SLAVE STATUSINSTALL PLUGIN、UNINSTALL PLUGINKILLCOMMITSET OPTIONRESET MASTER、RESET SLAVESLAVE START、SLAVE STOPLOAD DATA INFILE、USE、BEGIN 等)不支持通过预处理语句执行。mysql_stmt_init() 初始化预处理语句句柄。mysql_stmt_prepare() 将 SQL 模板发送到服务端进行预处理。mysql_stmt_bind_param() 绑定参数值。mysql_stmt_execute() 执行预处理语句。mysql_stmt_bind_result() 和 mysql_stmt_fetch() 获取查询结果(仅查询语句需要)。mysql_stmt_close() 关闭语句句柄,释放资源。函数 | 说明 |
mysql_stmt_init() | 初始化一个 MYSQL_STMT 句柄,用于后续的预处理操作 |
mysql_stmt_prepare() | 将 SQL 语句模板发送到服务端进行解析和编译 |
mysql_stmt_bind_param() | 将应用程序中的变量绑定到 SQL 模板中的 ? 占位符 |
mysql_stmt_execute() | 执行已预处理的语句 |
mysql_stmt_store_result() | 将完整的结果集从服务端读取到客户端缓存 |
mysql_stmt_result_metadata() | 获取预处理语句返回结果的元数据信息(列名、类型等) |
mysql_stmt_fetch() | 逐行获取结果集数据 |
mysql_stmt_close() | 关闭预处理语句句柄,释放客户端和服务端的相关资源 |
mysql_stmt_errno() | 返回最近一次预处理语句操作的错误码 |
mysql_stmt_error() | 返回最近一次预处理语句操作的错误信息 |
mysql_stmt_attr_set() | 设置语句属性,例如游标类型 CURSOR_TYPE_READ_ONLY |
mysql_stmt_next_result() | 用于处理多结果集场景,获取下一个结果集 |
STMT_ATTR_CURSOR_TYPE 为 CURSOR_TYPE_READ_ONLY,可以启用只读游标模式。在该模式下,结果集不会一次性加载到客户端内存,而是按需逐行获取,适用于处理大数据量的查询场景。编程语言 | 驱动或框架 | 预处理语句接口 |
Java | JDBC | java.sql.PreparedStatement |
Python | MySQL Connector/Python | cursor.execute(sql, params) |
Go | go-sql-driver/mysql | db.Prepare() + stmt.Exec() |
PHP | PDO | PDO::prepare() + PDOStatement::execute() |
Node.js | mysql2 | connection.execute(sql, values) |
C/C++ | MySQL C API | mysql_stmt_prepare() + mysql_stmt_execute() |
参数 | 推荐值 | 说明 |
useServerPrepStmts | true | 启用服务端预处理语句。默认情况下 JDBC 使用客户端模拟预处理,设置为 true 后使用服务端预处理,可提升多次执行相同语句的性能 |
cachePrepStmts | true | 启用客户端预处理语句缓存。避免每次使用时重复创建预处理语句 |
prepStmtCacheSqlLimit | 2048 | 单条预处理语句的最大 SQL 长度(单位:字节)。默认值为256,对于复杂 SQL 语句可能不足,建议调大 |
prepStmtCacheSize | 256 | 客户端缓存的预处理语句最大数量。默认值为25,建议根据应用实际使用的 SQL 语句数量调整 |
jdbc:mysql://<host>:<port>/<database>?useServerPrepStmts=true&cachePrepStmts=true&prepStmtCacheSqlLimit=2048&prepStmtCacheSize=256&rewriteBatchedStatements=true&allowMultiQueries=true
<host>、<port>、<database> 替换为 TDSQL Boundless 实例的实际连接信息。事件类型 | 说明 |
Prepare | 记录预处理语句的创建操作,包含 SQL 模板文本 |
Execute | 记录预处理语句的执行操作,包含实际参数值 |
Query | 记录通过文本协议执行的 PREPARE、EXECUTE、DEALLOCATE PREPARE 语句 |
COMMAND_CLASS、CONNECTION_ID、STATUS、SQLTEXT 等字段,可用于安全审计和执行分析。? 传递,避免将用户输入直接拼接到 SQL 字符串中,从根本上防止 SQL 注入攻击。DEALLOCATE PREPARE 释放预处理语句,避免占用服务端内存资源。useServerPrepStmts 设置为 true,使用服务端预处理而非客户端模拟,获得更高的执行效率。cachePrepStmts 并合理设置 prepStmtCacheSize 和 prepStmtCacheSqlLimit,减少重复创建预处理语句的开销。max_prepared_stmt_count 控制服务端允许同时存在的预处理语句总数。如果达到上限,新的 PREPARE 操作会返回错误。可通过 SHOW GLOBAL STATUS LIKE 'Prepared_stmt_count' 查看当前已创建的预处理语句数量。变量 | 作用域 | 默认值 | 范围 | 说明 |
max_prepared_stmt_count | GLOBAL | 16382 | 0 ~ 4194304 | 服务端允许同时存在的预处理语句全局总数(所有会话共计)。达到上限时新的 PREPARE 操作会返回 ERROR 1461 (42000): Can't create more than max_prepared_stmt_count statements |
? 数量没有固定上限,但受 max_allowed_packet 系统变量的限制。PREPARE 创建。; 分隔的多语句执行)。PREPARE ... FROM @variable 方式传入的 SQL 文本会在预处理时进行一次完整的语法解析,因此需确保用户变量中的 SQL 语句语法正确。文档反馈