5.5 SQL的数据操纵功能

5.5.1 数据插入

  使用CREATE语句创建的数据表还只是一个“空壳”,表中没有任何数据。利用SQL语言提供的INSERT语句可以完成向数据表插入数据的任务。

INSERT语句的语法格式为:

INSERT [INTO] <table>[(<column1>[, <column2>…])]

VALUES(<value1>[, <value2>…]);

  table表示表名,value1, value2, …分别表示待插入的常量值,它们插入后形成同一条记录上的各个字段值,且value1与字段column1对应,value2与字段column2对应,等。

  关于插入语句INSERT,应注意以下几点:

  <table>后面字段的顺序和数量都可以是任意的(当然,字段的数量必须少于或等于表中定义字段的数量)。但是对给定顺序的字段列表,VALUES子句中的常量值要分别按位置与字段列表中的字段相对应,而且数据类型也要一致。每个常量值必须是具体的值,而不能没有值。注意,“没有值”不是空值(NULL),它们是两个不同的概念。

  如果<table>后面没有指定字段列表,那么待插入的常量值的顺序必须与表中定义字段的顺序一样。

  除了在定义表时被设置为NOT NULL以外,任何数据类型的字段都可以插入NULL(空值)。

【例5.25】 用INSERT语句将一个学号为“20170201”、姓名为“刘洋”、性别为“女”、出生日期为“1997-02-03”、专业为“计算 机应用技术”、平均成绩为“98.5”、系别为“计算机系”的学生记录插入数据表student中。

根据以上信息,构造以下的记录:('20170201','刘洋','女','1997-02-03','计算机应用技术',98.5,'计算机系')。该记录中各分量值(常量值)的顺序与表student中定义字段的顺序相同,且数据类型也分别相同,因此可以用不带字段列表的INSERT语句来实现数据插入。代码如下:

INSERT student(s_no,s_name,s_sex,s_birthday, s_speciality,s_avgrade,s_dept)

VALUES('','刘洋','女','1997-02-03','计算机应用技术',98.5,'计算机系');

该语句等价下列语句:

INSERT INTO student

VALUES('','刘洋','女','1997-02-03','计算机应用技术',98.5,'计算机系');

【例5.26】 用INSERT语句将一个学生记录('20170202','王晓珂', 88.1) 插入数据表student中。

由于该记录并不包含所有的字段值,故在该INSERT语句中必须显式指定字段列表(s_no, s_name, s_avgrade)。其实现代码如下:

INSERT INTO student(s_no,s_name,s_avgrade)

VALUES('','王晓珂', 88.1); 

由于字段的顺序可以是任意的(但插入值要与字段对应),所以该语句等价与下列的INSERT语句:

INSERT  INTO student(s_name, s_avgrade, s_no)

VALUES('王晓珂', 88.1, '');

  注意:主键字段的值不能重复,也不能为空值(NULL);

  被设为NOT NULL的字段的插入值也不能为空值。

  此外,对于其他没有被插入的字段(如字段s_sex, s_birthday等),如果在定义表时设置了默认值,则这些字段会自动填上默认值,否则自动填上空值。

  在执行上述语句后,新插入的记录在字段s_speciality和s_dept上分别取默认值“计算机软件与理论”和“计算机科学系”,在字段s_sex和s_birthday,上都取空值(NULL)。

  另一种插入数据的方法是在INSERT语句中嵌入子查询,以子查询的返回结果集作为插入的数据。这样可以实现数据的批量插入,这在许多地方都有应用。但要求子查询的返回结果集和被插入数据的数据表在结果上要一致,否则无法完成插入操作。

【例5.27】  查询表student中学生的学号、姓名、专业、平均成绩和系别,并将查询结果输入到另一个数据表中。

首先要创建一个包含学号(s_no)、姓名(s_name)、专业(s_speciality)、平均成绩(s_avgrade)和系别(s_dept)的数据表student2,相应CREATE语句如下:

CREATE TABLE student2(

s_no char(8) PRIMARY KEY,

s_name char(8) NOT NULL,

s_speciality varchar(50) DEFAULT  '计算机软件与理论',

s_avgrade numeric(3,1) CHECK(s_avgrade >= 0 AND s_avgrade <= 100),

s_dept varchar(50) DEFAULT  '计算机科学系'

); 

