使用变量时MySQL插入语句无法写入数据库求助
问题分析与解决方案
核心问题
- 错误的事件绑定:按钮
onClick直接执行AddMember(),导致组件挂载时就触发函数,点击按钮时反而无效果,应传递函数引用而非立即执行。 - 异步函数未正确处理:
sql_query是异步函数,调用时未加await,导致数据库操作未完成就结束。 - 客户端直接操作数据库:Next.js客户端组件不能直接连接数据库,必须通过API路由完成服务端数据库操作,否则会暴露凭证且无法执行。
- SQL注入风险与参数绑定错误:用字符串拼接生成SQL语句,既不安全,也未利用
sql_query提供的参数绑定功能。 - 表单默认提交行为未阻止:按钮类型为
submit,点击会触发页面刷新,打断异步请求流程。 - 错误处理缺失:
sql_query的catch块为空,AddMember的错误抛出后无用户提示。
修正步骤
1. 创建API路由(服务端处理数据库操作)
在pages/api/members/add.js中创建接口,负责接收客户端请求并执行插入:
import { sql_query } from '../../../lib/db'; export default async function handler(req, res) { if (req.method === 'POST') { const { id, fullname } = req.body; try { const result = await sql_query( 'INSERT INTO members (id, Fullname) VALUES (?, ?)', [id, fullname] ); res.status(200).json({ success: true, data: result }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } } else { res.status(405).json({ success: false, error: '仅支持POST请求' }); } }
2. 修改AddForm组件(客户端调用API)
import React, { useState } from 'react'; import Link from 'next/link' export const AddForm = () => { const [fullname, setFullname] = useState('') const [id, setId] = useState('') async function handleSubmit(e) { e.preventDefault(); if (!id || !fullname) { alert('请填写完整信息'); return; } try { const response = await fetch('/api/members/add', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id, fullname }), }); const data = await response.json(); if (data.success) { alert('成员添加成功'); setId(''); setFullname(''); } else { alert(`添加失败: ${data.error}`); } } catch (error) { alert(`请求出错: ${error.message}`); } } return ( <> <div className="border h-20"> <h1 className="p-5 font-bold text-red-500">添加成员</h1> </div> <div className="fixed top-0 left-0 w-screen h-screen flex items-center justify-center"> <div className="flex flex-col items-end"> <Link href="/members"> <button className="bg-white rounded-full w-10 h-10 text-center p-2 m-2 left-0 hover:rotate-180 origin-center transition-all">X</button> </Link> <form onSubmit={handleSubmit} className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"> <div className="flex mb-2"> <div className="pr-5"> <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="id">ID </label> <input className="shadow appearance-none border rounded py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none" onChange={e => setId(e.target.value)} id="id" name='id' type="number" placeholder="身份证号码" value={id} ></input> </div> <div className="pr-5"> <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="fullname">姓名</label> <input className="shadow appearance-none border rounded w-96 py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" onChange={e => setFullname(e.target.value)} id="fullname" name='fullname' type="text" placeholder="姓名" value={fullname} ></input> </div> </div> <button type="submit" className="bg-red-500 rounded-full p-2 text-white hover:bg-red-400">添加成员</button> </form> </div> </div> </> ) } export default AddForm;
3. 完善数据库连接文件的错误处理
修改lib/db.js的sql_query函数,确保错误被抛出:
import mysql from 'serverless-mysql' export const db = mysql({ config: { host: process.env.MYSQL_HOST, database: process.env.MYSQL_DATABASE, user: process.env.MYSQL_USERNAME, password: process.env.MYSQL_PASSWORD, } }) export async function sql_query(query_string, values = []) { try { const results = await db.query(query_string, values) await db.end() return results } catch (error) { throw error; } }
关键说明
- API路由:Next.js的API路由运行在服务端,安全处理数据库操作,避免客户端暴露敏感信息。
- 参数绑定:使用
?作为占位符配合参数数组,防止SQL注入,同时保证数据类型正确。 - 异步处理:所有异步操作添加
await,确保操作完成后再执行后续逻辑。 - 表单处理:使用
onSubmit绑定提交函数,阻止默认刷新行为,提升用户体验。
内容的提问来源于stack exchange,提问作者Nor
相关产品推荐
相关产品推荐

