预编译 SQL 科普

虽然这是一个很基础的知识点,我发现其实还有很多人都不了解,有必要再次科普下。

预编译 SQL 是预防注入最基本的手段,在正式开始一个项目之前,非常有必要了解预编译 SQL ,现在大部分框架都支持预编译 SQL,如下这是预编译 SQL :

select * from test.user where id = ?;
insert into test.user (id, name) values (?, ?);

关于

预编译 SQL 参数值的占位符为 ? ,并且,预编译 SQL 参数占位符只能出现在可以传入参数的位置,这是数据库的强制性规则,使用预编译 SQL 有如下好处:

  1. 预防 SQL 注入;
  2. 避免拼接参数引号 ' 问题,降低错误率;
  3. 获得数据库底层优化:SQL 相同,仅仅参数不同,数据库可以对 SQL 进行缓存,优化执行计划,提高性能;

常见框架中的预编译参数占位符:

这些框架专属的写法最终都会被转换为数据库支持的 ? ,因为 ? 只能按顺序填入参数,框架的封装方便用户根据参数名来传入参数。

在 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 占位符,除非无法满足您特殊需求,您明确知道不会产生注入风险。