创建如下的查询:

SELECT s_no, s_name, s_speciality, s_avgrade, s_dept

FROM student;

  可以看出,上述查询返回的结果集在结构上与表student2是一致的。所以,该查询可以作为子查询嵌入到用于向表student1插入数据的INSERT语句中,从而实现将查询结果插入到表student2中的目的。相应的SQL语句如下:

INSERT INTO student2(s_no, s_name, s_speciality, s_avgrade, s_dept)

(SELECT s_no, s_name, s_speciality, s_avgrade, s_dept

FROM student); 

注意:上述INSERT语句中并无关键字VALUES。

5.5.2 数据更新

  在数据输入到数据表以后,或者是由于错误的输入,或者是由于应用环境和时间的变化等原因,都有可能需要对表中的数据进行修改。在SQL语句中,UPDATE语句提供了数据修改功能。其语法格式如下:

UPDATE <table>

SET <column1> = <value1>[,<column2> = <value2>…]

[WHERE <condition_expression>]; 

  <table>表示要修改数据的表;关键字SET后面的column1, column2, …表示要修改的字段,value1, value2, …对应字段修改后的新值;condition_expression为一逻辑表达式,此处表示修改条件。如果UPDATE语句不包含WHERE子句,则表示无条件对表中所有记录都进行修改(无条件修改);如果包含了WHERE子句,那么只有对满足修改条件的记录进行修改(有条件修改)。

【例5.28】 将所有学生的平均成绩都减5分。

这是一个无条件修改,相应语句如下:

UPDATE student

SET s_avgrade = s_avgrade - 5;

【例5.29】 将所有女学生的平均成绩都加上其原来分数的0.5%。

这是一个有条件修改,相应语句如下:

UPDATE student

SET s_avgrade = s_avgrade + s_avgrade*0.005

WHERE s_sex = '女';

  在项目开发实践中,经常遇到这样的操作:用一个表去更新另外一个表。在这种更新操作中,有一些“技巧”需要注意。根据1.5.2节的分析,两个表(实体)之间的联系主要有三种情况:(1:1)、(1:n)和(m:n)。如果两个表之间的联系是(m:n),则不宜用任何一个表去更新另外一个表;如果它们的联系是(1:n),则可以用“1”对应的表去更新“n”对应的表;如果它们的联系是(1:1),则可以用其中任何一个表去更新另外一个表。

【例5.30】 用学分表credit去更新课程信息表SC2。

从SQL语法上看,用一个表去更新另一个表,相应语句并不复杂。但要保证其语义上的正确性,这并不容易。我们考虑这样的例子:学分表credit保存了每门课程的课程名和学分,课程信息表SC2则保存学生选修的课程信息,包括学号、课程名、成绩和学分。表credit和表SC2的定义代码如下:

CREATE TABLE credit(  -- 表credit

c_name varchar(20)  PRIMARY KEY,

c_credit    int

);

CREATE TABLE SC2(  -- 表SC2  

s_no char(8),

c_name varchar(20),

c_gradenumeric(3,1)       CHECK(c_grade >= 0 AND c_grade <= 100),

c_credit   int,

PRIMARY KEY(s_no, c_name)       --将(s_no, c_name)设为主键

);

然后在这两个表中添加相关数据:

INSERT credit VALUES('英语',3);

INSERT credit VALUES('数据库原理',4);

INSERT credit VALUES('算法设计与分析',2);

INSERT SC2(s_no,c_name,c_grade) VALUES('','英语',80.2);

INSERT SC2(s_no,c_name,c_grade) VALUES('','数据库原理',70.0);

INSERT SC2(s_no,c_name,c_grade) VALUES('','算法设计与分析',92.4);

INSERT SC2(s_no,c_name,c_grade) VALUES('','英语',81.9);

INSERT SC2(s_no,c_name,c_grade) VALUES('','算法设计与分析',85.2);

INSERT SC2(s_no,c_name,c_grade) VALUES('','多媒体技术',68.1);

注意,表SC2中的学分字段c_credit未添加任何数据。可以看到,表credit和表SC2之间的联系是基于课程名称c_name的(1:n)联系(“一对多”联系),即表credit中的一条数据可能对应着表SC2中的多条数据,因此可以用“1”对应的表c_credit去更新“n”对应的表SC2。具体地,可以用表credit中的学分字段c_credit去更新表SC2中的学分字段c_credit,相应UPDATE语句如下:

