Azure Functions(TypeScript)中SQL Server VARCHAR参数传递报错求解
问题分析与解决方案
错误根源
你当前的代码使用模板字符串直接将变量插入SQL语句,导致字符串类型参数未被正确转义。例如当weight的值为5kg时,生成的SQL会是SET @weight = 5kg;——这里5kg没有被引号包裹,SQL解析器会把kg当作无效标识符,直接触发语法错误。同时这种写法存在严重的SQL注入风险,恶意输入可能直接破坏数据库。
正确解决方案(优先推荐:无动态SQL场景)
你的UPDATE语句不需要动态SQL,直接使用mssql的参数化查询即可,这是最简单且安全的方式:
const trainingId: number = parseInt(req.params.training_id); const exerciseId: number = parseInt(req.params.exercise_id); const weight: string = req.body.weight; // 直接使用参数化查询,无需手动拼接SQL await mssql.query(` UPDATE Exercises SET weight = @weight WHERE training_id = @training_id AND exercise_id = @exercise_id `, { params: { training_id: { type: mssql.Int, value: trainingId }, exercise_id: { type: mssql.Int, value: exerciseId }, weight: { type: mssql.VarChar(255), value: weight } } });
如果不需要严格指定参数类型,也可以用更简洁的写法(mssql会自动推断基础类型):
await mssql.query(` UPDATE Exercises SET weight = @weight WHERE training_id = @training_id AND exercise_id = @exercise_id `, { training_id: trainingId, exercise_id: exerciseId, weight: weight });
动态SQL场景的正确写法(如果确实需要)
如果后续业务需要动态生成SQL(比如动态指定更新字段),必须通过sp_executesql的参数列表传递值,绝对不能直接拼接变量到动态SQL字符串中:
const trainingId: number = parseInt(req.params.training_id); const exerciseId: number = parseInt(req.params.exercise_id); const weight: string = req.body.weight; await mssql.query(` DECLARE @sql NVARCHAR(4000); SET @sql = N' UPDATE Exercises SET weight = @weight WHERE training_id = @training_id AND exercise_id = @exercise_id' EXEC sp_executesql @sql, N'@training_id INT, @exercise_id INT, @weight VARCHAR(255)', @training_id = @training_id_param, @exercise_id = @exercise_id_param, @weight = @weight_param `, { params: { training_id_param: trainingId, exercise_id_param: exerciseId, weight_param: weight } });
核心注意事项
- 永远不要用模板字符串、字符串拼接的方式将用户输入直接插入SQL语句,这是SQL注入的高危操作
- 优先使用参数化查询,让数据库驱动自动处理参数的转义和类型匹配
- 动态SQL只能用于动态生成SQL结构(如字段名、表名),参数值必须通过
sp_executesql的参数传递
内容的提问来源于stack exchange,提问作者boolie29
相关产品推荐
相关产品推荐

