字段校验规则清单:必填/范围/唯一/组合唯一/正则(附校验表)

前言

字段校验是防止脏数据的第一道防线。很多线上问题都是因为校验不全:没有校验长度、没有校验格式、没有校验唯一性。这篇给你完整的校验规则清单+校验表模板。使用

一、6类校验规则

校验类型 说明 示例 错误提示
必填 字段不能为空 用户名必填 请输入用户名
长度 字符串长度限制 3-20个字符 用户名长度为3-20个字符
范围 数值范围限制 0-100 数值必须在0-100之间
唯一 字段值不能重复 手机号唯一 该手机号已存在
组合唯一 多个字段组合不能重复 商品+规格唯一 该规格组合已存在
正则 格式校验 邮箱格式 邮箱格式不正确

二、校验规则模板

必填校验

复制代码
字段名:用户名
是否必填:是
前端校验:提交时检查,为空则提示
后端校验:参数校验,为空返回400
错误提示:请输入用户名

长度校验

复制代码
字段名:用户名
长度限制:3-20个字符
前端校验:输入时实时提示
后端校验:参数校验,超长返回400
错误提示:用户名长度为3-20个字符

范围校验

复制代码
字段名:年龄
范围限制:≥0 且 ≤150
前端校验:输入时检查
后端校验:参数校验,超范围返回400
错误提示:年龄必须在0-150之间

唯一性校验

复制代码
字段名:手机号
唯一性要求:全局唯一
前端校验:失焦时调用接口检查
后端校验:数据库唯一索引
错误提示:该手机号已注册

组合唯一性校验

复制代码
字段名:商品SKU
组合唯一:商品ID + 颜色 + 尺码
前端校验:选择规格时检查
后端校验:数据库联合唯一索引
错误提示:该规格组合已存在

正则校验

复制代码
字段名:邮箱
正则表达式:^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$
前端校验:失焦时检查
后端校验:参数校验
错误提示:邮箱格式不正确

字段名:手机号
正则表达式:^1[3-9]\d{9}$
错误提示:手机号格式不正确

字段名:身份证号
正则表达式:^\d{17}[\dXx]$
错误提示:身份证号格式不正确

三、校验表模板

字段名 必填 长度 范围 唯一 正则 错误提示
用户名 3-20 - ^[a-zA-Z0-9_]+$ 用户名已存在
密码 6-20 - - 密码长度为6-20个字符
手机号 11 - ^1[3-9]\d{9}$ 手机号已注册
年龄 - 0-150 - 年龄必须在0-150之间

四、校验实现步骤

步骤1:前端校验

在表单提交前进行前端校验,提供即时反馈。

复制代码
前端校验示例(JavaScript):
// 必填校验
function validateRequired(value, fieldName) {
    if (!value || value.trim() === '') {
        return `${fieldName}不能为空`;
    }
    return null;
}

// 长度校验
function validateLength(value, min, max, fieldName) {
    if (value.length < min || value.length > max) {
        return `${fieldName}长度为${min}-${max}个字符`;
    }
    return null;
}

// 范围校验
function validateRange(value, min, max, fieldName) {
    const num = Number(value);
    if (isNaN(num) || num < min || num > max) {
        return `${fieldName}必须在${min}-${max}之间`;
    }
    return null;
}

// 正则校验
function validateRegex(value, regex, fieldName, errorMsg) {
    if (!regex.test(value)) {
        return errorMsg || `${fieldName}格式不正确`;
    }
    return null;
}

// 唯一性校验(异步)
async function validateUnique(value, apiUrl, fieldName) {
    const response = await fetch(`${apiUrl}?value=${value}`);
    const data = await response.json();
    if (data.exists) {
        return `${fieldName}已存在`;
    }
    return null;
}

步骤2:后端校验

在接口层进行后端校验,确保数据安全。

复制代码
后端校验示例(Node.js Express):
const { body, validationResult } = require('express-validator');

// 校验规则
const validateUser = [
    body('username')
        .notEmpty().withMessage('用户名不能为空')
        .isLength({ min: 3, max: 20 }).withMessage('用户名长度为3-20个字符')
        .matches(/^[a-zA-Z0-9_]+$/).withMessage('用户名只能包含字母、数字、下划线'),
    
    body('phone')
        .notEmpty().withMessage('手机号不能为空')
        .matches(/^1[3-9]\d{9}$/).withMessage('手机号格式不正确')
        .custom(async (value) => {
            const exists = await checkPhoneExists(value);
            if (exists) {
                throw new Error('手机号已注册');
            }
        }),
    
    body('age')
        .optional()
        .isInt({ min: 0, max: 150 }).withMessage('年龄必须在0-150之间'),
    
    (req, res, next) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(400).json({
                code: 400,
                message: '参数校验失败',
                errors: errors.array()
            });
        }
        next();
    }
];

