预编译 SQL 科普
虽然这是一个很基础的知识点,我发现其实还有很多人都不了解,有必要再次科普下。
预编译 SQL 是预防注入最基本的手段,在正式开始一个项目之前,非常有必要了解预编译 SQL ,现在大部分框架都支持预编译 SQL,如下这是预编译 SQL :
select * from test.user where id = ?;
insert into test.user (id, name) values (?, ?);
关于
预编译 SQL 参数值的占位符为 ? ,并且,预编译 SQL 参数占位符只能出现在可以传入参数的位置,这是数据库的强制性规则,使用预编译 SQL 有如下好处:
- 预防 SQL 注入;
- 避免拼接参数引号
'问题,降低错误率; - 获得数据库底层优化:SQL 相同,仅仅参数不同,数据库可以对 SQL 进行缓存,优化执行计划,提高性能;
常见框架中的预编译参数占位符:
- Rabbit SQL:
:id - MyBatis:
#{id} - JPA:
?id
这些框架专属的写法最终都会被转换为数据库支持的
?,因为?只能按顺序填入参数,框架的封装方便用户根据参数名来传入参数。
在 Rabbit SQL 中,${} 这个占位符叫做字符串模版占位符,同样可以用来当作参数占位符,但这是极不推荐的 ❌ ,因为并不进行参数的安全处理,主要作用是拼接 SQL 片段,如下例子在 XQL File Manager 中:
/*[queryUsers]*/
select * from user where ${cnd};
/*{cnd}*/
id = :id;
SQL 片段中也应该写预编译 SQL 参数占位符,最终拼接而成的 SQL 为:
select * from user where id = :id;
非必要情况下,尽可能使用预编译 SQL 占位符,除非无法满足您特殊需求,您明确知道不会产生注入风险。