如何创建带主键的MySQL数据表

作者:袖梨 2026-09-01

主键必须显式声明NOT NULL且唯一,推荐用INT/BIGINT AUTO_INCREMENT;字符串主键需指定长度,禁用TEXT/BLOB;UUID应存为BINARY(16)以提升性能。

主键必须是 NOT NULL 且唯一

MySQL 要求主键列不能为 NULL,也不能重复。如果你在建表时给主键列写了 NULL 或漏写 NOT NULL,MySQL 会自动补上——但别依赖这个行为,显式声明更安全。

常见错误:用 VARCHAR 字段当主键却没设长度,或用 TEXT 类型(不支持索引),直接报错 ERROR 1170 (42000): BLOB/TEXT column 'xxx' used in key specification without a key length

  1. 主键字段必须声明为 NOT NULL(即使不写,MySQL 也会强制,但建议明写)
  2. 字符串主键必须指定长度,比如 id VARCHAR(32) PRIMARY KEY,不能只写 VARCHAR
  3. 避免用 TEXTBLOBJSON 做主键——它们不支持索引定义

推荐用自增整数做主键:INT + AUTO_INCREMENT

除非业务强要求(如分布式 ID、UUID),否则优先选 INTBIGINT 配合 AUTO_INCREMENT。它高效、紧凑、天然有序,且 MySQL 对其优化最成熟。

注意:AUTO_INCREMENT 必须搭配 PRIMARY KEYUNIQUE KEY 使用,且该列要为索引列;如果建表后想加,得先加索引再改属性。

  1. id INT PRIMARY KEY AUTO_INCREMENT 是最简写法,等价于 id INT NOT NULL PRIMARY KEY AUTO_INCREMENT
  2. 自增值默认从 1 开始,可通过 ALTER TABLE tbl AUTO_INCREMENT = 100 调整起始值
  3. 插入时若显式指定 id 值(如 INSERT INTO t(id) VALUES(5)),后续自增会从该值+1继续,不是“跳过”

用 UUID 或雪花 ID 当主键?注意性能和排序问题

如果用 UUID() 或外部生成的字符串 ID(如 CHAR(36)BINARY(16)),主键就失去顺序性,会导致频繁页分裂、插入变慢、索引碎片多。

真正要用 UUID,建议转成二进制存:id BINARY(16) PRIMARY KEY DEFAULT (UNHEX(REPLACE(UUID(), '-', ''))),比字符串节省一半空间,查询也更快。

  1. 别用 UUID() 函数直接存字符串 —— CHAR(36) 太宽,索引体积大,缓存效率低
  2. ORDER BY id 在 UUID 主键上基本无业务意义,时间顺序无法保证
  3. 如果已有业务用 UUID 字符串,至少加前缀索引,如 INDEX idx_id_prefix (id(8)),但不如换二进制方案彻底

建表语句里定义主键的三种常见写法

主键可以在列定义内声明,也可以在表级约束中声明。两种都合法,但语义和可读性不同。列级写法更紧凑,表级写法方便多列联合主键。

错误示范:CREATE TABLE t (id INT, PRIMARY KEY (id)); 看似没问题,但如果 id 没写 NOT NULL,MySQL 会隐式加上——但你代码里没体现,容易误导协作者。

  1. 列级定义(推荐单列主键):id BIGINT PRIMARY KEY AUTO_INCREMENT
  2. 表级定义(适合联合主键):PRIMARY KEY (user_id, order_id)
  3. 命名主键约束(便于后期管理):CONSTRAINT pk_user PRIMARY KEY (id),这样删主键时可以用 DROP PRIMARY KEYDROP CONSTRAINT pk_user(取决于版本)
实际建表时,别为了“看起来简洁”省略 NOT NULL 或忽略类型长度限制。主键设计一旦上线,后期改起来代价远高于初期多敲几个字符。

相关文章

精彩推荐