返回文章列表

文章

关于自增id主键插入0的问题

目录
  1. 不同数据库对 “在自增(Auto‑Increment/IDENTITY/序列)主键列上插入 0” 的处理方式是不一样的,下面用中文分别说明几种常见引擎的行为:
  2. SQLite
  3. MySQL / MariaDB
  4. PostgreSQL
  5. INSERT INTO t DEFAULT VALUES; -- 或者 INSERT INTO t(id, ...) VALUES (DEFAULT, ...); ```
  6. SQL Server
  7. SET IDENTITY_INSERT t ON; ``` 然后再插入,才可以像普通列那样插入 0 或其他数字;这些手动插入的值不会改变下一次自增的起点。
  8. 小结

不同数据库对 “在自增(Auto‑Increment/IDENTITY/序列)主键列上插入 0” 的处理方式是不一样的,下面用中文分别说明几种常见引擎的行为:#

SQLite#

  • 表定义举例:

CREATE TABLE t ( id INTEGER PRIMARY KEY AUTOINCREMENT, ... ); ```

  • 行为 如果你写:

INSERT INTO t(id, ...) VALUES (0, ...); INSERT INTO t(id, ...) VALUES (NULL, ...); ``` SQLite 会把 0NULL 当作“请自动分配下一个 rowid”,插入时会忽略你给的 0,改用序列中下一个可用值。

  • 非零值 如果你显式插入一个非零的 id(比如 INSERT … VALUES(42, …)),SQLite 会直接使用 42(前提是不与已有 rowid 冲突)。

MySQL / MariaDB#

  • 表定义举例:

CREATE TABLE t ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ... ) ENGINE=InnoDB; ```

  • 行为 MySQL 也把 0NULL 视为“请求自增”:

INSERT INTO t(id, ...) VALUES (0, ...); INSERT INTO t(id, ...) VALUES (NULL, ...); ``` 这两种写法都会触发自增,分配下一个自增值。

  • 显式值 只要你插入的值非零(且不冲突),MySQL 会按你给的数字插入,并不会跳过或动用序列。

PostgreSQL#

  • 表定义举例(SERIALGENERATED):

CREATE TABLE t ( id SERIAL PRIMARY KEY, ... ); ```

  • 行为 在 PostgreSQL 里,你向 SERIAL(本质是序列)列插入 0,就会真的把 0 存进去——不会触发序列。 只有这样写才会用序列:

INSERT INTO t DEFAULT VALUES; -- 或者 INSERT INTO t(id, ...) VALUES (DEFAULT, ...); ```#

SQL Server#

  • 表定义举例:

CREATE TABLE t ( id INT IDENTITY(1,1) PRIMARY KEY, ... ); ```

  • 行为 默认情况下你不能IDENTITY 列插入任何值(包括 0),会报错。 如果你临时执行:

SET IDENTITY_INSERT t ON; ``` 然后再插入,才可以像普通列那样插入 0 或其他数字;这些手动插入的值不会改变下一次自增的起点。#

小结#

引擎插入 0NULL插入非零值触发自增逻辑
SQLite是(分配下一个)是(按值插入)0/NULL 自动,省略字段其他手工
MySQL是(分配下一个)是(按值插入)同 SQLite
PostgreSQL否(插入 0只省略字段或 DEFAULT
SQL Server报错(除非开启 IDENTITY_INSERT)同上只能通过省略字段触发

最佳实践:如果想让列使用自增,通常 不要 显式插入 id,直接省略该列或写成 DEFAULT,让数据库自己分配下一个值。