// 使用
app.post('/api/users', validateUser, createUser);

步骤3:数据库约束

在数据库层添加约束,作为最后一道防线。

复制代码
数据库约束示例(MySQL):
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(20) NOT NULL COMMENT '用户名',
    phone VARCHAR(11) NOT NULL COMMENT '手机号',
    email VARCHAR(100) COMMENT '邮箱',
    age INT COMMENT '年龄',
    
    -- 唯一性约束
    UNIQUE KEY uk_username (username),
    UNIQUE KEY uk_phone (phone),
    
    -- 检查约束(MySQL 8.0+)
    CHECK (LENGTH(username) >= 3 AND LENGTH(username) <= 20),
    CHECK (phone REGEXP '^1[3-9][0-9]{9}$'),
    CHECK (age IS NULL OR (age >= 0 AND age <= 150))
) COMMENT='用户表';

五、常用正则表达式

基础正则表达式

复制代码
手机号:^1[3-9]\d{9}$
邮箱:^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$
身份证:^\d{17}[\dXx]$
URL:^https?://[^\s]+$
IP地址:^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
日期(YYYY-MM-DD):^\d{4}-\d{2}-\d{2}$
中文:^[\u4e00-\u9fa5]+$
数字:^\d+$
字母:^[a-zA-Z]+$
字母数字:^[a-zA-Z0-9]+$

复杂正则表达式

