3.9.2 插入
要往关系中插入数据,我们可以指定待插入的元组,或者写一条查询语句来生成待插入的元组集合。显然,待插入元组的属性值必须在相应属性的域中。同样,待插入元组的分量数也必须是正确的。
按表中定义的顺序插入元组
最简单的insert
语句是单个元组的插入请求。假设我们想要插入的信息是Computer Science
系开设的名为"Database Systems"
的课程CS-437
,它有4个学分。我们可写成:
1 | insert into course |
1 | mysql> insert into course |
在此例中,元组属性值的排列顺序和关系模式中属性排列的顺序一致。
按指定顺序插入元组
考虑到用户可能不记得关系属性的排列顺序,SQL
允许在insert
语句中指定属性。例如,以下SQL insert
语句与前述语句的功能相同。
1 | insert into course(course_id, title, dept_name, credits) |
1 | mysql> insert into course(course_id, title, dept_name, credits) |
1 | insert into course(title, course_id, credits, dept_name) |
1 | mysql> insert into course(title, course_id, credits, dept_name) |
在查询结果的基础上插入
更通常的情况是,我们可能想在查询结果的基础上插入元组。假设我们想让Music
系每个修满144学分的学生成为Music
系的教师,其工资为18000美元。我们可写作:
1 | insert into instructor |
和本节前面的例子不同的是,我们没有指定一个元组,而是用select
选出一个元组集合。SQL
先执行这条select
语句,求出将要插入到instructor
关系中的元组集合。每个元组都有ID
、dept_name(Music)
和工资(18000美元)。
要保证select先执行完毕
在执行插入之前先执行完select
语句是非常重要的。
如果在执行select
语句的同时执行插入动作如果在student
上没有主码约束的话,像:
1 | insert into student |
这样的请求就可能会插入无数元组。如果没有主码约束,上述请求会重新插入student
中的第一个元组,产生该元组的第二份拷贝。由于这个副本现在是student
中的一部分, select
语句可能找到它,于是第三份拷贝被插入到student
中。第三份拷贝又可能被select
语句发现,于是又插入第四份拷贝,如此等等,无限循环。
在执行插入之前先完成select
语句的执行可以避免这样的问题。这样,如果在student
关系上没有主码约束,那么上述insert
语句就只是把student
关系中的每个元组都复制一遍。
没有给出值的属性会被设置为null
在讨论insert
语句时我们只考虑了这样的例子:待插人元组的每个属性都被赋了值。但是有可能待插入元组中只给出了模式中部分属性的值,那么其余属性将被赋空值,用null
表示。
考虑请求:
1 | insert into student |
此请求所插入的元组代表了一个在Finance
系、ID为”3003”的学生,但其tot_cred
值是未知的。
考虑查询:
1 | select ID from student |
1 | mysql> insert into student |
既然”3003”号学生的ot cred
值未知,我们不能确定它是否大于45。所以上述查询结果中不会出现”3003”
从格式化文本文件插入元组
大部分关系数据库产品有特殊的”bulk loader
“工具,它可以向关系中插入一个非常大的元组集合。这些工具允许从格式化文本文件中读出数据,且执行速度比同等目的的插入语句序列要快得多。
原文链接: 3.9.2 插入