MySQL数据插入 #

一、INSERT语句概述 #

1.1 基本语法 #

sql
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);

1.2 示例表结构 #

sql
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT,
    email VARCHAR(100),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

二、基本插入 #

2.1 指定列插入 #

sql
INSERT INTO users (name, age, email)
VALUES ('John', 25, 'john@example.com');

2.2 全列插入 #

sql
INSERT INTO users
VALUES (NULL, 'Jane', 30, 'jane@example.com', NOW());

-- 自增列可以传NULL或0
INSERT INTO users
VALUES (0, 'Bob', 28, 'bob@example.com', DEFAULT);

2.3 省略列名 #

sql
-- 省略列名时,必须按表定义顺序提供所有列的值
INSERT INTO users
VALUES (NULL, 'Alice', 22, 'alice@example.com', NOW());

三、批量插入 #

3.1 多行插入 #

sql
INSERT INTO users (name, age, email) VALUES
    ('John', 25, 'john@example.com'),
    ('Jane', 30, 'jane@example.com'),
    ('Bob', 28, 'bob@example.com'),
    ('Alice', 22, 'alice@example.com');

3.2 批量插入优势 #

sql
-- 推荐方式:一条语句插入多行
INSERT INTO users (name, age, email) VALUES
    ('User1', 20, 'user1@example.com'),
    ('User2', 21, 'user2@example.com'),
    ('User3', 22, 'user3@example.com');

-- 不推荐:多条单行插入
INSERT INTO users (name, age, email) VALUES ('User1', 20, 'user1@example.com');
INSERT INTO users (name, age, email) VALUES ('User2', 21, 'user2@example.com');
INSERT INTO users (name, age, email) VALUES ('User3', 22, 'user3@example.com');

四、INSERT其他形式 #

4.1 INSERT SET语法 #

sql
INSERT INTO users
SET name = 'John',
    age = 25,
    email = 'john@example.com';

4.2 INSERT SELECT #

sql
-- 从其他表复制数据
INSERT INTO users_backup (name, age, email)
SELECT name, age, email FROM users;

-- 带条件复制
INSERT INTO users_2024 (name, age, email)
SELECT name, age, email 
FROM users 
WHERE YEAR(created_at) = 2024;

4.3 INSERT IGNORE #

sql
-- 忽略重复键错误
INSERT IGNORE INTO users (id, name, email)
VALUES (1, 'John', 'john@example.com');

-- 如果id=1已存在,不会报错,只是跳过

4.4 ON DUPLICATE KEY UPDATE #

sql
-- 如果存在则更新,不存在则插入
INSERT INTO users (id, name, age, email)
VALUES (1, 'John', 25, 'john@example.com')
ON DUPLICATE KEY UPDATE
    name = VALUES(name),
    age = VALUES(age),
    email = VALUES(email);

-- MySQL 8.0+ 新语法
INSERT INTO users (id, name, age, email)
VALUES (1, 'John', 25, 'john@example.com') AS new
ON DUPLICATE KEY UPDATE
    name = new.name,
    age = new.age,
    email = new.email;

4.5 REPLACE INTO #

sql
-- 如果存在则删除后插入,不存在则插入
REPLACE INTO users (id, name, age, email)
VALUES (1, 'John', 26, 'john@example.com');

-- 注意:REPLACE会删除旧行再插入新行
-- 自增ID会改变

五、插入默认值 #

5.1 使用DEFAULT #

sql
INSERT INTO users (name, age, email, created_at)
VALUES ('John', 25, 'john@example.com', DEFAULT);

-- created_at使用默认值CURRENT_TIMESTAMP

5.2 省略有默认值的列 #

sql
-- age有默认值0,created_at有默认值
INSERT INTO users (name, email)
VALUES ('John', 'john@example.com');

六、插入NULL值 #

6.1 显式插入NULL #

sql
INSERT INTO users (name, age, email)
VALUES ('John', NULL, 'john@example.com');

6.2 省略允许NULL的列 #

