INSERT INTO SELECT 使用

本文详细介绍了 SQL 中 INSERT INTO 语句的使用方法,包括两种不同的语法形式及其应用场景。通过具体示例展示了如何利用该语句向数据库表中插入新记录。

INSERT INTO 语句用于向表中插入新记录。

SQL INSERT INTO 语句
INSERT INTO 语句用于向表中插入新记录。

SQL INSERT INTO 语法
INSERT INTO 语句可以有两种编写形式。

第一种形式无需指定要插入数据的列名,只需提供被插入的值即可:

INSERT INTO table_name
VALUES (value1,value2,value3,...);

第二种形式需要指定列名及被插入的值:

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

示例:

   INSERT INTO p_alarm_info (
      	school_id,
        school_name,
        ststus
        ) SELECT
        #{schoolId},
        #{schoolName},
        #{status}
        FROM
        p_papers_result_alarm_info b,
        s_people_info a
        WHERE
        b.student_code = a.people_code   
<think> 我们正在讨论的是INSERT INTO SELECT语句的使用注意事项。根据引用内容,INSERT INTO SELECT语句用于将数据从一个表复制到另一个已存在的表中。以下是使用该语句时需要注意的关键事项: 1. **列匹配问题**: - 必须确保SELECT语句选择的列与目标表的列在数量、顺序和数据类型上兼容。 - 如果只插入部分列,需要明确指定列名: ```sql INSERT INTO table2 (col1, col2) SELECT col1, col2 FROM table1; ``` - 若不指定列名,则要求两个表的列结构完全一致。 2. **性能问题**: - 大数据量操作可能导致锁表或性能下降,建议分批操作(如使用LIMIT分页): ```sql INSERT INTO table2 SELECT * FROM table1 LIMIT 1000 OFFSET 0; ``` - 在事务中进行操作,避免意外中断导致数据不一致: ```sql START TRANSACTION; INSERT INTO ... SELECT ...; COMMIT; ``` 3. **事务与锁机制**: - 默认情况下,INSERT INTO SELECT会对源表(table1)加共享锁(S锁),阻塞其他事务的写操作。 - 使用`SELECT ... FOR UPDATE`时需谨慎,可能导致死锁风险(参考前文FOR UPDATE的锁机制分析)。 4. **唯一键冲突**: - 若目标表存在唯一约束,需处理重复数据: ```sql -- 忽略重复 INSERT IGNORE INTO table2 SELECT * FROM table1; -- 更新重复 INSERT INTO table2 SELECT * FROM table1 ON DUPLICATE KEY UPDATE col=VALUES(col); ``` 5. **自增主键处理**: - 若目标表有自增主键,插入时可能出现跳号现象(如事务回滚导致自增值不连续)。 - 如需保留原主键值,需显式指定插入自增列: ```sql INSERT INTO table2 (id, col) SELECT old_id, col FROM table1; ``` 6. **权限要求**: - 用户需同时拥有源表的SELECT权限和目标表的INSERT权限。 7. **触发器影响**: - 若目标表定义了BEFORE INSERT/AFTER INSERT触发器,每条插入数据都会触发触发器执行。 8. **存储引擎差异**: - MyISAM引擎支持并发插入(CONCURRENT INSERT),InnoDB则依赖事务隔离级别。 > 引用[1]强调:需要确保列的匹配、考虑性能和使用事务控制[^1]。引用[3]指出可以只复制希望的列插入到另一个已存在的表中[^3]。 --- ### 最佳实践示例 ```sql -- 安全插入(指定列+事务控制) START TRANSACTION; INSERT INTO orders_archive (order_id, amount, customer) SELECT id, total_price, cust_name FROM orders WHERE order_date < '2020-01-01' LIMIT 1000; COMMIT; ``` §§相关问题§§ 1. INSERT INTO SELECT语句与SELECT INTO有何区别? 2. 如何避免INSERT INTO SELECT导致源表锁定的问题? 3. 大数据量迁移时有哪些替代方案(如数据泵、ETL工具)? 4. 在INSERT INTO SELECT中如何实现错误日志记录? </think> ### INSERT INTO SELECT 语句使用注意事项 INSERT INTO SELECT 语句用于将查询结果插入目标表,使用时需特别注意以下关键事项: #### 1. **列匹配问题(最常见错误)** - **列数量必须一致**: ```sql -- 错误示例(目标表3列,SELECT返回2列) INSERT INTO target_table SELECT col1, col2 FROM source_table; -- 正确写法(显式指定列) INSERT INTO target_table (colA, colB, colC) SELECT col1, col2, 'default' FROM source_table; ``` - **数据类型兼容性**: - 字符串列不能插入数值类型列 - 日期格式必须兼容(如`YYYY-MM-DD`) - 使用`CAST()`转换类型: ```sql SELECT CAST(date_str AS DATE) FROM source_table; ``` #### 2. **性能优化要点** - **批量写入限制**: ```sql -- 分批次插入(避免单次事务过大) INSERT INTO target SELECT * FROM source LIMIT 10000 OFFSET 0; ``` - **索引策略**: - **插入前**:禁用目标表非唯一索引(`ALTER TABLE...DISABLE KEYS`) - **插入后**:重建索引 - **事务控制**: ```sql START TRANSACTION; INSERT INTO ... SELECT ...; -- 分批执行 COMMIT; ``` #### 3. **锁机制与并发** - **源表锁定**: - 默认对源表加**共享锁**(允许读,阻塞写) - 使用`SELECT ... FOR UPDATE`会升级为排他锁[^1] - **目标表锁定**: - 对整个目标表加**排他锁**(阻塞所有操作) - 解决方法: ```sql LOCK TABLES target WRITE; -- 手动锁表减少等待时间 INSERT ... SELECT ...; UNLOCK TABLES; ``` #### 4. **数据冲突处理** - **唯一键冲突**: ```sql -- 忽略重复数据 INSERT IGNORE INTO target SELECT * FROM source; -- 更新重复记录 INSERT INTO target SELECT * FROM source ON DUPLICATE KEY UPDATE col=VALUES(col); ``` - **外键约束**: - 确保SELECT结果满足外键引用 - 禁用外键检查加速写入: ```sql SET FOREIGN_KEY_CHECKS=0; INSERT ... SELECT ...; SET FOREIGN_KEY_CHECKS=1; ``` #### 5. **特殊场景注意事项** - **自增主键处理**: - 保留原ID:`INSERT INTO target (id, ...) SELECT old_id, ...` - 自动生成新ID:省略主键列 - **大对象(BLOB/TEXT)**: - 单次插入可能超`max_allowed_packet`限制 - 需调整服务器参数或分块处理 - **触发器影响**: - BEFORE/AFTER INSERT 触发器会对**每条数据**触发 > 引用[3]强调:明确指定列名比`SELECT *`更安全(避免表结构变更导致错误)[^3] #### 6. 安全建议 ```sql -- 始终推荐的写法 INSERT INTO target (col1, col2, col3) -- 显式列名 SELECT SAFE_CAST(data AS INT), -- 类型转换 COALESCE(nullable_col, 0), -- 空值处理 '常量值' FROM source WHERE condition; -- 过滤条件 ``` --- ### 典型错误案例 ```sql /* 危险操作:未限定条件导致全表复制 */ INSERT INTO orders_backup SELECT * FROM orders; -- 可能锁表数小时! /* 改正方案 */ INSERT INTO orders_backup SELECT * FROM orders WHERE create_date > '2023-01-01' LIMIT 10000; -- 分批操作 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小七会喷火

小七想要bi

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值