You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:01:04