SQL 插入数据示例详解
SQL 中的 INSERT 语句用于向数据库表中插入新记录。以下是各种插入数据的详细示例和说明。
1. 基本语法
1.1 插入单行数据(指定列)
-- 基本语法
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
-- 示例:向 employees 表插入数据
INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id, salary)
VALUES (101, 'John', 'Doe', 'john.doe@company.com', '2023-01-15', 'IT_PROG', 75000);
1.2 插入单行数据(所有列)
-- 如果为所有列提供值,可以省略列名
INSERT INTO employees
VALUES (102, 'Jane', 'Smith', 'jane.smith@company.com', '2023-02-20', 'SA_REP', 65000, NULL, NULL, 80);
-- 注意:值必须与表结构中的列顺序完全一致
2. 多种插入方式
2.1 插入多行数据
-- 方式1:使用多个VALUES子句
INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id, salary)
VALUES
(103, 'Mike', 'Johnson', 'mike.j@company.com', '2023-03-10', 'IT_PROG', 80000),
(104, 'Sarah', 'Williams', 'sarah.w@company.com', '2023-04-05', 'HR_REP', 55000),
(105, 'Tom', 'Brown', 'tom.b@company.com', '2023-05-12', 'MK_REP', 60000);
2.2 从其他表插入数据
-- 基本语法
INSERT INTO table2 (column1, column2, ...)
SELECT column1, column2, ...
FROM table1
WHERE condition;
-- 示例:将高薪员工复制到 managers 表
INSERT INTO managers (manager_id, first_name, last_name, salary)
SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE salary > 70000;
-- 示例:插入计算值
INSERT INTO salary_history (employee_id, year, annual_salary, bonus)
SELECT
employee_id,
EXTRACT(YEAR FROM hire_date),
salary * 12,
CASE
WHEN salary > 70000 THEN salary * 0.15
ELSE salary * 0.10
END
FROM employees
WHERE hire_date < '2023-06-01';
3. 插入带有特殊值的数据
3.1 插入 NULL 值
-- 直接使用 NULL 关键字
INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id, salary, manager_id)
VALUES (106, 'Lisa', 'Davis', 'lisa.d@company.com', '2023-06-01', 'SA_REP', 58000, NULL);
-- 或者省略该列(如果列允许NULL)
INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id, salary)
VALUES (107, 'Robert', 'Wilson', 'robert.w@company.com', '2023-07-15', 'IT_PROG', 72000);
3.2 插入默认值
-- 使用 DEFAULT 关键字
INSERT INTO products (product_id, product_name, price, in_stock, created_date)
VALUES (1001, 'Laptop', 999.99, DEFAULT, DEFAULT);
-- 假设 in_stock 默认值为 0,created_date 默认值为 CURRENT_TIMESTAMP
3.3 插入当前日期和时间
-- MySQL/PostgreSQL
INSERT INTO orders (order_id, customer_id, order_date, status)
VALUES (5001, 123, NOW(), 'PENDING');
-- SQL Server
INSERT INTO orders (order_id, customer_id, order_date, status)
VALUES (5002, 456, GETDATE(), 'PROCESSING');
-- Oracle
INSERT INTO orders (order_id, customer_id, order_date, status)
VALUES (5003, 789, SYSDATE, 'SHIPPED');
4. 复杂插入示例
4.1 插入带有子查询的数据
-- 插入带有计算和条件的数据
INSERT INTO employee_stats (department_id, avg_salary, employee_count, last_updated)
SELECT
department_id,
AVG(salary) AS avg_salary,
COUNT(*) AS employee_count,
CURRENT_DATE
FROM employees
GROUP BY department_id;
-- 插入存在条件的子查询结果
INSERT INTO high_performers (employee_id, performance_score, reward_amount)
SELECT
e.employee_id,
p.performance_score,
CASE
WHEN p.performance_score >= 90 THEN 5000
WHEN p.performance_score >= 80 THEN 2000
ELSE 500
END
FROM employees e
INNER JOIN performance_reviews p ON e.employee_id = p.employee_id
WHERE p.review_date >= '2023-01-01';
4.2 插入 JSON 数据(现代数据库)
-- PostgreSQL JSON 插入
INSERT INTO user_profiles (user_id, profile_data)
VALUES
(1, '{"name": "Alice", "age": 30, "preferences": {"theme": "dark", "notifications": true}}'),
(2, '{"name": "Bob", "age": 25, "preferences": {"theme": "light", "notifications": false}}');
-- MySQL JSON 插入
INSERT INTO product_details (product_id, specifications)
VALUES
(1001, '{"brand": "Dell", "ram": "16GB", "storage": "512GB SSD"}');
5. 带有约束的插入处理
5.1 处理重复键(INSERT ... ON DUPLICATE KEY UPDATE)
-- MySQL:如果存在重复键则更新
INSERT INTO users (user_id, username, email, login_count)
VALUES (101, 'alice123', 'alice@email.com', 1)
ON DUPLICATE KEY UPDATE
login_count = login_count + 1,
last_login = NOW();
-- PostgreSQL:使用 ON CONFLICT
INSERT INTO users (user_id, username, email, login_count)
VALUES (101, 'alice123', 'alice@email.com', 1)
ON CONFLICT (user_id)
DO UPDATE SET
login_count = users.login_count + 1,
last_login = CURRENT_TIMESTAMP;
5.2 忽略重复插入
-- MySQL:使用 IGNORE
INSERT IGNORE INTO unique_users (user_id, username)
VALUES (101, 'alice123'), (102, 'bob456');
-- PostgreSQL:使用 ON CONFLICT DO NOTHING
INSERT INTO unique_users (user_id, username)
VALUES (101, 'alice123'), (102, 'bob456')
ON CONFLICT (user_id) DO NOTHING;
6. 实际应用示例
6.1 电商系统插入订单
-- 插入订单表
INSERT INTO orders (order_id, customer_id, order_date, total_amount, status)
VALUES (10001, 5001, '2023-10-15 14:30:00', 299.97, 'PENDING');
-- 插入订单详情
INSERT INTO order_items (order_id, product_id, quantity, unit_price)
VALUES
(10001, 2001, 1, 199.99),
(10001, 2002, 2, 49.99);
6.2 博客系统插入文章
-- 插入文章
INSERT INTO articles (article_id, title, content, author_id, category_id, created_at)
VALUES
(1001, 'SQL 入门教程', '这是 SQL 入门教程的内容...', 101, 5, NOW()),
(1002, '数据库设计原则', '数据库设计的最佳实践...', 102, 5, NOW());
-- 插入标签关联
INSERT INTO article_tags (article_id, tag_id)
SELECT 1001, tag_id FROM tags WHERE tag_name IN ('SQL', '数据库', '教程')
UNION
SELECT 1002, tag_id FROM tags WHERE tag_name IN ('数据库', '设计', '最佳实践');
7. 性能优化建议
7.1 批量插入
-- 使用多值语法(推荐)
INSERT INTO products (product_id, product_name, price)
VALUES
(1, 'Product A', 10.99),
(2, 'Product B', 19.99),
(3, 'Product C', 29.99);
-- 比分别执行三个INSERT语句快得多
7.2 禁用索引和约束(大型插入时)
-- MySQL:禁用/启用索引
ALTER TABLE large_table DISABLE KEYS;
-- 执行大量INSERT操作
ALTER TABLE large_table ENABLE KEYS;
-- PostgreSQL:使用事务
BEGIN;
-- 禁用触发器(如果需要)
ALTER TABLE large_table DISABLE TRIGGER ALL;
-- 执行插入
INSERT INTO large_table ...;
-- 重新启用
ALTER TABLE large_table ENABLE TRIGGER ALL;
COMMIT;
8. 常见错误及解决方法
8.1 列数不匹配
-- 错误:列数不匹配
INSERT INTO employees (employee_id, first_name, last_name)
VALUES (108, 'Anna'); -- 缺少一个值
-- 正确:要么提供所有列的值,要么明确指定列
INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id)
VALUES (108, 'Anna', 'Taylor', 'anna.t@company.com', '2023-08-01', 'HR_REP');
8.2 数据类型不匹配
-- 错误:字符串插入数字列
INSERT INTO products (product_id, product_name, price)
VALUES ('ABC123', 'Test Product', 'NOT_A_NUMBER'); -- price应该是数字
-- 正确:确保数据类型匹配
INSERT INTO products (product_id, product_name, price)
VALUES ('ABC123', 'Test Product', 29.99);
总结
基本插入:使用
INSERT INTO ... VALUES 语法
多行插入:使用多值语法提高性能
从查询插入:使用
INSERT ... SELECT 从其他表获取数据
处理重复:使用
ON DUPLICATE KEY UPDATE 或
ON CONFLICT 处理冲突
性能考虑:批量插入、适当禁用索引可以优化性能
错误处理:注意列数匹配、数据类型和约束条件
根据具体的数据库系统(MySQL、PostgreSQL、SQL Server、Oracle等),语法可能略有不同,建议查阅相应数据库的官方文档。