mysql原生只支持?位置参数,:name等命名参数需驱动层转换;混用会报错;存储过程in/out/inout决定参数流向;sp_executesql比exec更安全因强制分离sql与参数;mybatis推荐@param显式命名。

MySQL 里用 ? 和 :name 传参,到底该选哪个?
MySQL 原生不支持命名参数(如 :age),只认位置占位符 ?;但很多客户端(如 PDO、MyBatis、JDBC)在驱动层做了封装,让你能写 :name 或 @name,最终还是被转成 ? + 顺序绑定。所以「语法看着像命名,底层仍是位置」是常态。
- 用
?最稳妥:所有 MySQL 客户端都原生支持,比如PREPARE stmt FROM 'SELECT * FROM users WHERE age > ?'; EXECUTE stmt USING 18; - 用
:name要看驱动:PDO 支持:age,但必须配合prepare()+execute();直接丢进mysql_query()会报错或被当字面量处理 - 别混用:一个语句里不能同时写
?和:id,驱动通常只认一种模式,混用大概率触发SQLSTATE HY093(无效参数编号)错误
存储过程中 IN/OUT/INOUT 参数怎么真正生效?
这三个关键字不是装饰,它们决定了变量生命周期和调用方能否拿到值——OUT 参数在进入过程时自动初始化为 NULL,哪怕你传了个非空值进来,它也会被忽略;而 INOUT 才是“既读又写”的真实双向通道。
-
IN:只进不出,适合过滤条件,比如CREATE PROCEDURE get_user(IN uid INT) BEGIN SELECT * FROM users WHERE id = uid; END; -
OUT:只出不进,调用前必须声明用户变量,比如SET @count = 0; CALL count_users(18, @count); SELECT @count;—— 不声明@count就直接CALL,过程执行完你也拿不到值 -
INOUT:值先传入再被修改,适合需要“原地更新”的场景,比如字符串拼接:SET @s = 'hello'; CALL append_world(@s); SELECT @s;,过程内必须有SET s = CONCAT(s, ' world');
SQL Server 的 sp_executesql 为什么比 EXEC 更安全?
因为 EXEC('SELECT * FROM '+ @table) 是字符串拼接,@table 一旦含恶意内容(如 'users; DROP TABLE users--'),就直接执行注入语句;而 sp_executesql 强制把动态部分和参数分开,参数永远被当数据处理,不会进 SQL 解析器。
绿色农业公司网站模板源码采用织梦5.7 UTF编码制作,该源码附带栏目数据。安装说明:解压上传到空间,运行域名/install进行安装,安装好后到后台系统-数据备份还原 还原下数据,最新到系统-系统基本参数把网站名称什么的改为自己的即可。详细安装说明在压缩包,可自行查看。
- 正确写法:
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM users WHERE age > @age'; EXEC sp_executesql @sql, N'@age INT', @age = 25; - 错误写法:
EXEC('SELECT * FROM users WHERE age > ' + CAST(@age AS VARCHAR))—— 看似一样,实则失去参数化保护 - 注意类型匹配:
@age = 25中的25是 int,如果传字符串却没加引号,会报Conversion failed when converting the varchar value...
MyBatis 传多个参数时,@Param 和 Map 哪个更稳?
用 @Param("uid") 显式标注参数名,XML 中才能写 #{uid};否则 MyBatis 3.4+ 默认按位置映射为 #{param1}、#{param2},极易因方法重载或参数调整导致取错值。
- 推荐
@Param:适合 2–5 个固定参数,比如findUser(@Param("uid") Long uid, @Param("status") String status) - 用
Map:适合参数数量不固定或需运行时组装,但必须确保 key 名和 XML 中一致,且 Map 本身不能为null,否则抛BindingException - 避免 JavaBean:虽然直观,但一旦接口要兼容旧字段+新字段,就得改实体类加
@JsonIgnore或判空逻辑,反而增加维护成本
参数传递最常被忽略的一点:数据库驱动版本和 SQL 方言的隐式差异。比如 MySQL 8.0+ 的 PREPARE 对用户变量支持更严格,而低版本允许某些模糊写法;SQL Server 的 sp_executesql 在 Azure SQL 中对参数长度限制也不同。上线前务必在目标环境验证参数绑定行为。









