database-03-SQL介绍
数据库系统原理
SQL介绍
2025
SQL查询语言概览§3.1
- Sequel language 是IBM圣何塞研究实验室R系统项目的一部分
- 后更名: Structured Query Language (
SQL)
- 后更名: Structured Query Language (
- ANSI 和 ISO 标准SQL:
- SQL-86, SQL-89, SQL-92
- SQL:1999, SQL:2003, SQL:2008,SQL:2011,SQL:2016
- 一般商业数据库
- 支持SQL-92多数特性+部分高版标准特性+部分非标扩展特性
- 不是所有的例子都能运行在某个特定的系统上
DDL– Data Definition language.integrity(完整性) – DDL 包含用于定义完整性约束的功能.View definition(视图定义) – DDL能够定义视图.Authorization(授权) – 能够定义视图和关系的访问权限
DML– 查询、插入、删除、修改Transaction control(事务控制) – 控制事务的开始和结束.Embedded SQL(嵌入SQL) 和Dynamic SQL(动态SQL) - 定义如何将 SQL 语句嵌入到通用编程语言中
SQL的语言特性§3.1.0
- 综合统一
- 非关系模型数据语言
- 以下语言分别定义
- 模式DDL(Schema Data Definition Language)
- 外模式DDL(Subschema Data Definition Language)
- DSDL(Data Storage Description Language)
- DML(Data Manipulation Language)
- 如需修改模式,必须停止当前DB运行、备份、修改、编译、重装数据
- 以下语言分别定义
- SQL语言
- 集DDL、DML、DCL于一体
- 有能力运行中修改模式
- 数据结构的单一带来数据操作符的简化
- 非关系模型数据语言
- 高度非过程化
- 不再关心存取路径
- 面向集合的操作方式
- 不再说明具体处理过程(如存取路径、如何循环处理)
- 一种语法两种用途
- 自含式语言
- 嵌入式语言
- 语言简洁、易学易用
- 查询:
SELECT - 定义:
CREATE,DROP,ALTER - 操纵:
INSERT,UPDATE,DELETE - 控制:
GRANT,REVOKE
- 查询:
SQL的语法特性§3.1.0
- 大小写不敏感 关键词、表名(关系名)、字段名(属性名)、内建/自定义函数或过程名
- 以
;作为语句分隔符注意:"分隔符"不是"结束符"
SQL数据定义§3.2
SQL数据定义语言data-definition language(DDL)可定义关系的如下特性:
- 每个
关系(relation)的模式(schema) - 每个属性的
值域(domain) 完整性约束/Integrity constraints- 以及后面会讲到的:
- 关系的
索引定义(indices,index) - 每个关系的
安全与权限设定(Security and Authorization) - 关系的
物理存储结构(physical storage structure)
- 关系的
SQL中的基本(数据)类型§3.2.1
char(n)定长串,不足充空varchar(n)变长串,不足截断int整数(精度长度和具体机器相关,4字节居多)smallint小整数(机器相关,2字节居多)numeric(p,d)定点数,用户指定精度为p位,小数点右侧为d位real,double浮点数和双精度浮点数(精度长度和具体机器相关)float(n)浮点数,用户指定的精度至少为n位- Chapter 4 会涉及更多类型
基本模式(表)定义 - Create Table§3.2.2
create table语法CREATE TABLE 表名 ( 字段名 数据类型列级约束条件 ,字段名 数据类型列级约束条件 ,表级约束条件) - 例
CREATE TABLE Cou( --课程表Cno int primary key, /*课程号*/Cname varchar(16) not null, --课程名Cpno int, --先导课程号Ccredit int not null, --学分foreign key (Cpno) references Cou(cno) --外码约束条件)
完整性约束条件§3.2.2
- 列级约束条件::= null|not null|unique|primay key|references 表名(字段名)
- 表级约束条件::=
unqiue(字段名,字段名)
|primary key(字段名,字段名) |foreign key(字段名,字段名) references 表名(字段名,字段名) - 例
Create Table Tea( --教师表tno int primary key, --工号tname varchar(16) not null, --姓名phone varchar(13) unique --联系电话);CREATE TABLE TC( --教师可讲学科表tno int references Tea, --教师工号cno int references Cou, --课程号primary key(tno,cno));create table CouHis( --开课记录表at_year int, --开课学年cno int references Cou, --课程号serialNo int, --课序号tno int not null references Tea, --主讲老师工号weekDay int not null, --星期几secNo int not null, --第几大节unique(at_year,cno,weekDay,secNo,tno),primary key(at_year,cno,serialNo),foreign key(tno,cno) references TC)
💡大多数数据库的 primary key 隐含 not null 约束😈SQLite是例外,它要求 not null 必须显式标出修改表定义(模式)§3.2.2
- 语法:ALTER TABLE 表名 修改指令,修改指令
修改指令::= ADD COLUMN 字段名 数据类型列级约束条件 |DROP COLUMN 字段名 |ALTER COLUMN 字段名 新字段名 数据类型列级约束条件 |DROP CONSTRAINT 约束名称 |ADD CONSTRAINT 约束名称 表级约束条件
- 例
ALTER TABLE Tea add gender char(2) not null;--上方SQL如表中已有数据,会执行失败ALTER TABLE Tea add gender char(2) not null default '男';--上方SQL成功🚨SQL中的字符串常量应使用单引号 ' 而不是双引号 "🚨许多数据库不支持删除已有字段,不支持操作约束🚨各版本数据库 ALTER TABLE 语法实现不够规范,注意查看数据库手册
SQL查询基本语法§3.3
select from语法SELECT ALL|DISTINCT 目标列,目标列 FROM 表名|视图名|子查询,表名|视图名|子查询 WHERE 条件表达式 GROUP BY 字段名,字段名HAVING 条件表达式 ORDER BY 字段名ASC|DESC,字段名ASC|DESC
- 含义
- 根据
WHERE子句的条件表达式,从FROM子句指定的基本表或视图中找出满足条件的元组 - 按
SELECT子句中的目标列(表达式),选出元组中的属性值形成结果表 - 如有
GROUP BY子句,则结果按<字段名>的值进行分组(该分量相等的元组为一个组),每组产生结果表中的一条记录(一般会在每组中作用集函数) - 如果GROUP子句带
HAVING短语,则只有满足指定条件的组才予输出 - 如有
ORDER BY子句,则结果表要按<字段名>分量值的升序或降序排序
- 根据
- 要求掌握2~3层的嵌套查询
select子句§3.3.1,§3.4.1
select子句列出查询结果希望获得的属性,对应关系代数中的投影(π)
--指定目标字段select Sname,Sage from Stu;--获取全部字段select * from Stu;--计算表达式select Sname,2025-Sage,'乖学生' from Stu;--更名(别名)select Sname as 姓名, 2025-Sage as 出生年, '乖学生' as 属性from Stu;--更名(别名)select Sname as 姓名, strftime('%Y','now')-Sage as 出生年from Stu;- ALL|DISTINCT
SQL允许查询结果中有重复行select dept from Stu; --返回所有行,包括重复行select ALL dept from Stu; --同上,ALL是默认值select DISTINCT dept from Stu; --去重select DISTINCT dept,Sname from Stu; --DISTINCT的作用范围
字符串目标列补充§3.3.1.0
-- 字符串连接select sname || '-' || ssex || sage from Stu; --使用连接符select concat(sname,'-',ssex,sage) from Stu; --使用内建函数-- 大小写转换,获取字符串长度,抽取子字符串等内建函数select sname,lower(dept),upper(dept) from Stu; --大小写转换select cname,length(cname) from Cou; --获取字符串长度select cname,substr(cname,2,3) from Cou; --抽取子字符串🚨内建函数并无统一标准,不同数据库需注意查手册where子句§3.3 §3.4
where子句查询满足条件的元组,对应关系代数中的选择(σ)
比较运算§3.3.1
select * from Stu where sage<20;select * from Stu where sage<20 AND ssex='女';select * from Stu where NOT sage<20 AND ssex='女';select * from Stu where NOT(sage<20 AND ssex='女');🚨比较运算符: >,<,>=,<=,!>,!< 要求<目标列>的值是能够比较大小的(值是有序的)范围运算§3.4.5
select * from SC where grade BETWEEN 80 AND 90;select * from SC where grade>=80 AND grade<=90; --等价🚨范围判断运算符要求<目标列>的值是有序的🚨范围区间是闭区间集合成员§3.8.1
select * from Stu where dept IN('CS','IS');字符串比较§3.4.2
=<><=>=<>都可以用来做字符串比较select * from Cou where cname<='数据库';- 字符串的有序性问题
- 字符串的大小比较实质上是字符
编码值的比较,字符集编码方案不止一个,所以……🙈 - 数据库能够支持的编码方案也不止一种,所以……😰
- 字符串的大小比较实质上是字符
🚨字符串的比较默认是`大小写敏感`的💡很多数据库在字符串常量中使用连续的两个单引号表示一个单引号字符串匹配§3.4.2
%:匹配0到多个任意字符;_:匹配1个任意字符
select * from Stu where sname LIKE '李%';/* 示例改名update Stu set sname='李刘晨' where sno='95002';update Stu set sname='张王敏' where sno='95003'; -- */insert into Stu values('96001','李%','男',17,'CS');select * from Stu where sname LIKE '李\%' ESCAPE '\';--select * from Stu where sname='李%';🚨字符串匹配运算符要求<目标列>的值是字符串🚨字符串的匹配默认是`大小写敏感`的空值判断§3.6
select * from Cou where cpno IS NULL;有的系统允许使用=和<>进行NULL比较完成空值判断,但不推荐from子句与多关系查询§3.3.1~§3.3.2
from子句指明查询涉及到的表(关系),概念上对应关系代数中的笛卡尔积(×)
- 只涉及到一张表时,就是单关系查询
- 涉及到的表(关系)不止一个即多关系查询
select Sname,Cname from Stu,Cou;笛卡尔积直接使用一般没有意义,通常和`where`配合使用构成连接from子句中表的别名
语法: from 原表名as别名
select S.sno,sname,cname,gradefrom Stu AS S,SC,Cou AS Cwhere S.sno=SC.sno and C.cno=SC.cno;💡有些数据库(比如Oracle)只接受省略关键词`AS`的别名语法多关系查询中的命名冲突
/* 反派黑料 */select sno,sname,cname,gradefrom Stu,SC,Couwhere sno=sno and cno=cno;/* 这才是正面角色 */select SC.sno,sname,cname,gradefrom Stu,SC,Couwhere SC.sno=Stu.sno and SC.cno=Cou.cno;/* '*'之领域和别名的妙用 */select Cou.*,CP.cname as 先导课from Cou,Cou as CPwhere Cou.cpno=CP.cno;💡实际项目中增加和修改字段时,应避免非必要的重复名称简单SQL查询与关系代数的联系§3.3.2
SELECT A1, A2, ..., AnFROM T1, T2, ..., TmWHERE F;- 简单SQL查询的逻辑
- 通过
from子句列出的表(关系)得到笛卡尔积 - 使用
where子句给出的条件筛选步骤1的结果 - 对步骤2得到结果中的每一条元组,根据
select子句指明的属性或计算表达式输出
- 通过
order by子句 - 结果排序§3.4.4
order by子句使输出关系按<字段名>分量值的升序或降序排序
ASC- 升序;DESC- 降序
select * from Stu ORDER BY sage; --升序(从小到大)select * from Stu ORDER BY sage ASC; --同上,ASC是默认值select * from Stu ORDER BY sage ASC,ssex DESC; --多属性组合排序聚集函数/Aggregate Functions§3.7.1
目标列中一种特殊的计算表达式
select MAX(sage),MIN(sage),AVG(sage) from Stu;/* COUNT那些事 */select COUNT(*),COUNT(cno) from Cou; --COUNT(*) vs. COUNT(key)select COUNT(*),COUNT(cpno) from Cou; --遇到null/* distinct那些事 */select SUM(sage),SUM(distinct sage) from Stu;/* AVG=SUM/COUNT ? */select AVG(sage),SUM(sage),COUNT(sage), SUM(sage)/COUNT(sage) as avg from Stu;select AVG(sage),SUM(sage),COUNT(sage), cast(SUM(sage) as float)/COUNT(sage) as avg from Stu;group by子句 - 分组§3.7.2
- 在group by指定字段上取值都相同的元组分到同一组
- 每一组在结果集中产生一条元组(行)
- 一般会在
select子句中使用聚集函数配合group by
/* 列出每门课的课程号、最高分、最低分、平均分 */select cno,max(grade),min(grade),avg(grade)from SC GROUP BY cno;
/* 🚫下面是一个错误的SQL,请大家批判地看它 */select cno,cname,max(grade),min(grade),avg(grade)from SC,Cou GROUP BY cno;/* 下面这个例子才是光明正确滴 */select SC.cno,cname,max(grade),min(grade),avg(grade)from SC,Cou where SC.cno=Stu.cnoGROUP BY SC.cno,cname;🚨select子句中的字段只能使用出现在group by后的字段🚨作为聚集函数的参数没有上述限制分组的HAVING子句§3.7.3
select sno,avg(grade) from SCgroup by sno HAVING avg(grade)>80;
select sno,avg(grade) as avg from SCgroup by sno HAVING avg>80 and sno='95001';- 按
group by指定的属性分组 - 然后依据
having剔除不符合条件的分组
HAVING vs. WHERE§3.7.3
select sno,avg(grade) from SC where cno<>2group by sno HAVING avg(grade)>80;- 首先通过
where筛选符合条件的元组 - 然后
group by指定的属性分组 - 接着依据
having剔除不符合条件的分组 - 最后每组分别计算聚集后产生一条元组
当NULL遇到……§3.6,§3.7.4
当NULL遇到计算表达式§3.6
select 5+NULL, 'string' || NULL, concat('A',NULL,'B');select DISTINCT cpno from Cou;- 规则
💡包含NULL的计算表达的结果是NULL💡内建函数试图忽略NULL💡DISTINCT判断时,NULL=NULL 处理为 true
当NULL遇到逻辑运算§3.6
- 包含
null的逻辑表达式的结果是unknown- 如: ; ;
unknown参与逻辑运算有以下规则where/having子句的逻辑表达式如结果为unknown,视为false
当NULL遇到聚集函数§3.7.4
select avg(cpno),sum(cpno),count(*),count(cpno) from Cou;- 规则
💡所有聚集函数都忽略输入集中的空值,COUNT(*)除外💡如输入集为空(或忽略空值后导致空集),COUNT返回0,其他返回null
集合运算§3.5
UNIONUNION会自动去掉重复元组(去重);可用select * from Stu where dept='IS'UNIONselect * from Stu where Sage<19;-- 等价于:select DISTINCT * from Stu where dept='IS' OR Sage<19;UNION ALL表示不去重。select sno from SC where cno=1UNIONselect sno from SC where cno=2INTERSECTINTERSECT自动去重;可用select * from Stu where dept='IS'INTERSECTselect * from Stu where Sage<=19;-- 等价于:select DISTINCT * from Stu where dept='IS' AND Sage<=19;INTERSECT ALL表示不去重。select cpno from Cou INTERSECT select cpno from Cou;-- 对比:select cpno from Cou;EXCEPTEXCEPT自动去重;可用select cno from Cou EXCEPT select cpno from Cou;select cpno from Cou EXCEPT select 1 from Cou;EXCEPT ALL表示不去重。- 关于消重(eliminates duplicates)
- 默认情况下,SQL中的集合运算都会自动消重
- 用
union all,intersect all,except all表示不消重;
😰但很多数据库不支持intersect all,except all语法
嵌套子查询/Nested Subqueries§3.8
在SQL中,一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套在另一个查询块中的查询称为嵌套查询
◆ 父查询(外层查询)
◆ 子查询(内层查询)/Subquery
select sname from Stuwhere sno in(select sno from SC where cno=2); 嵌套查询使得可以用一系列简单查询构成复杂的查询,从而明显地增强了SQL的查询能力。
以层层嵌套的方式来构造程序正是 SQL(Structured Query Language)中“结构化”的含义所在
集合成员谓词IN带子查询§3.8.1
IN带子查询是指父查询与子查询之间用IN/NOT IN进行连接,判断某个属性列值是否在子查询的结果中。
🔎 查询与“刘晨”在同一个系的学生的学号、姓名、所在系
-- 自身连接求解:SELECT S1.Sno,S1.Sname,S1.dept FROM Stu S1,Stu S2WHERE S1.dept=S2.dept AND S2.sname='刘晨';-- 上方语句步骤分解:SELECT dept FROM Stu WHERE Sname='刘晨';--步骤1SELECT Sno,Sname,dept FROM Stu WHERE dept IN('CS');--步骤2-- 子查询求解:SELECT Sno,Sname,dept FROM Stu WHERE dept IN( SELECT dept FROM Stu WHERE Sname='刘晨')🔎 查询选修了课程名为“数据库”的学生的学号和姓名
-- 连接求解:SELECT Stu.Sno,Sname FROM Stu,SC,CouWHERE Stu.Sno=SC.Sno AND SC.Cno=Cou.Cno AND Cname='数据库';-- 子查询求解:SELECT Sno,Sname FROM Stu WHERE Sno IN( SELECT Sno FROM SC WHERE Cno IN( SELECT Cno FROM Cou WHERE Cname='数据库' ));🔎 查询没有选修课程名为“数据库”的学生的学号和姓名
SELECT Sno,Sname FROM Stu WHERE Sno NOT IN( SELECT Sno FROM SC WHERE Cno IN( SELECT Cno FROM Cou WHERE Cname='数据库' ));如果不使用子查询
SELECT Stu.Sno,Sname FROM Stu EXCEPTSELECT Stu.Sno,Sname FROM Stu,SC,CouWHERE Stu.Sno=SC.Sno AND SC.Cno=Cou.Cno AND Cname='数据库';比较运算带子查询§3.8.2
父查询与子查询之间用比较运算符(> < = <= >= <>)进行连接
需要注意的是,子查询一定要跟在比较符之后而不是之前🔎 找出超过平均年龄的学生的学号和姓名
SELECT Sno,Sname FROM Stu WHERE Sage>( SELECT AVG(Sage) FROM Stu);单值(标量/Scalar)比较§3.8.2,§3.8.7
语法: 比较运算符(子查询)
标量查询/Scalarquery 查询结果有且只有一个元组,且元组有且只有一个分量(属性)的查询,如:select AVG(Sage) from Stu; --要求至少有一个学生select cname from Cou where cno=1; --要求必须有1号课程select cno from Cou where cname='数据库'; --这个不一定是标量- 计算表达式中的标量查询
(SELECT count(*) FROM SC) / (SELECT count(*) FROM Stu);
- 比较运算直接带子查询要确保子查询是标量查询
SELECT Sno,Sname FROM Stu WHERE Sage>(SELECT AVG(Sage) FROM Stu --这个必需是标量查询);
集合比较/Set Comparison§3.8.2
语法: 比较运算符 all|some|any(子查询)
all: 子查询结果中所有的值都必须满足条件some等同any: 子查询结果中有一个满足条件即可
🔎 找出年龄比’IS’系的至少一个学生大的学生姓名
select sname from Stu where sage>SOME( select sage from Stu where dept='IS');🔎 找出年龄比’IS’系的所有学生大的学生姓名
select sname from Stu where sage>ALL( select sage from Stu where dept='IS');- 等效语义
=some(...)等同于in(...)<>some(...)基本无意义<>all(...)等同于not in(...)>some(...)等同于>(select min(...) ...)<some(...)等同于<(select max(...) ...)>all(...)等同于>(select max(...) ...)<all(...)等同于<(select min(...) ...)
嵌套查询的求解§3.8.0
嵌套查询的一般求解§3.8.0
DBS对嵌套查询的求解方法一般是由里向外处理。即每个子查询在其上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件
SELECT Sname FROM Stu WHERE Sno IN( SELECT Sno FROM SC WHERE Cno=2;);--首先求解子查询:SELECT Sno FROM SC WHERE Cno=2; --得到{('95001'),('95002')}--代入上级查询求解:SELECT Sname FROM Stu WHERE Sno IN('95001','95002');相关变量/Correlation Variables§3.8.3
考虑这个查询:🔎找出每个学生超过自己选修课程平均成绩的课程号
SELECT Sno,Cno FROM SC X WHERE Grade>=( SELECT AVG(Grade) FROM SC Y WHERE Y.Sno=X.Sno);子查询的查询条件依赖于外层查询的属性(在本例中是X.Sno)
这种子查询称为 相关子查询/Correlated Subquery
这种属性被称为 相关变量/Correlation Variables
相关子查询的求解§3.8.3
求解相关子查询不能象求解不相关子查询那样,一次将子查询求解出来,然后求解父查询。相关子查询的内层查询由于与外层查询有关,因此必须反复求值
- 从概念上讲,相关子查询的一般处理过程是
- 首先取外层查询中S表的第一个元组
- 根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表
- 然后再检查S表的下一个元组
- 重复这一过程,直至S表全部检查完毕
空关系(Empty Relation)测试:EXISTS§3.8.3
语法: NOTEXISTS(子查询)
- 判断子查询结果是否空集,代表存在量词
∃🔎列出所有选修了1号课程的学生姓名-- 连接求解:SELECT Sname FROM Stu,SC WHERE SC.Sno=Stu.Sno AND Cno=1;-- EXISTS子查询求解:SELECT Sname FROM Stu WHERE EXISTS(SELECT * FROM SC WHERE SC.Sno=Stu.Sno AND Cno=1);
- 等价替换
一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换,但所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换
全称量词的表达§3.8.3.0
选修了全部课程的学生姓名 ≡ 不存在一门课程是没选的
select Sname from Stu where NOT EXISTS( select * from Cou where NOT EXISTS( select * from SC where Sno=Stu.Sno and Cno=Cou.Cno ));蕴含的表达§3.8.3.0
🔎查询至少选修了学生’95002’选修的全部课程的学号
不存在课程被学生95002选了()而学生没有选()
select Sno from Stu X where NOT EXISTS( select * from Cou Y where Cno in( select Cno from SC where Sno='95002' --95002选了Y ) and NOT EXISTS( select * from SC where Sno=X.Sno and Cno=Y.Cno ));select distinct Sno from SC X where NOT EXISTS( select * from SC Y where Y.Sno='95002' and NOT EXISTS( select * from SC Z where Z.Sno=X.Sno and Z.Cno=Y.Cno ));重复元组(Duplicate Tuples)存在测试§3.8.4
语法: NOTUNIQUE(子查询)
- 判断子查询结果是否有重复元组
🔎列出最多只被一门课作为先导课的课程号select Cno from Cou C where UNIQUE(select Cpno from Cou where Cpno=C.Cno) - 很多RDBS不支持
UNIQUE(子查询),可用替代方案select Cno from Cou C where 1>=(select COUNT(*) from Cou where Cpno=C.Cno)
FROM子句中的子查询§3.8.5
select avg_grade,Cname from Cou,( select Cno,avg(grade) as avg_grade from SC group by Cno) AS SC_AVGwhere SC_AVG.Cno=Cou.Cno and avg_grade>85WITH子句§3.8.6
WITH...AS...子句提供一种定义临时关系的方式,作用域仅在同一查询中
WITH SC_AVG(Cno,avg_grade) AS( select Cno,avg(grade) as avg_grade from SC group by Cno)select avg_grade,Cname from Cou,SC_AVGwhere SC_AVG.Cno=Cou.Cno and avg_grade>85;SQL数据修改§3.9
DELETE - 删除元组§3.9.1
DELETE FROM Cou; --尝试删除所有课程DELETE FROM SC WHERE grade<60;DELETE FROM SC WHERE grade<(select avg(grade) from SC);-- 疑问:删除会导致平均成绩变化!-- 实际上会先计算“子查询” 然后再带入求解🚨注意:FROM后只能有一个关系表!!!INSERT INTO - 添加元组§3.9.2
--不指定字段名,values中的值数量和域需匹配create table的字段定义:INSERT INTO Stu VALUES('95020','陈冬','男',18,'CS');--指定属性列values中值的数量和顺序需和属性列匹配:INSERT INTO Stu(Sname,Sno,Ssex) VALUES('辛夏','95021','女');--指定为空值:INSERT INTO Stu VALUES('95020','梁秋','男',NULL,NULL);🚨注意:INSERT INTO后只能有一个关系表!!!- 缺省值和默认值
-- /*假定有表create table T(id int primary key,x int not null DEFAULT 0,y int not null,z int); -- */insert into T(y,id) values(2,1); -- (id,x,y,z)=(1,0,2,null)insert into T(id) values(2);-- y报错💡未指定某字段值时,首先尝试字段的DEFAULT设定,其次尝试NULL
- 插入子查询,子查询先完成,然后再插入
insert into R(A,B,C) select S.*,0 from S;🚨子查询的结果的模式必需和指定的目标模式匹配!!!
UPDATE - 修改元素分量§3.9.3
🚨注意:UPDATE后只允许存在一个关系表!!!
💡值可以是常量、计算表达式,也可以是标量查询
UPDATE SC SET grade=grade+10; --分数可能超100--两条语句分段改分,不同顺序会导致不同结果:UPDATE SC SET grade=grade*1.05 WHERE grade>80;UPDATE SC SET grade=grade*1.25 WHERE grade<=80;--使用标量子查询赋值:update Stu set Sage=(SELECT avg(sage) FROM Stu)+1;条件修改/Case Statement for Conditional Updates* §3.9.3
update SC set grade=CASE WHEN grade<=90 THEN grade*1.05 WHEN grade<=80 THEN grade*1.25 ELSE grade*1.01END;支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!