MySQL 变量和预处理语句

最后更新: 2021-06-24 18:18:18 +0800 +0800
tags: Mysql | Sql | Databases
原文以英文撰写。您正在阅读AI翻译版本。

MySQL 区分服务器系统变量、局部例程变量和会话用户变量。它们的作用域和求值规则不同,因此不应互换使用。

系统变量和用户变量 #

系统变量使用 @@,并且可能具有全局作用域、会话作用域或同时具有二者:

sql
SELECT @@GLOBAL.transaction_isolation, @@SESSION.sql_mode;
SET SESSION sql_safe_updates = 1;

更改全局变量会在该变量也具有会话作用域时影响新会话;它不能用来更改现有连接的事务策略。动态变量可以在运行时更改,而只读变量需要启动配置。SET PERSIST 会更改运行时全局值并写入 mysqld-auto.cnf;SET PERSIST_ONLY 会写入持久化值,但不更改运行时状态。使用任一形式前,应确认变量支持持久化,并让服务器拥有该文件,而不要编辑生成的文件。

用户变量使用 @name,以连接为作用域,并且没有声明类型:

sql
SET @minimum_total = 100;
SELECT id FROM orders WHERE total >= @minimum_total;

不要在同一个表达式或查询中赋值并读取同一个用户变量,以模拟过程式求值。MySQL 不保证能使此类查询可靠的求值顺序。应改用窗口函数、公共表表达式、存储程序局部变量或应用代码。值的类型在赋值时确定;预处理语句引用会保留语句首次准备时建立的变量类型。当所需 SQL 类型属于契约的一部分时,应显式使用 CAST 转换值。

预处理语句 #

客户端库的预处理语句会将数据与 SQL 语法分开绑定,并且应作为应用查询的默认方式。它们可以防止值被解释为注入的 SQL,并允许服务器分别解析语句结构。

服务器端 SQL 预处理语句遵循连接作用域的生命周期:PREPARE 解析一条语句, EXECUTE 重复执行它,DEALLOCATE PREPARE 释放它。使用同名的第二个 PREPARE 会先释放旧语句。会话结束时,预处理语句也会被丢弃。当必须组装标识符时,预处理语句适用于管理用动态 SQL。参数标记绑定的是数据值,而不是标识符、关键字或 SQL 片段:

sql
SET @sql = 'SELECT id FROM orders WHERE customer_id = ?';
PREPARE stmt FROM @sql;
SET @customer_id = 42;
EXECUTE stmt USING @customer_id;
DEALLOCATE PREPARE stmt;

在将任何动态标识符连接到 SQL 之前,应验证它或使用允许列表。参数标记不能在每个语法位置代表任意表达式,并且预处理语句受 max_prepared_stmt_count 限制。应释放短期管理语句,并让应用驱动程序管理自己的预处理语句句柄。

参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)