sql
-- 如果age允许NULL,可以省略
INSERT INTO users (name, email)
VALUES ('John', 'john@example.com');

七、插入特殊值 #

7.1 插入表达式 #

sql
INSERT INTO users (name, age, email, created_at)
VALUES ('John', 25, 'john@example.com', NOW());

INSERT INTO products (name, price, discount_price)
VALUES ('Product', 100.00, 100.00 * 0.9);

7.2 插入函数结果 #

sql
INSERT INTO logs (message, created_at)
VALUES ('System started', CURRENT_TIMESTAMP);

INSERT INTO users (name, uuid)
VALUES ('John', UUID());

八、获取插入ID #

8.1 LAST_INSERT_ID() #

sql
INSERT INTO users (name, age, email)
VALUES ('John', 25, 'john@example.com');

SELECT LAST_INSERT_ID();
-- 返回最后插入的自增ID

-- 在应用程序中使用
-- PHP: $id = $pdo->lastInsertId();
// Java: long id = statement.getGeneratedKeys();

8.2 批量插入获取ID #

sql
INSERT INTO users (name, age, email) VALUES
    ('User1', 20, 'user1@example.com'),
    ('User2', 21, 'user2@example.com'),
    ('User3', 22, 'user3@example.com');

SELECT LAST_INSERT_ID();
-- 返回第一个插入的ID
-- 后续ID依次递增

九、插入性能优化 #

9.1 批量插入 #

sql
-- 推荐:一次插入多行
INSERT INTO users (name, age, email) VALUES
    ('User1', 20, 'user1@example.com'),
    ('User2', 21, 'user2@example.com'),
    ('User3', 22, 'user3@example.com');

-- 不推荐:多次单行插入
INSERT INTO users (name, age, email) VALUES ('User1', 20, 'user1@example.com');
INSERT INTO users (name, age, email) VALUES ('User2', 21, 'user2@example.com');
INSERT INTO users (name, age, email) VALUES ('User3', 22, 'user3@example.com');

9.2 禁用索引(大批量导入) #

sql
-- 禁用索引
ALTER TABLE users DISABLE KEYS;

-- 批量插入数据
INSERT INTO users (name, age, email) VALUES
    -- ... 大量数据

-- 启用索引
ALTER TABLE users ENABLE KEYS;

9.3 使用LOAD DATA #

sql
-- 从文件导入(更快)
LOAD DATA INFILE '/path/to/users.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(name, age, email);

十、常见错误处理 #

10.1 重复键错误 #

sql
-- 错误信息
INSERT INTO users (id, name) VALUES (1, 'John');
-- ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

-- 解决方案
INSERT IGNORE INTO users (id, name) VALUES (1, 'John');
-- 或
INSERT INTO users (id, name) VALUES (1, 'John')
ON DUPLICATE KEY UPDATE name = 'John';

10.2 非空约束错误 #

sql
-- 错误信息
INSERT INTO users (age, email) VALUES (25, 'john@example.com');
-- ERROR 1364 (HY000): Field 'name' doesn't have a default value

-- 解决方案:提供name值
INSERT INTO users (name, age, email) VALUES ('John', 25, 'john@example.com');

10.3 数据类型错误 #

sql
-- 错误信息
INSERT INTO users (name, age) VALUES ('John', 'abc');
-- ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'age'

-- 解决方案:提供正确类型
INSERT INTO users (name, age) VALUES ('John', 25);

十一、总结 #

插入数据要点:

方式 语法 适用场景
基本插入 INSERT INTO … VALUES 单行插入
批量插入 INSERT INTO … VALUES (…), (…) 多行插入
查询插入 INSERT INTO … SELECT 复制数据
存在更新 ON DUPLICATE KEY UPDATE 插入或更新

最佳实践:

  1. 使用批量插入提高性能
  2. 指定列名,避免依赖顺序
  3. 处理重复数据时使用INSERT IGNORE或ON DUPLICATE KEY UPDATE
  4. 大批量导入考虑使用LOAD DATA

下一步,让我们学习数据更新!

最后更新:2026-03-26