INSERT
功能概述
INSERT INTO
INSERT INTO
语句用于将数据插入表中。你可以为表中的每个列显式指定值,或者使用
SELECT
SELECT
查询的结果作为插入的数据源。
语法
INSERT INTO|OVERWRITE [TABLE] table_name
[ PARTITION partition_spec]
[ (column1, column2, ...)]
{VALUES(value1 [,...],(value2 [,...]),...) | subquery}
partition_spec ::=
partition_column_name = partition_column_val [ , ... ]
参数说明
- INSERT INTO:追加写入,不影响表中已有数据——日常写入数据的标准方式。
- INSERT OVERWRITE:覆盖写入,清空目标表(或指定分区)后重新写入——适合每次全量刷新的场景,谨慎使用。
- 对于分区表,将覆盖指定分区的数据。
- 对于非分区表,将覆盖整个表的数据。
- TABLE:(可选)关键字,用于指定目标表。
- partition_spec:指定写入哪个分区——分区表必须提供分区值,非分区表不需要。
- column_list:指定要插入数据的列,确保输入查询的列顺序与表中的列顺序相匹配。
使用指南
-
数据类型匹配:确保插入的数据类型与表定义中的列类型相匹配。
-
查询结果匹配:使用
SELECT
SELECT
语句插入数据时,查询返回的列数量和顺序应与目标表的列相匹配。
-
分区规范:在分区表中插入数据时,如果未指定分区规范,系统将根据分区列的值自动选择分区。确保插入的数据中包含有效的分区值。
-
INSERT OVERWRITE:使用此语句插入数据时,确保目标表或分区存在,否则操作将失败。
-
数据检查:执行插入操作前,检查数据类型和列数量是否与目标表匹配,以避免数据插入错误。特别注意的是,Apache Hive要求分区列是最后一个位置。没有这种强制要求,因此加列的时候特别注意:按照原来Hive方式加列可能会将列加到最后一个位置,所以加列的时候必须指定位置。否则会造成数据错误。
-
自动分区处理:当使用分区字段为函数的表时,无需指定
PARTITION
PARTITION
子句,系统会自动根据函数返回值处理分区。
-
大量数据导入:在lakehouse环境中,不推荐使用
INSERT INTO...VALUES
INSERT INTO...VALUES
方式导入大量数据,这种方式更适合测试场景。对于大量数据导入,请参阅数据导入指南。
使用示例
1. 基本 VALUES 插入
向
doc_test.products
doc_test.products
追加写入单行和多行数据。
-- 插入单行
INSERT INTO doc_test.products VALUES (101, 'Wireless Mouse', 89.90, 200, 'Electronics');
-- 插入多行(一次提交)
INSERT INTO doc_test.products VALUES
(102, 'USB-C Hub', 149.00, 150, 'Electronics'),
(103, 'Desk Lamp', 59.50, 300, 'Office');
-- 验证
SELECT product_id, name, price, stock FROM doc_test.products WHERE product_id IN (101, 102, 103);
+------------+----------------+--------+-------+
| product_id | name | price | stock |
+------------+----------------+--------+-------+
| 101 | Wireless Mouse | 89.90 | 200 |
| 102 | USB-C Hub | 149.00 | 150 |
| 103 | Desk Lamp | 59.50 | 300 |
+------------+----------------+--------+-------+
2. 指定列名插入(省略部分列)
未指定的列填充 NULL(若列有默认值则使用默认值)。
-- 仅指定 product_id 和 name,其余列为 NULL
INSERT INTO doc_test.products (product_id, name) VALUES (104, 'Notebook');
-- 验证
SELECT product_id, name, price, stock, category FROM doc_test.products WHERE product_id = 104;
+------------+----------+-------+-------+----------+
| product_id | name | price | stock | category |
+------------+----------+-------+-------+----------+
| 104 | Notebook | NULL | NULL | NULL |
+------------+----------+-------+-------+----------+
3. SELECT 插入(从查询结果写入另一张表)
将薪资高于 10000 的员工信息归档到备份表。
-- 创建归档表(与 employees 结构相同)
CREATE TABLE IF NOT EXISTS doc_test.employees_archive
LIKE doc_test.employees;
-- 将薪资高于 10000 的员工写入归档表
INSERT INTO doc_test.employees_archive
SELECT * FROM doc_test.employees WHERE salary > 10000;
-- 验证:归档表中的行数
SELECT COUNT(*) AS archived_count FROM doc_test.employees_archive;
+----------------+
| archived_count |
+----------------+
| 2 |
+----------------+
salary > 10000
salary > 10000
的员工为 Alice(12000)和 Charlie(11000),共 2 行。
也可以只写入部分列:
INSERT INTO doc_test.employees_archive (id, name, dept)
SELECT id, name, dept FROM doc_test.employees WHERE is_active = false;
4. 分区表插入数据
doc_test.orders
doc_test.orders
按
order_date
order_date
分区。插入时在 VALUES 末尾提供分区列的值,系统自动路由到对应分区。
-- 动态分区:系统根据 order_date 值自动选择分区
INSERT INTO doc_test.orders VALUES
(5001, 1001, 'Wireless Mouse', 89.90, 'paid', '2024-03-01'),
(5002, 1002, 'USB-C Hub', 149.00, 'pending', '2024-03-01'),
(5003, 1003, 'Desk Lamp', 59.50, 'paid', '2024-03-02');
-- 静态分区:显式指定分区,VALUES 中无需再提供分区列
INSERT INTO doc_test.orders PARTITION (order_date='2024-03-03') (order_id, customer_id, product, amount, status)
VALUES (5004, 1004, 'Notebook', 35.00, 'paid');
-- 验证
SELECT order_id, product, amount, order_date FROM doc_test.orders WHERE order_date IN ('2024-03-01','2024-03-02','2024-03-03');
+----------+----------------+--------+------------+
| order_id | product | amount | order_date |
+----------+----------------+--------+------------+
| 5001 | Wireless Mouse | 89.90 | 2024-03-01 |
| 5002 | USB-C Hub | 149.00 | 2024-03-01 |
| 5003 | Desk Lamp | 59.50 | 2024-03-02 |
| 5004 | Notebook | 35.00 | 2024-03-03 |
+----------+----------------+--------+------------+
5. INSERT OVERWRITE(覆盖写入)
适合每日全量刷新场景——先清空目标分区,再写入当天最新数据。以下示例覆盖
2024-03-01
2024-03-01
分区(已有数据将被清除):
-- 覆盖单个分区
INSERT OVERWRITE doc_test.orders PARTITION (order_date='2024-03-01') (order_id, customer_id, product, amount, status)
VALUES
(5001, 1001, 'Wireless Mouse', 99.90, 'paid'), -- 金额已更新
(5005, 1005, 'Keyboard', 199.00, 'paid'); -- 新增订单,5002 行被清除
-- 验证:2024-03-01 分区只剩新写入的两行
SELECT order_id, product, amount FROM doc_test.orders WHERE order_date = '2024-03-01';
+----------+----------------+--------+
| order_id | product | amount |
+----------+----------------+--------+
| 5001 | Wireless Mouse | 99.90 |
| 5005 | Keyboard | 199.00 |
+----------+----------------+--------+
对非分区表使用
INSERT OVERWRITE
INSERT OVERWRITE
会清空整张表后重新写入,适合维度表全量刷新:
-- 用最新数据集全量替换商品表
INSERT OVERWRITE doc_test.products
SELECT * FROM doc_test.products_staging;
6. 插入不同的数据类型
展示各种内置类型的字面量写法,供类型映射参考。此示例仅演示语法,不展示查询输出。
CREATE TABLE doc_test.type_demo(
`c_bigint` bigint,
`c_boolean` boolean,
`c_binary` binary,
`c_char` char(1),
`c_date` date,
`c_decimal` decimal(20,6),
`c_double` double,
`c_float` float,
`c_int` int,
`c_smallint` smallint,
`c_string` string,
`c_timestamp` timestamp,
`c_tinyint` tinyint,
`c_array` array<int>,
`c_map` map<string,string>,
`c_struct` struct<a:int,b:string,c:double>,
`c_varchar` varchar(100),
`c_json` json);
INSERT INTO doc_test.type_demo
VALUES (
1l, -- c_bigint
true, -- c_boolean
X'7A', -- c_binary
'A', -- c_char
date'2025-05-21' , -- c_date
1.1bd, -- c_decimal
1.1d, -- c_double
1.1f, -- c_float
1, -- c_int
1s, -- c_smallint
'This is a string', -- c_string
timestamp'2025-05-21 12:00:00', -- c_timestamp
127, -- c_tinyint
ARRAY(1,2,3), -- c_array
MAP('key1', 'value1', 'key2', 'value2'), -- c_map
STRUCT(1, 'a', 3.14), -- c_struct
'This is a varchar string', -- c_varchar
json'123' -- c_json
);
相关指南
- 批量插入数据:多种批量写入方式对比,含 INSERT INTO SELECT、VALUES 批量、COPY INTO 等场景
- SQL DML使用指南:INSERT/UPDATE/DELETE/MERGE 的注意事项与最佳实践