复制代码
银行卡号:^\d{16,19}$(16-19位数字)
密码(6-20位,包含字母和数字):^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z0-9]{6,20}$
密码(6-20位,包含大小写字母、数字、特殊字符):
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,20}$
时间(HH:mm:ss):^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$
日期时间(YYYY-MM-DD HH:mm:ss):
^\d{4}-\d{2}-\d{2} ([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$
金额(最多2位小数):^\d+(\.\d{1,2})?$
百分比(0-100,最多2位小数):^(100(\.0{1,2})?|([0-9]|[1-9][0-9])(\.\d{1,2})?)$

六、实际案例

案例1:用户注册校验

**业务场景:**用户注册时需要校验用户名、手机号、密码等字段。

复制代码
校验规则:

| 字段名 | 必填 | 长度 | 范围 | 唯一 | 正则 | 错误提示 |
|--------|------|------|------|------|------|---------|
| 用户名 | 是 | 3-20 | - | 是 | ^[a-zA-Z0-9_]+$ | 用户名已存在 |
| 密码 | 是 | 6-20 | - | 否 | ^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z0-9]{6,20}$ | 密码必须包含字母和数字 |
| 手机号 | 是 | 11 | - | 是 | ^1[3-9]\d{9}$ | 手机号已注册 |
| 邮箱 | 否 | - | - | 是 | ^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$ | 邮箱格式不正确 |
| 年龄 | 否 | - | 0-150 | 否 | - | 年龄必须在0-150之间 |

校验顺序:
1. 前端校验:提交时检查必填、长度、格式
2. 后端校验:接口层校验所有规则
3. 数据库约束:唯一性约束、检查约束

案例2:商品信息校验

**业务场景:**商品创建时需要校验商品名称、价格、库存等字段。

复制代码
校验规则:

| 字段名 | 必填 | 长度 | 范围 | 唯一 | 正则 | 错误提示 |
|--------|------|------|------|------|------|---------|
| 商品名称 | 是 | 1-100 | - | 否 | - | 商品名称不能为空 |
| 商品价格 | 是 | - | ≥0.01, ≤999999.99 | 否 | ^\d+(\.\d{1,2})?$ | 价格必须在0.01-999999.99之间 |
| 库存数量 | 是 | - | ≥0, ≤999999 | 否 | ^\d+$ | 库存数量必须在0-999999之间 |
| 商品SKU | 是 | - | - | 组合唯一(商品ID+颜色+尺码) | - | 该规格组合已存在 |
| 商品图片 | 是 | - | - | 否 | - | 商品图片不能为空 |

组合唯一校验:
- 商品ID + 颜色 + 尺码:组合唯一
- 数据库:UNIQUE KEY uk_sku (product_id, color, size)

案例3:订单信息校验

**业务场景:**订单创建时需要校验订单金额、收货地址等字段。

复制代码
校验规则:

| 字段名 | 必填 | 长度 | 范围 | 唯一 | 正则 | 错误提示 |
|--------|------|------|------|------|------|---------|
| 订单金额 | 是 | - | ≥0.01 | 否 | ^\d+(\.\d{1,2})?$ | 订单金额不能为空 |
| 收货人 | 是 | 1-50 | - | 否 | - | 收货人不能为空 |
| 收货手机 | 是 | 11 | - | 否 | ^1[3-9]\d{9}$ | 手机号格式不正确 |
| 收货地址 | 是 | 1-200 | - | 否 | - | 收货地址不能为空 |
| 备注 | 否 | ≤500 | - | 否 | - | 备注不能超过500个字符 |

业务校验:
- 订单金额 = 商品总价(需要后端校验)
- 库存是否充足(需要后端校验)

七、常见错误

错误1:只做前端校验

**问题:**只在前端校验,后端不校验,用户可以直接调用接口绕过。

复制代码
❌ 错误示例:
前端:校验用户名长度3-20
后端:不校验,直接保存

问题:用户可以直接调用接口,传入1个字符的用户名。

✅ 正确示例:
前端:校验用户名长度3-20(用户体验优化)
后端:校验用户名长度3-20(安全控制)
数据库:CHECK约束(最后一道防线)

错误2:唯一性校验不完整

**问题:**只在前端或后端校验唯一性,没有数据库唯一索引。

复制代码
❌ 错误示例:
前端:失焦时调用接口检查唯一性
后端:查询数据库检查唯一性
数据库:没有唯一索引

问题:并发情况下,可能插入重复数据。

✅ 正确示例:
前端:失焦时调用接口检查(用户体验优化)
后端:查询数据库检查(业务校验)
数据库:唯一索引(最后一道防线)

CREATE TABLE users (
    username VARCHAR(20) NOT NULL,
    UNIQUE KEY uk_username (username)  -- 唯一索引
);

错误3:校验规则不一致

**问题:**前端和后端的校验规则不一致,导致用户体验差。

复制代码
❌ 错误示例:
前端:用户名长度3-20
后端:用户名长度5-20

问题:前端校验通过,后端校验失败,用户体验差。

✅ 正确示例:
前端和后端使用相同的校验规则:
- 使用配置文件统一管理校验规则
- 前端和后端共享配置
- 校验规则变更时同步更新

错误4:错误提示不明确

**问题:**错误提示不明确,用户不知道如何修改。

复制代码
❌ 错误示例:
错误提示:"输入错误"
问题:用户不知道哪里错了,如何修改。

✅ 正确示例:
错误提示:"用户名长度为3-20个字符,只能包含字母、数字、下划线"
说明:明确告诉用户规则,便于修改。

错误5:组合唯一性校验缺失

**问题:**需要组合唯一性的字段,只校验单个字段唯一性。

复制代码
❌ 错误示例:
商品SKU:只校验商品ID唯一性

问题:同一个商品可以有多个SKU(不同颜色、尺码)。

✅ 正确示例:
商品SKU:组合唯一(商品ID + 颜色 + 尺码)
数据库:UNIQUE KEY uk_sku (product_id, color, size)

八、最佳实践

实践1:三层校验

前端、后端、数据库三层校验,确保数据安全。

复制代码
三层校验:
1. 前端校验:用户体验优化,即时反馈
2. 后端校验:安全控制,防止绕过
3. 数据库约束:最后一道防线,数据完整性

✓ 正确做法:
- 前端:校验必填、长度、格式(用户体验)
- 后端:校验所有规则(安全控制)
- 数据库:唯一索引、检查约束(数据完整性)

✗ 错误做法:
- 只做前端校验
- 只做后端校验
- 不做数据库约束

实践2:校验规则配置化

将校验规则配置化,统一管理,便于维护。

复制代码
配置化方式:
- 使用JSON或YAML配置文件
- 前端和后端共享配置
- 校验规则变更时同步更新

示例(validation-rules.json):
{
  "username": {
    "required": true,
    "minLength": 3,
    "maxLength": 20,
    "pattern": "^[a-zA-Z0-9_]+$",
    "unique": true,
    "errorMessage": "用户名长度为3-20个字符,只能包含字母、数字、下划线"
  }
}

实践3:错误提示明确

错误提示要明确,告诉用户规则和如何修改。

复制代码
✓ 正确示例:
- "用户名长度为3-20个字符"
- "手机号格式不正确,请输入11位手机号"
- "该手机号已注册,请使用其他手机号"

✗ 错误示例:
- "输入错误"
- "格式不正确"
- "已存在"

实践4:异步唯一性校验

唯一性校验使用异步方式,避免阻塞用户输入。

复制代码
异步校验:
- 前端:失焦时调用接口检查唯一性
- 后端:查询数据库检查唯一性
- 数据库:唯一索引保证数据完整性

注意:
- 异步校验只是提示,不能完全依赖
- 最终校验在提交时进行
- 数据库唯一索引是最后一道防线

九、FAQ

Q1:前端校验够吗?

**答:**不够。前端校验只是体验优化,后端必须校验。前端可以被绕过。

为什么前端校验不够:

  • **前端代码可修改:**用户可以通过浏览器开发者工具修改前端代码
  • **接口可直接调用:**用户可以直接调用接口,绕过前端限制
  • **网络请求可拦截:**用户可以通过抓包工具拦截和修改请求

正确的做法:

  • **前端校验:**用户体验优化,即时反馈
  • **后端校验:**安全控制,防止绕过
  • **数据库约束:**最后一道防线,数据完整性

Q2:唯一性校验在哪里做?

**答:**建议数据库唯一索引 + 后端校验。前端可以失焦时调用接口提前提示。

实现方式:

  • **前端:**失焦时调用接口检查唯一性(用户体验优化)

  • **后端:**提交时查询数据库检查唯一性(业务校验)

  • **数据库:**唯一索引保证数据完整性(最后一道防线)

    示例:
    // 前端:失焦时检查
    input.onblur = async function() {
    const value = this.value;
    const exists = await checkUnique(value);
    if (exists) {
    showError('该值已存在');
    }
    };

    // 后端:提交时检查
    app.post('/api/users', async (req, res) => {
    const { username } = req.body;
    const exists = await db.query('SELECT 1 FROM users WHERE username = ?', [username]);
    if (exists.length > 0) {
    return res.status(400).json({ message: '用户名已存在' });
    }
    // 保存数据
    });

    // 数据库:唯一索引
    CREATE TABLE users (
    username VARCHAR(20) NOT NULL,
    UNIQUE KEY uk_username (username)
    );

Q3:组合唯一性怎么实现?

**答:**使用数据库联合唯一索引实现组合唯一性。

实现方式:

  • **数据库:**创建联合唯一索引

  • **后端:**提交时查询数据库检查组合唯一性

  • **前端:**选择组合字段时检查组合唯一性

    示例:商品SKU组合唯一(商品ID + 颜色 + 尺码)

    // 数据库:联合唯一索引
    CREATE TABLE product_sku (
    product_id BIGINT NOT NULL,
    color VARCHAR(20) NOT NULL,
    size VARCHAR(20) NOT NULL,
    UNIQUE KEY uk_sku (product_id, color, size)
    );

    // 后端:检查组合唯一性
    app.post('/api/product-sku', async (req, res) => {
    const { product_id, color, size } = req.body;
    const exists = await db.query(
    'SELECT 1 FROM product_sku WHERE product_id = ? AND color = ? AND size = ?',
    [product_id, color, size]
    );
    if (exists.length > 0) {
    return res.status(400).json({ message: '该规格组合已存在' });
    }
    // 保存数据
    });

Q4:校验规则怎么管理?

**答:**建议将校验规则配置化,统一管理。

管理方式:

  • **配置文件:**使用JSON或YAML配置文件管理校验规则
  • **数据库:**使用数据库存储校验规则,支持动态管理
  • **代码常量:**使用代码常量定义校验规则(适合固定规则)

推荐方式:

  • **固定规则:**使用代码常量(如手机号、邮箱格式)
  • **业务规则:**使用配置文件或数据库(如长度、范围限制)

Q5:错误提示怎么写?

**答:**错误提示要明确,告诉用户规则和如何修改。

错误提示原则:

  • **明确规则:**告诉用户具体的规则(如长度、格式)

  • **提示修改:**告诉用户如何修改(如"请输入11位手机号")

  • **避免技术术语:**使用用户能理解的语言

    ✓ 正确示例:

    • "用户名长度为3-20个字符,只能包含字母、数字、下划线"
    • "手机号格式不正确,请输入11位手机号(如:13812345678)"
    • "该手机号已注册,请使用其他手机号或http://localhost:8000/login"

    ✗ 错误示例:

    • "输入错误"
    • "格式不正确"
    • "已存在"

Q6:校验性能如何优化?

**答:**可以通过缓存、异步校验、批量校验等方式优化性能。

优化方法:

  • **缓存校验结果:**缓存唯一性校验结果,减少数据库查询
  • **异步校验:**唯一性校验使用异步方式,不阻塞用户输入
  • **批量校验:**批量操作时,批量校验,减少接口调用
  • **前端预校验:**前端先校验格式,减少后端请求
相关推荐
NAGNIP7 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab8 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab8 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP12 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年12 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼12 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS12 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区14 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈14 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang14 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx