使用Prisma执行SQL出错,日志写入MySQL失败问题求助
问题原因与解决方案
错误原因
- Error对象直接插入SQL导致语法/类型错误:日志更新语句中直接拼接
${err},但err是Error对象,直接转字符串会包含换行、引号等特殊字符,破坏SQL语法;同时Prisma的Raw Query参数绑定无法正确处理Error对象的结构,导致底层SQL执行失败,返回模糊的N/A错误。 - 不必要的新建Prisma Client实例:原Prisma Client采用连接池模式,单个操作失败不会导致整个实例不可用,重复创建实例反而可能引发连接资源浪费或初始化问题。
解决步骤
1. 正确处理Error对象,提取可插入的错误信息
将Error对象转为结构化的纯字符串(比如提取message、stack字段,或转为JSON格式),避免特殊字符干扰SQL语法。
2. 优先使用Prisma模型方法替代Raw Query
使用Prisma生成的模型方法(如update),而非Raw Query,Prisma会自动处理参数转义和类型校验,避免SQL注入和语法错误。
3. 复用原Prisma Client实例
无需新建实例,原实例可以正常执行后续的日志写入操作。
优化后的代码示例
let prisma = new PrismaClient({ datasources: { db: { url: dbUrl, }, }, }); try { // 用事务包裹批量操作,出错时自动回滚,避免部分数据插入成功 await prisma.$transaction([ prisma.table1.create({ data: { col1: val1, col2: val2 } // 替换为实际业务字段值 }), prisma.table2.create({ data: { col1: val1, col2: val2 } }) ]); } catch (err: any) { console.log('Error doing sql insert: ' + err); try { console.log('getting ready to log sql error') // 提取错误的结构化信息,转为可插入的字符串 const errorMsg = `Error at: ${msg}. Message: ${err.message}, Stack: ${err.stack || 'No stack trace'}`; // 也可以转为JSON格式存储:const errorMsg = JSON.stringify({ message: err.message, stack: err.stack, time: new Date() }); // 使用Prisma模型方法更新日志 await prisma.fisImportLog.update({ where: { fisImportLogGUID: logId }, data: { Success: 0, Message: errorMsg } }); } catch (logErr: any) { console.log('FIS Import *Log* Error Message: ' + logErr); // 调用通知服务 } } finally { // 长期运行服务可忽略此步骤,短期脚本建议关闭连接释放资源 await prisma.$disconnect(); }
若必须使用Raw Query的处理方式
如果业务需求必须用Raw Query,需确保错误信息是处理后的纯字符串,通过参数绑定传入:
// 先处理错误信息为纯字符串 const errorMsg = `Error at: ${msg}. ${err.message}`; await prisma.$executeRaw` UPDATE FisImportLog SET Success = 0, Message = ${errorMsg} WHERE FisImportLogGUID = ${logId}; `;
内容的提问来源于stack exchange,提问作者spacedog
相关产品推荐
相关产品推荐

