插入数据
表创建后,可以使用 INSERT 语句或其他语句向表中插入行记录。本文介绍了相关语句的使用方法和示例。
数据插入准备
在插入数据前,请确认以下事项:
-
请确认您已连接到 seekdb,连接数据库的操作请参见 连接方式概述。
-
请确认您已拥有待操作的表的
INSERT权限,查看当前用户权限的相关操作请参见 查看用户权限。如果不具备该权限,请联系管理员为您授权,用户授权的相关操作请参见 直接授予权限。
使用 INSERT INTO 语句插入数据
请使用 INSERT 语句,再参考下面的建议,向表中插入数据。
INSERT INTO 语句的语法格式如下:
INSERT INTO table_name [(list_of_columns)] VALUES (list_of_values);
| 参数 | 是否必填 | 描述 |
|---|---|---|
| table_name | 是 | 指定需要插入数据的表 |
| (list_of_columns) | 否 | 指定表中需要插入数据的列 |
| (list_of_values) | 是 | list_of_columns 提到的列的对应值,必须一一对应。 |
插入数据建议
-
插入数据前,建议了解表的所有列信息,包括列类型、有效值以及是否允许为 NULL 等。
查看列信息可以通过
DESC语句查看。DESC test;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| col1 | int(11) | NO | | NULL | |
| col2 | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set-
如果列属性为
NOT NULL-
如果列属性有默认值,则可以在插入时不指定该列的值,系统会在该列上插入默认值。
-
如果列属性无默认值,则插入时必须指定该列的值。
-
-
如果列属性为
NULL,则可以在插入时不指定该列的值,系统会在该列上插入一个NULL值。
-
-
插入数据前,建议了解表上列的约束定义情况,避免插入数据时报错。
NOT NULL、PRIMARY KEY约束、UNIQUE约束均可以通过DESC语句查看,FOREIGN KEY、CHECK约束可以通过查询information_schema.TABLE_CONSTRAINTS视图进行查看。
插入单行数据
通过 INSERT 语句可以插入单行数据。如果需要插入多条记录,可以执行多个单行插入语句来实现。如果需要批量插入,可参考 批量插入多行数据 进行操作。
假设待插入数据的表信息如下:
CREATE TABLE t_insert(
id int NOT NULL PRIMARY KEY,
name varchar(10) NOT NULL,
value int,
gmt_create DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Query OK, 0 rows affected
其中,表的 id 列、name 列不能为空,且 id 列为主键列,满足唯一性约束要求,不能有重复的值;gmt_create 列指定了默认值。
示例 1:使用多个单行插入语句插入多行数据。
由于 gmt_create 列指定了默认值,在插入数据时可以不指定默认值。
INSERT INTO t_insert(id, name, value)
VALUES (1,'CN',10001);
Query OK, 2 rows affected
INSERT INTO t_insert(id, name, value)
VALUES(2,'US', 10002);
Query OK, 2 rows affected
注意,如果 gmt_create 列未指定默认值,则在插入数据时,必须指定值,语句如下。
INSERT INTO t_insert(id, name, value, gmt_create)
VALUES (3,'EN', 10003, current_timestamp ());
Query OK, 1 row affected
批量插入多行数据
在插入数据时,如果要插入多条记录,也可以用一个 INSERT 语句包含多个 VALUES 来批量插入。单个多行插入语句比多个单行插入语句要快。
示例 1 中的操作,又可以通过以下语句来完成。
示例 2:批量插入多行数据。
INSERT INTO t_insert(id, name, value)
VALUES (1,'CN',10001),(2,'US', 10002);
Query OK, 2 rows affected
此外,当需要备份表数据或者将一个表的全部记录拷贝到另一个表时,可以使用查询语句 INSERT INTO ... SELECT ... FROM 充当 INSERT 的 values 子句进行批量插入。
示例 3:将表 t_insert 中的全部数据备份到 t_insert_bak 表中。
SELECT * FROM t_insert;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2025-12-22 21:41:28 |
| 2 | US | 10002 | 2025-12-22 21:41:32 |
| 3 | EN | 10003 | 2025-12-22 21:41:43 |
+----+------+-------+---------------------+
3 rows in set
CREATE TABLE t_insert_bak(
id number NOT NULL PRIMARY KEY,
name varchar(10) NOT NULL,
value number,
gmt_create DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Query OK, 0 rows affected
INSERT INTO t_insert_bak SELECT * FROM t_insert;
Query OK, 3 rows affected
SELECT * FROM t_insert_bak;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2025-12-22 21:41:28 |
| 2 | US | 10002 | 2025-12-22 21:41:32 |
| 3 | EN | 10003 | 2025-12-22 21:41:43 |
+----+------+-------+---------------------+
3 rows in set
避免唯一性约束冲突
当表上有唯一性约束的时候,插入相同的记录,数据库会报错。报错信息如下:
INSERT INTO t_insert(id, name, value) VALUES (3,'UK', 10003),(4, 'JP', 10004);
ERROR 1062 (23000): Duplicate entry '3' for key 'PRIMARY'
该报错可以通过 INSERT IGNORE INTO 语句或 INSERT INTO ON DUPLICATE KEY UPDATE 语句来避免。
示例:
-
通过
INSERT IGNORE INTO语句避免约束冲突时,IGNORE关键字可以忽略由于约束冲突导致的INSERT失败的影响。INSERT IGNORE INTO t_insert(id, name, value)
VALUES (3,'UK', 10003),(4, 'JP', 10004);
Query OK, 1 row affected
SELECT * FROM t_insert;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2025-12-22 21:41:28 |
| 2 | US | 10002 | 2025-12-22 21:41:32 |
| 3 | EN | 10003 | 2025-12-22 21:41:43 |
| 4 | JP | 10004 | 2025-12-22 21:43:28 |
+----+------+-------+---------------------+
4 rows in set示例中,使用了
INSERT IGNORE INTO语句,(3,'UK', 10003)这一行数据插入失败,但系统未再报错。 -
通过
INSERT INTO ON DUPLICATE KEY UPDATE语句避免约束冲突时,可以指定对重复主键或唯一键的后续处理。信息-
指定
ON DUPLICATE KEY UPDATE column_name = expr:当要插入的主键或唯一键有重复时,可以使用column_name = expr赋值语句来更新表中冲突行的数据。column_name = expr赋值语句可以为冲突行赋某一列或几列的值。赋多列值时,列与列之间用逗号分隔。 -
不指定
ON DUPLICATE KEY UPDATE column_name = expr:当要插入的主键或唯一键有重复时,插入数据时,系统会报错。
INSERT INTO t_insert(id, name, value) VALUES (3,'UK', 10003),(5, 'CN', 10005) ON DUPLICATE KEY UPDATE name = VALUES(name);
Query OK, 1 row affected
SELECT * FROM t_insert;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2025-12-22 21:41:28 |
| 2 | US | 10002 | 2025-12-22 21:41:32 |
| 3 | UK | 10003 | 2025-12-22 21:41:43 |
| 4 | JP | 10004 | 2025-12-22 21:43:28 |
| 5 | CN | 10005 | 2025-12-22 21:46:27 |
+----+------+-------+---------------------+
5 rows in set示例中,
ON DUPLICATE KEY UPDATE name = VALUES(name)即表示当插入的数据与表中的主键值有重复时,将表中冲突行原数据中(3,'EN', 10003)的name列的值更新为当前待插入的name列的数据。其他不冲突的行,则正常插入。 -
使用 INSERT OVERWRITE SELECT 语句插入数据
INSERT OVERWRITE SELECT 语句用于将查询结果替换表或分区中的现有数据,即将查询出的数据覆盖写到目标表或分区中。
该语句语法格式如下:
INSERT [/*+PARALLEL(N)*/] OVERWRITE table_name [(list_of_columns)] [PARTITION (partition_name, ...)] select_stmt;
| 参数 | 描述 |
|---|---|
| PARALLEL(N) | 可选项,指定覆盖写操作的并行执行程度。若未指定,默认采用的并行度为 2。 |
| table_name | 指定要插入的表名。 |
| list_of_columns | 指定表中需要插入数据的列。 |
| select_stmt | 指定 SELECT 子句。有关查询语句的详细信息,参见 SELECT 语句。 |
| partition_name | 插入表指定的分 区名,同时插入多个分区时以逗号(,)分隔。 |
INSERT OVERWRITE SELECT 使用限制
表级 INSERT OVERWRITE SELECT 使用限制
- 该语句无法在多行事务中操作。因此,为确保操作顺利进行,需先执行
SET autocommit = on;命令开启自动提交事务。 - 对写入表加表锁,不允许对同一张表并发的发起任何 DDL 操作,并发发起的 DML 操作会等待表锁释放直至超时,允许在操作期间对表进行查询。
- 该语句操作的源数据和目标表覆盖写的列数目必须严格匹配,否则会报错。
- 该语句数据写入操作是全量旁路导入方式,所以操作受全量旁路导入功能限制。有关旁路导入的信息,参见 使用 INSERT INTO SELECT 语句旁路导入数据 中的 使用限制 章节。
- 该语句指定旁路导入 Hint 会报错。
- 受 PDML(Parallel Data Manipulation Language,并行数据操纵语言)框架限制,PDML 不支持的场景无法导入数据,
INSERT OVERWRITE SELECT会报错 not supported。有关并行 DML 的详细信息,参 见 并行 DML。
分区级 INSERT OVERWRITE SELECT
功能介绍
- 源表可以为分区表或非分区表,分区类型无要求。
- 支持目标表为一级或二级分区。
- 支持目标表有局部索引和 LOB。
- 可以指定目标表的全部或者部分分区,如果目标表有二级分区,则可以单独或混合指定一二级分区。
- 如果指定的目标表分区没有被任何来自源表的数据命中,则该分区数据会被清空(被空数据覆盖)。
- 分区级的
insert overwrite操作支持目标表最后一级分区为 Hash 或 Key 分区。
使用限制
- 指定的分区必须已经存在,否则会报错。
- 基于全量旁路导入,无需再添加
/*+ append */Hint,否则使用会报错。 - 该语句无法在多行事务中操作。因此,为确保操作顺利进行,需先执行
SET autocommit = on;命令开启自动提交事务。 - 如果来自源表的数据经过目标表的分区规则计算后,没有命中到指定的目标表分区中,则会报错分区不存在。
- 暂不支持目标表有自增列。
- 暂不支持目标表有全局索引或外键。
- 暂不支持目标表为外表。
INSERT OVERWRITE SELECT 示例
示例一
-
创建两个测试表:
source_tbl1作为数据源,target_tbl1作为目标表。CREATE TABLE source_tbl1 (col1 INT, col2 VARCHAR(20), col3 INT);CREATE TABLE target_tbl1 (col1 INT, col2 VARCHAR(20), col3 INT); -
向表
source_tbl1中插入示例数据。INSERT INTO source_tbl1 VALUES (1, 'A1', 30),(2, 'B2', 25),(3, 'C3', 22); -
向表
target_tbl1中插入示例数据。INSERT INTO target_tbl1 VALUES (4, 'D4', 35),(5, 'E5', 28); -
查询表
target_tbl1中的数据。SELECT * FROM target_tbl1;返回结果如下:
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
| 4 | D4 | 35 |
| 5 | E5 | 28 |
+------+------+------+
2 rows in set -
使用
INSERT OVERWRITE SELECT语句,基于col3大于 25 从source_tbl1中筛选数据,并将这些数据插入到target_tbl1中,替换其原有内容。INSERT OVERWRITE target_tbl1 SELECT * FROM source_tbl1 WHERE col3 > 25; -
查看表
target_tbl1替换数据后的数据。SELECT * FROM target_tbl1;返回结果如下:
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
| 1 | A1 | 30 |
+------+------+------+
1 row in set
示例二
INSTER OVERWRITE PARTITION SELECT 使用示例:
-
创建分区表
t1_ins_overwrt。CREATE TABLE t1_ins_overwrt (c1 int primary key, c2 int) partition by range(c1)(
partition p0 values less than(10),
partition p1 values less than(20),
partition p2 values less than(30),
partition p3 values less than (MAXVALUE)
);
Query OK, 1 row affected -
创建分区表
t2_ins_overwrt。CREATE TABLE t2_ins_overwrt (c1 int primary key, c2 int) partition by range(c1)(
partition p0 values less than(10),
partition p1 values less than(20),
partition p2 values less than(30),
partition p3 values less than (MAXVALUE)
);
Query OK, 1 row affected -
分别向两表中插入几条数据。
INSERT INTO t1_ins_overwrt values (1, 10), (12, 20), (23, 30), (34, 40), (45, 50);
Query OK, 5 rows affected (0.018 sec)
Records: 5 Duplicates: 0 Warnings: 0
INSERT INTO t2_ins_overwrt values (3, 60), (8, 80), (17, 170), (26, 260), (29, 290), (142, 1420);
Query OK, 6 rows affected (0.015 sec)
Records: 6 Duplicates: 0 Warnings: 0 -
分别查询两张表中 p3 分区的数据。
SELECT * FROM t1_ins_overwrt partition(p3);
+------+------+
| c1 | c2 |
+------+------+
| 34 | 40 |
| 45 | 50 |
+------+------+
2 rows in set (0.006 sec)
SELECT * FROM t2_ins_overwrt partition(p3);
+------+------+
| c1 | c2 |
+------+------+
| 142 | 1420 |
+------+------+
1 row in set (0.006 sec) -
执行如下 SQL 将
t1_ins_overwrt表中 p3 分区的数据插入到t2_ins_overwrt表的 p3 分区中。INSERT OVERWRITE t2_ins_overwrt partition(p3) select * from t1_ins_overwrt partition(p3);
Query OK, 2 rows affected (1.354 sec)
Records: 2 Duplicates: 0 Warnings: 0 -
查询
t2_ins_overwrt表的 p3 分区,发现数据已经被覆盖了。SELECT * FROM t2_ins_overwrt partition(p3);
+------+------+
| c1 | c2 |
+------+------+
| 34 | 40 |
| 45 | 50 |
+------+------+
2 rows in set (0.006 sec)
示例三
-
创建有分区表
tbl1。CREATE TABLE tbl1(col1 INT,col2 INT)
PARTITION BY RANGE COLUMNS(col1)
SUBPARTITION BY HASH(col2) SUBPARTITIONS 3 (
PARTITION p0 VALUES LESS THAN(10),
PARTITION p1 VALUES LESS THAN(20));
Query OK, 0 rows affected -
在
tbl1表中插入一条数据。INSERT INTO tbl1 (col1, col2) VALUES (2, 3);
INSERT INTO tbl1 (col1, col2) VALUES (15, 2); -
查询表
tbl1p0 分区中是否插入数据。SELECT * FROM tbl1 PARTITION (p0);查询结果如下:
+------+------+
| col1 | col2 |
+------+------+
| 2 | 3 |
+------+------+SELECT * FROM tbl1 PARTITION (p1);查询结果如下:
+------+------+
| col1 | col2 |
+------+------+
| 15 | 2 |
+------+------+ -
创建分区表
tbl2。CREATE TABLE tbl2(col1 INT,col2 INT)
PARTITION BY RANGE COLUMNS(col1)
SUBPARTITION BY HASH(col2) SUBPARTITIONS 3 (
PARTITION p0 VALUES LESS THAN(10),
PARTITION p1 VALUES LESS THAN(20));
Query OK, 0 rows affected -
插入数据到表
tbl2中。INSERT INTO tbl2 (col1, col2) VALUES (0, 22);
INSERT INTO tbl2 (col1, col2) VALUES (18, 6); -
查询表
tbl2中p0和p1分区是否有数据插入。SELECT * FROM tbl2 PARTITION (p0);查询结果如下:
+------+------+
| c1 | c2 |
+------+------+
| 0 | 22 |
+------+------+SELECT * FROM tbl2 PARTITION (p1);查询结果如下:
+------+------+
| c1 | c2 |
+------+------+
| 18 | 6 |
+------+------+ -
使用
insert overwrite将表tbl1中的数据覆盖写到表tbl2中的指定分区p1中。insert overwrite tbl2 partition (p1) select * from tbl1 partition (p1); -
验证表
tbl2中 p1 分区的数据是否已经被覆盖。SELECT * FROM tbl2 PARTITION (p1);查询结果如下:
+------+------+
| col1 | col2 |
+------+------+
| 15 | 2 |
+------+------+结果显示表
tbl2中 p1 分区的数据已被覆盖。
使用 REPLACE INTO 语句插入数据
除了 INSERT 语句,当表中无数据记录,或者表中有数据记录但无主键或唯一键冲突时,还可以使用 REPLACE INTO 语句代替 INSERT 语句插入数据。REPLACE INTO 语句的详细语法及说明请参见 REPLACE。
示例:
-
创建
t_replace表后,使用REPLACE INTO语句插入数据。CREATE TABLE t_replace(
id int NOT NULL PRIMARY KEY,
name varchar(10) NOT NULL,
value int,
gmt_create timestamp NOT NULL DEFAULT current_timestamp
);
Query OK, 0 rows affected
REPLACE INTO t_replace VALUES(1,'CN',2001, current_timestamp ());
Query OK, 1 row affected
SELECT * FROM t_replace;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 2001 | 2025-12-23 10:55:53 |
+----+------+-------+---------------------+
1 row in set -
在有数据记录的表
t_replace中,使用REPLACE INTO语句插入数据。SELECT * FROM t_replace;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 2001 | 2025-12-23 10:55:53 |
+----+------+-------+---------------------+
1 row in set
REPLACE INTO t_replace values(2,'US',2002, current_timestamp ());
Query OK, 1 row affected
SELECT * FROM t_replace;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 2001 | 2025-12-23 10:55:53 |
| 2 | US | 2002 | 2025-12-23 10:56:23 |
+----+------+-------+---------------------+
2 rows in set