MySQL 9.0 发行说明
预处理语句 API 允许执行受支持的 SQL 语句(参见 预处理语句中允许的 SQL 语法),而无需每次都承担解析和优化的成本。
预处理语句支持参数化。问号或问号 (?
) 用作参数标记;参数在之前更新(绑定到值),每次执行语句时,使用 PreparedStatement.bind()
。有关更多信息,请参见此方法的描述。
要释放解析查询和语句参数占用的资源,请调用 PreparedStatement.deallocate()
,它将关闭预处理语句并释放其资源。省略取消分配不会产生错误,但存储过程执行期间消耗的内存否则不会在例程执行完成之前释放。一旦预处理语句关闭(取消分配),它将不再可用以执行。
预处理语句的执行流程包括以下步骤
准备语句 (
prepare()
)更新参数 (
bind()
)执行语句 (
execute()
)关闭语句 (
deallocate()
)
步骤 2 和 3 可以在关闭预处理语句之前重复任意次数。
这里所示的 JavaScript 存储过程 jssp_prep1()
接受一个包含两个参数标记的任意 SQL 语句,准备语句,然后执行它两次,每次将不同的值绑定到参数,并将结果打印到 stdout
CREATE PROCEDURE jssp_prep1(IN query VARCHAR(200))
LANGUAGE JAVASCRIPT AS $$
function print_result(result) {
console.log(result.getColumnNames())
let row = result.fetchOne()
while(row) {
console.log(row.toArray())
row = result.fetchOne()
}
}
function fetch_warnings(result) {
console.log("Number of warnings: " + result.getWarningsCount())
for (var w in result.getWarnings()) {
console.log(w.level + ", " + w.code + ", " + w.message)
}
}
let stmt = session.prepare(query)
stmt.bind(3, 4)
let res1 = stmt.execute()
print_result(res1)
fetch_warnings(res1)
stmt.bind(2, 3)
let res2 = stmt.execute()
print_result(res2)
fetch_warnings(res2)
stmt.bind(5)
let res3 = stmt.execute()
print_result(res3)
fetch_warnings(res3)
stmt.deallocate()
$$;
完成预处理语句后,通过调用 deallocate()
关闭它,释放准备和执行它时使用的任何资源。
在所有参数至少绑定一次之后,允许使用少于语句中参数数量的参数调用 bind()
。在这种情况下,在之前调用 stmt.bind(2,3)
之后调用 stmt.bind(5)
与调用 stmt.bind(5,3)
相同 - 缺少的第二个值将从之前的调用中重复使用,正如我们在这里看到的那样
mysql> CALL jssp_prep1("
"> SELECT *
"> FROM t1
"> WHERE c1 = ? OR c1 = ?
"> ");
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT mle_session_state("stdout")\G
*************************** 1. row ***************************
mle_session_state('stdout'): c1,c2,c3
3,37,peach
4,221,watermelon
Number of warnings: 0
c1,c2,c3
2,139,apple
3,37,peach
Number of warnings: 0
c1,c2,c3
3,37,peach
5,83,pear
Number of warnings: 0
1 row in set (0.00 sec)