UPDATE  SC2

SET SC2.c_credit = credit.c_credit

FROM SC2

JOIN credit

ON SC2.c_name = credit.c_name

执行上述语句后,表SC2中的内容如下:

s_no c_namec_grade                c_credit

---------------------------------------------------------------------------------------------------

20170201数据库原理                      70.04

20170201算法设计与分析92.42

20170201英语80.23

20170202算法设计与分析85.22

20170202英语81.93

20170203多媒体技术     68.1NULL

可以看到,更新结果是正确的。

需要注意的是,在“一对多”的两个表中,必须保证是用“1”表去更新“n”表,否则极为可能出现问题。

说明: 如果用表SC2去更新表credit,则会容易出现不一致性等问题。请读者考虑这个问题。

【例5.30】 假设表student中的平均成绩(s_avgrade)是由表SC中的课程成绩(c_grade)平均得到的,请通过查询表SC的方法来更新表student中的s_avgrade字段值,使之满足上述假设。    
        对于“刘洋”的平均成绩,它是《英语》、《数据库原理》和《算法设计与分析》这三门课程成绩的平均值(因为表SC显示“刘洋”选修了这三门课程),结果应该是(70.0+92.4+80.2)/3=80.9。对于其他学生的平均成绩亦可类推。

但是用SQL语言求出各个学生的平均成绩并填到表student中,这不是一件很容易的事情。我们通过创建一个用于存放中间结果的数据表的方法来解决这个问题,相应的SQL语句及其说明如下:

(1) 创建一个用于存放中间结果的数据表tmp_table

CREATE TABLE tmp_table(

s_no char(8),  

s_avgrade numeric(3,1)  

);

(2)通过按学号分组的方法求各个学生的平均成绩,并将其学号和平均成绩存放到表tmp_table中

INSERT INTO tmp_table(s_no,s_avgrade)

(SELECT  s_no, AVG(c_grade) --c_grade

FROM SC

GROUP BY s_no);

表student和表tmp_table的联系是基于字段s_no的(1:1)联系。因此,我们可以用表tmp_table中的平均成绩字段s_avgrade去更新表student中的平均成绩字段s_avgrade:

UPDATE student

SET s_avgrade = b.s_avgrade

FROM  student as a

JOIN tmp_table as b

ON a.s_no = b.s_no

DROP TABLE tmp_table; -- 删除临时数据表

经过一次性执行以上代码后即可计算出各位学生的平均成绩。

5.5.3 数据删除

  一般来说,数据也有个生成、发展和淘汰的过程。随着时间的推移,在经过长期使用后有些数据必须予以淘汰。对数据库来说,淘汰就意味着删除。在SQL语言中,DELETE  语句提供了数据删除功能,其一般语法格式如下:

DELETE   

FROM <table>

[WHERE <condition_expression>];

table表示要删除数据的表,condition_expression亦为一逻辑表达式,此处表示删除条件。如果DELETE语句不包含WHERE子句,则表示无条件删除表<table>中所有的数据(无条件删除);如果包含了WHERE子句,那么只删除那些满足删除条件的记录(有条件删除)。

【例5.31】 删除表student中的所有数据。

这是一个无条件删除,其实现语句如下:

DELETE FROM student;

【例5.32】 删除表student中没有选修任何课程的学生。

这是一个有条件删除。由于学生的选课信息保存在表SC中,所以这个删除操作要涉及到两个数据表。一个直观的想法是,只要一个学生的学号没有在表SC中出现,则表明该学生没有选修课程,应予以删除。因此,很容易想到使用子查询来实现:

DELETE   

FROM student

WHERE s_no NOT IN (

SELECT s_no

FROM SC);

