NodeJS中如何让app.get实现多表查询或多数据库操作?
NodeJS+EJS+MySQL项目多查询渲染页面问题解答
问题描述
我正在进行大学期末项目,采用NodeJS、EJS、MySQL技术栈。原本使用内连接查询users表与type_users表,导致下拉列表显示全部三种用户类型(不符合需求)。尝试在app.get中同时执行两个独立数据库查询(分别查询type_users表和users表)并渲染页面,但不确定写法是否可行,希望得到指导。
原内连接查询代码
connection.query('SELECT u.id_users,u.name_users,u.surname_users,u.email_users, t.desc_typeusers FROM users u INNER JOIN type_users t ON u.id_type_users = t.id_type_users', function(error, results){ if(error){ console.log(error); } else{ res.render("./admuser", { usert:'Express', desc_typeusers_data: results, results:results } ); } }) })
尝试的错误多查询写法
connection.query('SELECT desc_typeusers FROM type_users', function(error, data){ if(error){ console.log(error); } else{ res.render("./admuser",{usert:'Express', desc_typeusers_data: data}); } } ,connection.query('SELECT * FROM users', (error, results)=>{ if(error){ console.log(error); }else{ res.render('./admuser',{ results:results },{ usert:'Express', desc_typeusers_data: data }) } }) ) })
问题分析
你尝试的写法存在多个致命问题:
connection.query不支持这种参数传递方式,第二个参数必须是回调函数,你直接传入另一个connection.query的执行结果,逻辑完全错误。- 两次调用
res.render会触发报错,因为一个HTTP请求只能发送一次响应,第二次调用时响应已经完成发送。 - 第二个查询中的
data变量是第一个查询回调的局部变量,根本无法访问到。
另外,原内连接的问题在于:你把用户数据和关联的类型数据混在一起,desc_typeusers_data用的是内连接结果,里面的类型会和用户条目重复,且如果某个类型没有被任何用户使用,就不会出现在结果里。而你需要下拉显示所有可用用户类型,必须单独查询type_users表,再获取用户列表,将两个独立数据传给EJS模板。
正确写法指导
方法1:嵌套回调(简单直接,适合小项目)
通过嵌套回调保证查询顺序,最后一次渲染页面传递所有数据:
app.get('/admuser', (req, res) => { // 先查询所有用户类型 connection.query('SELECT desc_typeusers FROM type_users', (error, typeData) => { if (error) { console.log(error); return res.status(500).send('查询用户类型失败'); } // 再查询用户列表 connection.query('SELECT * FROM users', (error, userData) => { if (error) { console.log(error); return res.status(500).send('查询用户列表失败'); } // 一次性渲染页面,传递两个查询结果 res.render('./admuser', { usert: 'Express', desc_typeusers_data: typeData, results: userData }); }); }); });
方法2:Promise+Async/Await(避免回调地狱,代码更清晰)
先将connection.query封装为Promise,再用async/await并行执行查询:
// 封装查询为Promise function dbQuery(sql) { return new Promise((resolve, reject) => { connection.query(sql, (error, results) => { if (error) reject(error); else resolve(results); }); }); } // 路由处理 app.get('/admuser', async (req, res) => { try { // 并行执行两个查询,提高效率 const [typeData, userData] = await Promise.all([ dbQuery('SELECT desc_typeusers FROM type_users'), dbQuery('SELECT * FROM users') ]); // 渲染页面 res.render('./admuser', { usert: 'Express', desc_typeusers_data: typeData, results: userData }); } catch (error) { console.log(error); res.status(500).send('查询失败'); } });
方法3:MySQL多语句查询(不推荐,存在安全风险)
如果开启了MySQL多语句支持,可以一次执行两个查询,但需注意SQL注入风险:
connection.query('SELECT desc_typeusers FROM type_users; SELECT * FROM users;', (error, results) => { if (error) { console.log(error); return res.status(500).send('查询失败'); } // results是数组,第一个元素是用户类型结果,第二个是用户列表结果 const typeData = results[0]; const userData = results[1]; res.render('./admuser', { usert: 'Express', desc_typeusers_data: typeData, results: userData }); });
注意:开启多语句查询会增加SQL注入风险,若项目中有用户输入参数,强烈不建议使用此方法。
内容的提问来源于stack exchange,提问作者Sofia Blanco Sanchez
相关产品推荐
相关产品推荐

