一、Node.js 连接 SQL Server
安装数据库驱动
bash
npm install mssql
重点理解:
Node.js 并不直接操作数据库,而是通过 数据库驱动 与 SQL Server 通信。
mssql 驱动到底是什么?
可以把 mssql 驱动理解成:翻译官
Node.js 语言 → JavaScript
SQL Server → T-SQL 协议
两者语言不同。
所以需要一个 中间层。
架构如下:
bash
Node.js 代码
↓
mssql 驱动
↓
SQL Server 网络协议 (TDS)
↓
SQL Server 数据库
流程:
bash
Node.js 发送 SQL
↓
mssql 驱动封装请求
↓
通过 TCP 发送给 SQL Server
↓
SQL Server 执行 SQL
↓
返回数据
↓
mssql 驱动解析结果
↓
Node.js 得到 JS 对象
Node.js 如何连接数据库
连接数据库本质就是:建立 TCP 连接
SQL Server 默认端口:1433
连接时需要提供配置:
javascript
const sql = require('mssql')
const config = {
user: 'sa',
password: '123456',
server: 'localhost',
database: 'testdb',
options: {
encrypt: false,
trustServerCertificate: true
}
}
配置解释:
| 配置 | 作用 |
|---|---|
| user | 登录用户名 |
| password | 登录密码 |
| server | 数据库服务器地址 |
| database | 使用哪个数据库 |
| encrypt | 是否加密 |
| trustServerCertificate | 信任证书 |
真正建立连接
javascript
async function connectDB() {
try {
await sql.connect(config)
console.log('数据库连接成功')
} catch (err) {
console.log('数据库连接失败', err)
}
}
核心代码:
javascript
await sql.connect(config)
发生的事情:
bash
1 Node.js 调用 mssql
2 mssql 创建 TCP 连接
3 连接 SQL Server 1433端口
4 发送登录信息
5 SQL Server 验证账号
6 连接成功
使用 async / await 查询数据库
查询示例:
javascript
const result = await sql.query('SELECT * FROM Users')
执行流程:
bash
Node.js 执行 query
↓
mssql 发送 SQL
↓
SQL Server 执行 SQL
↓
返回数据表
↓
mssql 转成 JS 对象
↓
返回 result
返回结果结构:
bash
{
recordset: [
{ id: 1, name: 'Tom', age: 20 },
{ id: 2, name: 'Jack', age: 25 }
]
}
真正的数据在:
bash
result.recordset
为什么要用 async / await
数据库查询是:网络 IO 操作
特点:需要时间
不能阻塞 Node.js
所以是 异步操作。
旧写法:
javascript
sql.query('SELECT * FROM Users')
.then(result => console.log(result))
.catch(err => console.log(err))
现代写法:
javascript
const result = await sql.query('SELECT * FROM Users')
配合:
javascript
try {} catch {}
更清晰。
数据库连接错误处理
连接数据库可能失败:
原因很多:
| 错误 | 原因 |
|---|---|
| 用户名密码错误 | 登录失败 |
| 数据库没启动 | 服务未运行 |
| 端口被防火墙阻止 | 连接失败 |
| 数据库不存在 | DB 错误 |
所以必须写:
javascript
try {
await sql.connect(config)
} catch (err) {
console.error(err)
}
否则程序可能直接崩溃。
重点理解(最重要的一句话)
你必须建立这个认知:
bash
Node.js 不会操作数据库文件
Node.js 只会:发送 SQL 语句
真正做事的是:SQL Server
职责分工:
| 系统 | 负责 |
|---|---|
| Node.js | 业务逻辑 |
| SQL Server | 数据存储 |
| mssql 驱动 | 通信桥梁 |
二、建立数据库连接池
什么是连接池(Connection Pool)
连接池的思想其实很简单:提前创建一批数据库连接
然后:
bash
需要查询 → 从池里拿一个连接
查询结束 → 归还连接
结构如下:
bash
┌─────────────┐
│ Connection1 │
│ Connection2 │
│ Connection3 │
│ Connection4 │
└─────────────┘
↑
Connection Pool
↑
Node.js
流程:
bash
请求1 → 连接1
请求2 → 连接2
请求3 → 连接3
请求4 → 连接1(复用)
所以:连接不会反复创建 而是:重复利用
连接池的优势
| 优势 | 解释 |
|---|---|
| 提升性能 | 避免重复创建连接 |
| 减少数据库压力 | 连接数量可控 |
| 提高并发能力 | 多个连接同时执行 |
| 更稳定 | 不会频繁连接/断开 |
所以必须使用连接池
创建全局连接池
正确写法:
创建一个 db 模块
项目结构:
bash
project
├── db
│ └── index.js
├── routes
├── controllers
└── app.js
db/index.js:
bash
const sql = require('mssql')
const config = {
user: 'sa',
password: '123456',
server: 'localhost',
database: 'testdb',
options: {
encrypt: false,
trustServerCertificate: true
}
}
const pool = new sql.ConnectionPool(config)
const poolConnect = pool.connect()
module.exports = {
sql,
pool,
poolConnect
}
Controller 使用数据库
javascript
const { pool, poolConnect } = require('../db')
async function getUsers(req, res) {
try {
await poolConnect
const result = await pool
.request()
.query('SELECT * FROM Users')
res.json(result.recordset)
} catch (err) {
res.status(500).json({ error: err.message })
}
}
module.exports = {
getUsers
}
三、实战
1.创建项目
bash
mkdir day10-sqlserver-crud
cd day10-sqlserver-crud
npm init -y
2.安装依赖
bash
npm install express mssql
作用:
| 包 | 作用 |
|---|---|
| express | Web API 框架 |
| mssql | SQL Server 驱动 |
3.创建项目结构
创建目录结构:
bash
day10-sqlserver-crud
│
├── db
│ └── index.js
│
├── controllers
│ └── userController.js
│
├── routes
│ └── userRoutes.js
│
├── app.js
└── package.json
按照结构创建文件
4.创建数据库表
bash
CREATE DATABASE testdb;
GO
USE testdb;
GO
CREATE TABLE Users (
id INT PRIMARY KEY IDENTITY(1,1),
name NVARCHAR(50),
age INT
);
5.编写数据库连接模块
db/index.js
javascript
const sql = require('mssql')
const config = {
user: 'sa',
password: '123456',
server: 'localhost',
database: 'testdb',
options: {
encrypt: false,
trustServerCertificate: true
}
}
const pool = new sql.ConnectionPool(config)
const poolConnect = pool.connect()
module.exports = {
sql,
pool,
poolConnect
}
这里做了三件事:
创建数据库配置
创建连接池
导出连接池
整个项目 只创建这一个连接池。
6.编写 Controller
controllers/userController.js
javascript
const { pool, poolConnect } = require('../db')
async function getUsers(req, res) {
try {
await poolConnect
const result = await pool
.request()
.query('SELECT * FROM Users')
res.json(result.recordset)
} catch (err) {
res.status(500).json({ error: err.message })
}
}
module.exports = {
getUsers
}
7.编写路由
routes/userRoutes.js
javascript
const express = require('express')
const router = express.Router()
const { getUsers } = require('../controllers/userController')
router.get('/users', getUsers)
module.exports = router
8.创建 Express 服务器
app.js
javascript
const express = require('express')
const app = express()
const userRoutes = require('./routes/userRoutes')
app.use(express.json())
app.use('/', userRoutes)
app.listen(3000, () => {
console.log('server running at http://localhost:3000')
})
9.启动服务器
bash
node app.js
server running at http://localhost:3000