Mikro-ORM执行原生SQL报there is no parameter $1错误怎么解决?
错误原因
PostgreSQL返回42P02错误代表参数引用不存在,本质是MikroORM的execute方法默认不识别$1风格的位置占位符,你编写的占位符没有被替换直接透传到数据库,导致数据库找不到对应绑定参数。
解决方案
方案1:使用默认问号占位符
将SQL中的占位符替换为?,参数数组顺序和占位符顺序一一对应即可:
@Query(() => String) async Conversations(@Ctx() { em, userData }: MyContext): Promise<string> { const connection = em.getConnection(); // 把$1替换为?,两个占位符对应两个相同参数 const queryString = `SELECT DISTINCT * FROM direct_messages WHERE receiver_id = ? OR sender_id = ? ORDER BY sent_at DESC`; return await connection .execute(queryString, [userData['sub'], userData['sub']]) .then((results) => { console.log(results); return 'worked'; }) .catch((error) => { console.log(error); return 'Failed'; }); }
方案2:使用命名参数(更适合重复参数场景)
用:参数名格式做占位符,参数传对象,同一个参数多次引用不需要重复传值:
@Query(() => String) async Conversations(@Ctx() { em, userData }: MyContext): Promise<string> { const connection = em.getConnection(); const queryString = `SELECT DISTINCT * FROM direct_messages WHERE receiver_id = :userId OR sender_id = :userId ORDER BY sent_at DESC`; return await connection .execute(queryString, { userId: userData['sub'] }) .then((results) => { console.log(results); return 'worked'; }) .catch((error) => { console.log(error); return 'Failed'; }); }
方案3:开启原生位置占位符支持
如果要保留$1风格的写法,给execute方法最后一个参数传true开启位置参数识别即可:
@Query(() => String) async Conversations(@Ctx() { em, userData }: MyContext): Promise<string> { const connection = em.getConnection(); const queryString = `SELECT DISTINCT * FROM direct_messages WHERE receiver_id = $1 OR sender_id = $1 ORDER BY sent_at DESC`; // 最后一个参数设为true启用$n格式的位置占位符 return await connection .execute(queryString, [userData['sub']], true, true, true) .then((results) => { console.log(results); return 'worked'; }) .catch((error) => { console.log(error); return 'Failed'; }); }
内容的提问来源于stack exchange,提问作者BigBellyBigDreams
相关产品推荐
相关产品推荐

