3.9.2 插入

3.9.2 插入

要往关系中插入数据,我们可以指定待插入的元组,或者写一条查询语句来生成待插入的元组集合。显然,待插入元组的属性值必须在相应属性的域中。同样,待插入元组的分量数也必须是正确的。

按表中定义的顺序插入元组

最简单的insert语句是单个元组的插入请求。假设我们想要插入的信息是**Computer Science系开设的名为"Database Systems"的课程CS-437,它有4个学分**。我们可写成:

1
2
insert into course
values('CS-437', 'Database Systems', 'Comp. Sci. ',4);
1
2
3
mysql> insert into course
values('CS-437', 'Database Systems', 'Comp. Sci. ',4);
Query OK, 1 row affected (0.02 sec)

在此例中,元组属性值的排列顺序和关系模式中属性排列的顺序一致。

按指定顺序插入元组

考虑到用户可能不记得关系属性的排列顺序,SQL允许在insert语句中指定属性。例如,以下SQL insert语句与前述语句的功能相同。

1
2
insert into course(course_id, title, dept_name, credits)
values('CS-437', 'Database Systems','Comp. Sci. ', 4);
1
2
3
mysql> insert into course(course_id, title, dept_name, credits)
values('CS-437', 'Database Systems','Comp. Sci. ', 4);
Query OK, 1 row affected (0.01 sec)
1
2
insert into course(title, course_id, credits, dept_name)
values('Database Systems', 'CS-437', 4,'Comp. Sci. ');
1
2
3
mysql> insert into course(title, course_id, credits, dept_name)
values('Database Systems', 'CS-437', 4,'Comp. Sci. ');
Query OK, 1 row affected (0.01 sec)

在查询结果的基础上插入

更通常的情况是,我们可能想在查询结果的基础上插入元组。假设我们想让Music系每个修满144学分的学生成为Music系的教师,其工资为18000美元。我们可写作:

1
2
3
4
insert into instructor
select ID, name, dept_name, 18000
from student
where dept_name ='Music' and tot_cred>144;

和本节前面的例子不同的是,我们没有指定一个元组,而是用select选出一个元组集合。**SQL先执行这条select语句,求出将要插入到instructor关系中的元组集合**。每个元组都有IDdept_name(Music)和工资(18000美元)。

要保证select先执行完毕

在执行插入之前先执行完select语句是非常重要的。
如果在执行select语句的同时执行插入动作如果在student上没有主码约束的话,像:

1
2
insert into student
select * from student;

这样的请求就可能会插入无数元组。如果没有主码约束,上述请求会重新插入student中的第一个元组,产生该元组的第二份拷贝。由于这个副本现在是student中的一部分, select语句可能找到它,于是第三份拷贝被插入到student中。第三份拷贝又可能被select语句发现,于是又插入第四份拷贝,如此等等,无限循环。
在执行插入之前先完成select语句的执行可以避免这样的问题。这样,如果在student关系上没有主码约束,那么上述insert语句就只是把student关系中的每个元组都复制一遍。

没有给出值的属性会被设置为null

在讨论insert语句时我们只考虑了这样的例子:待插人元组的每个属性都被赋了值。但是有可能待插入元组中只给出了模式中部分属性的值,那么其余属性将被赋空值,用null表示
考虑请求:

1
2
insert into student
values('3003', 'Green','Finance', null);

此请求所插入的元组代表了一个在Finance系、ID为”3003”的学生,但其tot_cred值是未知的。
考虑查询:

1
2
select ID from student
where tot_cred>45;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> insert into student
values('3003', 'Green','Finance', null);
Query OK, 1 row affected (0.02 sec)

mysql> select ID from student
where tot_cred>45;
+-------+
| ID |
+-------+
| 00128 |
| 19991 |
| 23121 |
| 44553 |
| 45678 |
| 54321 |
| 76543 |
| 76653 |
| 98765 |
| 98988 |
+-------+
10 rows in set (0.06 sec)

既然”3003”号学生的ot cred值未知,我们不能确定它是否大于45。所以上述查询结果中不会出现”3003”

从格式化文本文件插入元组

大部分关系数据库产品有特殊的”bulk loader“工具,它可以向关系中插入一个非常大的元组集合。这些工具允许从格式化文本文件中读出数据,且执行速度比同等目的的插入语句序列要快得多。