本文介绍如何利用 SQL 的 INSERT
语句将数据插入表中。
1. 数据插入
顾名思义,INSERT
用来将行插入(或添加)到数据库表。插入有几种方式:
- 插入完整的行;
- 插入行的一部分;
- 插入某些查询的结果。
下面逐一介绍这些内容。
1.1 插入完整的行
把数据插入表中的最简单方法是使用基本的 INSERT
语法,它要求指定表名和插入到新行中的值。下面举一个例子:
sql">INSERT INTO Customers
VALUES(1000000006,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA',
NULL,
NULL);
分析:这个例子将一个新顾客插入到 Customers
表中。存储到表中每一列的数据在 VALUES
子句中给出,必须给每一列提供一个值。如果某列没有值,如上面的 cust_contact
和 cust_email
列,则应该使用 NULL
值(假定表允许对该列指定空值)。各列必须以它们在表定义中出现的次序填充。
提示:INTO
关键字
在某些 SQL 实现中,跟在 INSERT
之后的 INTO
关键字是可选的。但是,即使不一定需要,最好还是提供这个关键字,这样做将保证 SQL 代码在 DBMS 之间可移植。
虽然这种语法很简单,但并不安全,应该尽量避免使用。上面的 SQL 语句高度依赖于表中列的定义次序,还依赖于其容易获得的次序信息。即使可以得到这种次序信息,也不能保证各列在下一次表结构变动后保持完全相同的次序。因此,编写依赖于特定列次序的 SQL 语句是很不安全的,这样做迟早会出问题。
编写 INSERT
语句的更安全(不过更烦琐)的方法如下:
sql">INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES(1000000006,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA',
NULL,
NULL);
分析:这个例子与前一个 INSERT
语句的工作完全相同,但在表名后的括号里明确给出了列名。在插入行时,DBMS 将用 VALUES
列表中的相应值填入列表中的对应项。VALUES
中的第一个值对应于第一个指定列名,第二个值对应于第二个列名,如此等等。
因为提供了列名,VALUES
必须以其指定的次序匹配指定的列名,不一定按各列出现在表中的实际次序。其优点是,即使表的结构改变,这条 INSERT
语句仍然能正确工作。
说明:不能插入同一条记录两次
如果你尝试了这个例子的两种方法,会发现第二次生成了一条出错消息,说 ID 为 1000000006
的顾客已经存在。在第一课我们说过,主键的值必须有唯一性,而 cust_id
是主键,DBMS 不允许插入相同 cust_id
值的新行。
下面的 INSERT
语句填充所有列(与前面的一样),但以一种不同的次序填充。因为给出了列名,所以插入结果仍然正确:
sql">INSERT INTO Customers(cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip)
VALUES(1000000006,
NULL,
NULL,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111');
提示:总是使用列的列表
不要使用没有明确给出列的 INSERT
语句。给出列能使 SQL 代码继续发挥作用,即使表结构发生了变化。
注意:小心使用 VALUES
不管使用哪种 INSERT
语法,VALUES
的数目都必须正确。如果不提供列名,则必须给每个表列提供一个值;如果提供列名,则必须给列出的每个列一个值。否则,就会产生一条错误消息,相应的行不能成功插入。
1.2 插入部分行
正如所述,使用 INSERT
的推荐方法是明确给出表的列名。使用这种语法,还可以省略列,这表示可以只给某些列提供值,给其他列不提供值。
请看下面的例子:
sql">INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
VALUES(1000000006,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA');
分析:在前面的例子中,没有给 cust_contact
和 cust_email
这两列提供值。这表示没必要在 INSERT
语句中包含它们。因此,这里的 INSERT
语句省略了这两列及其对应的值。
注意:省略列
如果表的定义允许,则可以在 INSERT
操作中省略某些列。省略的列必须满足以下某个条件:
- 该列定义为允许
NULL
值(无值或空值)。 - 在表定义中给出默认值。这表示如果不给出值,将使用默认值。
注意:省略所需的值
如果表中不允许有 NULL
值或者默认值,这时却省略了表中的值,DBMS 就会产生错误消息,相应的行不能成功插入。
1.3 插入检索出的数据
INSERT
一般用来给表插入具有指定列值的行。INSERT
还存在另一种形式,可以利用它将 SELECT
语句的结果插入表中,这就是所谓的 INSERT SELECT
。顾名思义,它是由一条 INSERT
语句和一条 SELECT
语句组成的。
假如想把另一表中的顾客列合并到 Customers
表中,不需要每次读取一行再将它用 INSERT
插入,可以如下进行:
sql">INSERT INTO Customers(cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
SELECT cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country
FROM CustNew;
说明:新例子的说明
这个例子从一个名为 CustNew
的表中读出数据并插入到 Customers
表。为了试验这个例子,应该首先创建和填充 CustNew
表。CustNew
表的结构与 Customers
表相同。在填充 CustNew
时,不应该使用已经在 Customers
中用过的 cust_id
值(如果主键值重复,后续的 INSERT
操作将会失败)。
分析:这个例子使用 INSERT SELECT
从 CustNew
中将所有数据导入 Customers
。SELECT
语句从 CustNew
检索出要插入的值,而不是列出它们。SELECT
中列出的每一列对应于 Customers
表名后所跟的每一列。这条语句将插入多少行呢?这依赖于 CustNew
表有多少行。如果这个表为空,则没有行被插入(也不产生错误,因为操作仍然是合法的)。如果这个表确实有数据,则所有数据将被插入到 Customers
。
提示:INSERT SELECT
中的列名
为简单起见,这个例子在 INSERT
和 SELECT
语句中使用了相同的列名。但是,不一定要求列名匹配。事实上,DBMS 一点儿也不关心 SELECT
返回的列名。它使用的是列的位置,因此 SELECT
中的第一列(不管其列名)将用来填充表列中指定的第一列,第二列将用来填充表列中指定的第二列,如此等等。
INSERT SELECT
中 SELECT
语句可以包含 WHERE
子句,以过滤插入的数据。
提示:插入多行
INSERT
通常只插入一行。要插入多行,必须执行多个 INSERT
语句。INSERT SELECT
是个例外,它可以用一条 INSERT
插入多行,不管 SELECT
语句返回多少行,都将被 INSERT
插入。
2. 从一个表复制到另一个表
有一种数据插入不使用 INSERT
语句。要将一个表的内容复制到一个全新的表(运行中创建的表),可以使用 CREATE SELECT
语句(或者在 SQL Server 里也可用 SELECT INTO
语句)。
说明:DB2 不支持
DB2 不支持这里描述的 CREATE SELECT
。
与 INSERT SELECT
将数据添加到一个已经存在的表不同,CREATE SELECT
将数据复制到一个新表(有的 DBMS 可以覆盖已经存在的表,这依赖于所使用的具体 DBMS)。
下面的例子说明如何使用 CREATE SELECT
:
sql">CREATE TABLE CustCopy AS SELECT * FROM Customers;
若是使用 SQL Server,可以这么写:
sql">SELECT * INTO CustCopy FROM Customers;
分析:这条 SELECT
语句创建一个名为 CustCopy
的新表,并把 Customers
表的整个内容复制到新表中。因为这里使用的是 SELECT *
,所以将在 CustCopy
表中创建(并填充)与 Customers
表相同的列结构。
3. 插入数据时的注意事项
插入数据时有几个常见的注意点:
-
数据类型匹配: 在使用
INSERT
语句时,确保插入的数据与目标表的列的数据类型匹配。例如,如果某个列定义为INT
类型,你不能尝试插入一个字符串值。 -
约束条件: 如果目标表的列有约束条件(如
NOT NULL
、UNIQUE
、PRIMARY KEY
),插入数据时需要确保这些约束得到满足,否则会导致插入失败。 -
默认值与
NULL
值: 如果某些列允许NULL
或有默认值,你可以选择不插入值,DBMS 将自动填充NULL
或默认值。如果列没有设置默认值且不允许NULL
,插入时必须提供值。 -
避免重复数据: 在插入数据时,要特别注意主键的唯一性。如果尝试插入一条具有相同主键的记录,将会出现错误。在插入前,可以使用查询检查主键值是否已存在。
-
批量插入: 在某些情况下,需要批量插入数据。可以使用多行
INSERT
语句来一次性插入多条记录。例如:sql">INSERT INTO Customers (cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) VALUES (1000000007, 'Toy Factory', '456 Some Street', 'Los Angeles', 'CA', '90001', 'USA'), (1000000008, 'Tech Zone', '789 Tech Road', 'San Francisco', 'CA', '94105', 'USA'), (1000000009, 'Book World', '101 Book Lane', 'Chicago', 'IL', '60601', 'USA');
-
事务处理: 如果你执行多个插入操作,并且这些操作之间有依赖关系,可以将它们放在一个事务中,确保数据一致性。如果在插入过程中出现错误,事务可以回滚,从而避免部分插入成功导致数据不一致的情况。
4. 总结
INSERT
语句是 SQL 中用来向表中插入数据的基础工具,理解和掌握不同的插入方式对于有效地管理数据库至关重要。插入数据时应注意以下几点:
- 明确指定列名和插入顺序,以确保插入数据的安全性。
- 小心处理
NULL
和默认值。 - 使用
INSERT SELECT
语法插入来自其他表的数据。 - 在批量插入数据时,要确保数据的一致性和完整性。
- 通过事务控制确保插入操作的原子性。
了解这些插入数据的基本操作和注意事项,能够帮助你更高效地进行数据库的管理与维护。