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)

);

相关推荐
现在,此刻4 小时前
clickhouse和pgSql跨库查询方案对比
数据库·sql·clickhouse·性能优化
nvd115 小时前
指南:为何及如何使用Envoy作为跳板机代理Cloud SQL
sql
l1t7 小时前
利用短整数类型和部分字符串优化DuckDB利用数组求解数独SQL
开发语言·数据库·sql·duckdb
驾数者10 小时前
Flink SQL核心概念解析:Table API与流表二元性
大数据·sql·flink
vortex515 小时前
谷歌黑客语法挖掘 SQL 注入漏洞
android·数据库·sql
wind_one116 小时前
7.基础--SQL--DDL-数据类型及案例
数据库·sql
l1t17 小时前
利用DeepSeek改写SQLite版本的二进制位数独求解SQL
数据库·人工智能·sql·sqlite
August_._19 小时前
【MySQL】SQL语法详细总结
java·数据库·后端·sql·mysql·oracle
还是奇怪1 天前
隐藏在字符编码中的陷阱:深入剖析宽字节注入
数据库·sql·安全·web安全