INSERT INTO … SELECT … 常见问答(含样例)

1)INSERT INTO A SELECT x FROM B 是什么意思?

回答

把查询 SELECT x FROM B 返回的结果集逐行插入到表 A。插入哪些列,取决于是否写了目标列清单以及列数/顺序是否匹配。

示例

-- 把 B.person_id 插到 A.user_id

INSERT INTO A(user_id)

SELECT person_id

FROM B;

2)不写列清单会怎样?列如何对齐?

回答

INSERT INTO A SELECT ...(无列清单)要求 SELECT 产生的列数与顺序和 A 的物理列顺序一一对应。列数不等或类型不兼容会报错;即使能成功,也脆弱(A 增减列就歪了),不推荐。

示例

-- 不推荐:依赖 A 的物理列顺序

INSERT INTO A

SELECT x, y, z FROM B;

3)A 有 100 列,只插 5 列可以吗?

回答

可以,但必须显式列出这 5 列;其余 95 列要么 允许 NULL、要么有默认值/自动生成,否则会因 NOT NULL 无默认而报错。

示例

-- 只写 5 列,其余列走默认值或 NULL

INSERT INTO A(c1, c2, c3, c4, c5)

SELECT x1, x2, x3, x4, x5

FROM B;

4)INSERT ... SELECT 没有列清单,如何理解字段对应?

回答

数据库按位置对齐:SELECT 的第 1 列对应 A 的第 1 列......依此类推。

若 SELECT *,就会把星号展开成来源表的全部列,再按位置对齐到 A(极易错位)。最佳实践:永远显式写出 A 的目标列清单。

示例

-- 脆弱:A 增列/改顺序就错位

INSERT INTO A

SELECT * FROM B;

5)如何插常量或表达式?

回答

SELECT 子句里可以是列、表达式、常量的任意组合。

示例

INSERT INTO A(user_id, death_date, remark)

SELECT person_id,

CAST(death_dt AS DATE),

'import-from-B'

FROM B

WHERE death_dt IS NOT NULL;

6)有自增/标识/生成列怎么办?

回答

这类列通常不要出现在目标列清单里,交给数据库自动填。SQL Server 若要手动写入,需先 SET IDENTITY_INSERT A ON。

示例

-- MySQL/PG:id 自增/序列自动填

INSERT INTO A(user_id, value)

SELECT person_id, score FROM B;

7)只想插入一行「全部默认值」怎么写?

回答

PostgreSQL / SQL Server:INSERT INTO A DEFAULT VALUES;

MySQL:INSERT INTO A () VALUES ();

8)如何防止重复插入?

回答(三种常用)

约束法:给唯一键/主键,违反时失败(最干净)。

过滤法:NOT EXISTS / LEFT JOIN IS NULL 只插不存在的。

方言法:PG ON CONFLICT DO NOTHING;MySQL INSERT IGNORE 或 ON DUPLICATE KEY UPDATE。

示例(通用)

INSERT INTO A(key_col, val)

SELECT b.key_col, b.val

FROM B b

WHERE NOT EXISTS (

SELECT 1 FROM A a WHERE a.key_col = b.key_col

);

9)为什么会报错「列数不匹配 / 不能为空 / 类型不兼容」?

回答

列数不匹配:没写列清单且 SELECT 列数与 A 列数不同。

不能为空:A 中有 NOT NULL 列既没在列清单里,也无默认值。

类型不兼容:SELECT 的列类型与 A 的目标列类型不匹配,需 CAST/CONVERT。

示例(显式转换)

INSERT INTO A(death_date)

SELECT CAST(death_dt AS DATE)

FROM B;

10)跨库/不同方言的小差异

回答(速览)

PostgreSQL / SQL Server:未指定列 → 用默认值;无默认则 NULL;NOT NULL 无默认会失败。

MySQL:同上;还支持 INSERT INTO A SET c1=..., c2=...;;以及 INSERT INTO A () VALUES (); 插全部默认。

Hive/Spark(宽表常见):更依赖位置对齐,更要写列清单。

11)最佳实践清单(拿去即用)

回答

总是写明目标列清单,并与 SELECT 列一一对应。

对类型不兼容的列显式 CAST。

让自增/生成列自动填,不要手写。

保证未写入的列要么可空,要么有默认值。

防重:唯一键 + NOT EXISTS/ON CONFLICT/ON DUPLICATE KEY。

避免 SELECT *,避免依赖物理列序。

大批量插入用事务与批次(分批提交),必要时关闭/延后索引/触发器再重建。

12)进阶样例:多列映射+去重+类型转换

示例

-- 把 B 的数据清洗后插入 A,避免重复,兼顾类型转换

INSERT INTO A(user_id, death_date, death_reason, remark)

SELECT b.person_id,

CAST(b.death_dt AS DATE),

b.death_reason,

CONCAT('import ', CURRENT_DATE)

FROM B b

WHERE b.death_dt IS NOT NULL

AND NOT EXISTS (

SELECT 1 FROM A a

WHERE a.user_id = b.person_id

AND a.death_date = CAST(b.death_dt AS DATE)

);

相关推荐
星川水月1 小时前
Access数据库快速入门——外部数据导入和SQL简单查询
数据库·sql·access
ElevenS_it1881 小时前
MySQL慢查询监控与告警实战:从slow_log采集到分钟级定位慢SQL的完整链路配置
android·sql·mysql
阳光九叶草LXGZXJ2 小时前
达梦数据库-学习-57-读写数据页超时告警排查(page[x,x,xxxxxx] disk write uses)-DSC集群版
linux·运维·服务器·数据库·sql·学习
阳光九叶草LXGZXJ2 小时前
达梦数据库-堆栈看问题-01-asmapi_asm_extent_load
linux·运维·数据库·sql·学习
pixle02 小时前
LangChain v1.2 Text-to-SQL 实战:从入门到生产级部署
sql·langchain·agent·智能助手·text-to-sql
清平乐的技术专栏3 小时前
【FlinkSQL笔记】(二)Flink SQL 基础语法详解
笔记·sql·flink
清平乐的技术专栏4 小时前
【FlinkSQL笔记】(一)什么是Flink SQL
笔记·sql·flink
廿一夏4 小时前
MySql视图触发器函数存储过程
数据库·sql·oracle
数据库小学妹4 小时前
CTE+阶段式递归:用公共表表达式搞定复杂业务逻辑,告别SQL难题!
数据库·经验分享·b树·sql
清平乐的技术专栏4 小时前
【FlinkSQL笔记】(三)Flink SQL 核心重难点(窗口函数、水印)
笔记·sql·flink