30442数据操纵语言DML的更多相关文章

  1. (让你提前知道软件开发33):数据操纵语言(DML)

    文章2部分 数据库SQL语言 数据操纵语言(DML) 数据操纵语言(Data Manipulation Language,DML)包含insert.delete和update语句,用于增.删.改数据. ...

  2. MySQL之数据操纵语言(DML)

    数据操纵语言(DML) 数据操纵语(Data Manipulation Language),简称DML. DML主要有四个常用功能. 增 删 改 查 insert delete update sele ...

  3. oracle数据操纵语言(DML)data manipulation language

    数据库操纵语言(DML)用于查询和操纵模式对象中的数据,它不隐式地提交当前事务. SELECTINSERTUPDATEDELETECALLEXPLAIN PLANLOCK TABLEMERGE使用算术 ...

  4. oracle数据操纵语言(DML)data manipulation language(续集)

    SQL查询语句(SELECT)进阶分组函数(Group Functions):对多行进行操作,并为每一组给出一个结果. AVG([DISTINCT|ALL] expression) 平均值COUNT ...

  5. 【MySQL笔记】数据操纵语言DML

    1.数据插入   INSERT INTO table_name (列1, 列2,...) VALUES(值1, 值2,....),(第二条),(第三条)...   注: 1)如果表中的每一列均有数据插 ...

  6. DML(数据操纵语言)

    1.概念(C) 数据操纵语言 DML (Data Manipulation Langua)是SQL语言的一个分类,用于对表的内容或者说数据进行增.删.改.查等操作. 通过以下几个关键字实现: SELE ...

  7. sql 语言--- DML,DDL,DQL,DCL,TCL,CCL

    结构化查询语言(Structured Query Language)简称SQL                是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询.更新和管理 ...

  8. 数据操作语言DML与运算符

    数据操作语言DML(添加,修改,删除) 1.添加数据 insert into insert into 表名 (字段列表) values (值列表),值列表要和字段列表按顺序匹配. insert int ...

  9. 数据库原理及应用-SQL数据操纵语言(Data Manipulation Language)和嵌入式SQL&存储过程

    2018-02-19 18:03:54 一.数据操纵语言(Data Manipulation Language) 数据操纵语言是指插入,删除和更新语言. 二.视图(View) 数据库三级模式,两级映射 ...

随机推荐

  1. QT之圆形头像(使用PNG的Mask达到的效果)

    废话不多说!直接上代码. 我们在很多UI设计应用中,需要用到自定义形状头像,在这里,我对圆形头像的设计做简单的阐述,其它形状头像可参考本文做相应的更改即可.如下图所示为设计的圆形头像: 上代码: Se ...

  2. SQL Server 统计某个月周末的天数

    ---注意:这里统计的周末包括周5,周6,但不包括周日ALTER FUNCTION [dbo].[GetWeekDaysByMonth] ( @Year INT, @Month INT, @Day I ...

  3. Java--数组和链表的区别以及使用场景

    数组:是将元素在内存中连续存储的:它的优点:因为数据是连续存储的,内存地址连续,所以在查找数据的时候效率比较高:它的缺点:在存储之前,我们需要申请一块连续的内存空间,并且在编译的时候就必须确定好它的空 ...

  4. python 教程 第十六章、 正则表达式

    第十六章. 正则表达式 1)    匹配多个表达式 记号  re1|re2 说明  匹配正则表达式re1或re2 举例  foo|bar  匹配  foo, bar 记号  {N} 说明  匹配前面出 ...

  5. WPF窗体隐藏鼠标光标的方法

    原文:WPF窗体隐藏鼠标光标的方法 要引用 System.Windows.Input;   Mouse.OverrideCursor = Cursors.None; 去掉 Override 则使用: ...

  6. react项目实践——(1)使用webpack创建项目

    1. 新建文件夹,命名为项目名称——myapp,并打开myapp文件夹. mkdir webpack-demo && cd webpack-demo 2. 在./myapp中打开命令行 ...

  7. [转]Nodejs开发框架Express4.x开发手记

    Express: ?web application framework for?Node.js? Express 是一个简洁.灵活的 node.js Web 应用开发框架, 它提供一系列强大的特性,帮 ...

  8. MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制

    最近一直做物联网方面的开发,以下内容关于使用MQTT过程中遇到问题的记录以及需要掌握的机制原理,主要讲解理论. 背景 MQTT是IBM开发的一个即时通讯协议.MQTT构建于TCP/IP协议上,面向M2 ...

  9. DataGrid DataGridTemplateColumn

    设置单元格的样式 <DataGrid.Columns> <DataGridTextColumn Header="检测项目" Binding="{Bind ...

  10. GetDateFormat和GetTimeFormat两个API

    https://msdn.microsoft.com/en-us/library/windows/desktop/dd318086(v=vs.85).aspx