1、SQL ——Structured Query Language 结构化查询语言,是通用的、集数据查询(Data Query)、数据操纵(Data Manipulation)、
数据定义(Data Definition)和数据控制(Data Control)于一体的功能性极强的关系数据库语言。
2、关系数据库的三级模式结构:
外模式——视图(View)和部分基本表(Base Table);
模式——基本表;
内模式——存储文件(Stored File)。
3、基本表、视图、存储文件
基本表是本身独立存在的表,在SQL中一个关系对应一个基本表。一个或多个基本表对应一个存储文件,一个表可以带若干个索引,
索引也存放在存储文件中。
存储文件的逻辑结构组成了关系数据库的内模式。存储文件的物理结构是任意的,对用户是透明的。
视图是从一个或几个基本表导出的表,它本身不独立存储在数据库中。数据库中只存放视图的定义而不存放视图对应的数据。
这些数据仍存放在导出视图的基本表中,视图只是一个虚表。视图在概念上与基本表等同,用户可以在视图上再定义视图。
4、定义模式
语句:Create Schema <模式名> Authrization <用户名> 。 用户名> 模式名>
解析:如果没有定义<模式名>,<模式名>则隐含为<用户名>。用户调用该命令时须具有DBA权限,或获得了DBA授予的Create Schema的权限。
定义模式实际上是定义了一个命名空间。
例子:Create Schema "Student" Authorization LittleBai; --为用户 LittleBai 定义了模式 Student。 Create Schema "Student" Authorization LittleBai; --没有指定 <模式名> , <模式名> 隐含为用户名 LittleBai。 模式名> 模式名>
在Create Schema 中可以接受 Create Table,Create View 和 Grant子句。
语句:Create Schema <模式名> Authorization <用户名> [ <表定义子句> | <视图定义子句> | <授权定义子句> ] 例子:Create Schema Test Authorization LittleBai Create Table Student (Sno Char(9), SName char(20), SAge int, SDep Char(20), SNum int); --为用户LittleBai用户创建模式Test,并定义了一个Student表。 授权定义子句> 视图定义子句> 表定义子句> 用户名> 模式名>
5、删除模式
语句:Drop Schema <模式名>模式名>
例子:Drop Schema LittleBai; --模式下不能有表;有表会涉及级联删除,要写存储过程
6、定义基本表
创建了一个模式,就建立了一个数据库的命名空间,一个框架。在该空间中首先要定义的是:数据库基本表。
语句: Create Table <表名> ( <列名> <数据类型> [ 列级完整性约束条件 ] [ , <列名> <数据类型> [ 列级完整性约束条件 ] ] … [ , [ 表级完整性约束条件 ] ]); 数据类型> 列名> 数据类型> 列名> 表名>
解析:建表时还可同时定义与该表有关的完整性约束条件,这些约束条件将被存入到系统的数据字典中。
如果约束条件涉及到该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级。
例子:Create Table Student (SNo Char(9) Primary Key, --列级完整性约束条件,SID是主键(主码) SName Char(20) Unique, --SName取唯一值 SSex Char(2), SAge Smallint, SDep Char(20) ); --创建Student表并将相关约束条件存放在字典里。 Create Table Course (CNo Char(4) Primary Key, --列级完整性约束条件,CID 是主键(主码) CName Cher(40), CPno char(4), --先修课 CCredit Smallint, Foreign Key CPno References Course(CNo) ); --表级完整性约束条件,CPno是外键(外码),被参照表是Course,被按照列是CNo。参照表和被参照表可以是同一个表。 Create Table StuCou (SNo Char(9), CNo Char(4), Grade Smallint, Primary Key (SNo,CNo), --主键(主码)由两个属性构成,必须作为表级完整性进行定义 Foreign Key (SNo) References Student(SNo), --表级完整性约束条件,SNo是外键(外码),被参照表是Student Foreign Key(CNo) References Course(CNo) ); --表级完整性约束条件,CNo是外键(外码),被参照表是Course
7、数据类型
关系模式中很重要的一个概念是域。每个属性来自一个域,它的取值必须是域中的值。
在SQL中域的概念用数据类型来实现。定义表的各个属性时需要指明其数据类型及长度。
一个属性一般要通过两点来确定数据类型:取值范围和要做那些运算。比如年龄 用Char(3) 类型足够了,但是它又涉及到运算,所以要采用整数类型。
数据类型 | 含义 |
char(n) | 长度为n的定长字符串,固定长度的字符串。最多 8,000 个字符。 |
varchar(n) | 最大长度为n的变长字符串,可变长度的字符串。最多 8,000 个字符。 |
varchar(max) | 可变长度的字符串。最多 1,073,741,824 个字符。 |
text | 可变长度的字符串。最多 2GB 字符数据。 |
nchar(n) | 固定长度的 Unicode 数据。最多 4,000 个字符。 |
nvarchar(n) | 可变长度的 Unicode 数据。最多 4,000 个字符。 |
nvarchar(max) | 可变长度的 Unicode 数据。最多 536,870,912 个字符。 |
ntext | 可变长度的 Unicode 数据。最多 2GB 字符数据。 |
bit | 允许 0、1 或 NULL。 |
varbinary(n) | 可变长度的二进制数据。最多 8,000 字节。 |
binary(n) | 固定长度的二进制数据。最多 8,000 字节。 |
varbinary(max) | 可变长度的二进制数据。最多 2GB 字节。 |
image | 可变长度的二进制数据。最多 2GB。 |
tinyint | 允许从 0 到 255 的所有数字。 |
smallint | 短整数,允许从 -32,768 到 32,767 的所有数字。 |
int | 长整数(也可以写作Integer),允许从 -2,147,483,648 到 2,147,483,647 的所有数字。 |
bigint | 允许介于 -9,223,372,036,854,775,808 和 9,223,372,036,854,775,807 之间的所有数字。 |
decimal(p,s) | 固定精度和比例的数字。允许从 -10^38 +1 到 10^38 -1 之间的数字。 p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。 s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。 |
numeric(p,s) | 固定精度和比例的数字。允许从 -10^38 +1 到 10^38 -1 之间的数字。 p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。 s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。 |
smallmoney | 介于 -214,748.3648 和 214,748.3647 之间的货币数据。 |
money | 介于 -922,337,203,685,477.5808 和 922,337,203,685,477.5807 之间的货币数据。 |
float(n) | 从 -1.79E + 308 到 1.79E + 308 的浮动精度数字数据。 参数 n 指示该字段保存 4 字节还是 8 字节。 float(24) 保存 4 字节,而 float(53) 保存 8 字节。n 的默认值是 53。 |
real | 取决于机器精度的双精度浮点数,从 -3.40E + 38 到 3.40E + 38 的浮动精度数字数据。 |
datetime | 从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 3.33 毫秒。 |
datetime2 | 从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 100 纳秒。 |
smalldatetime | 从 1900 年 1 月 1 日 到 2079 年 6 月 6 日,精度为 1 分钟。 |
date | 仅存储日期。从 0001 年 1 月 1 日 到 9999 年 12 月 31 日。 |
time | 时间,包括一日的时、分、秒,格式为:HH:MM:SS,仅存储时间。精度为 100 纳秒。 |
datetimeoffset | 与 datetime2 相同,外加时区偏移。 |
timestamp | 存储唯一的数字,每当创建或修改某行时,该数字会更新。timestamp 基于内部时钟,不对应真实时间。 每个表只能有一个 timestamp 变量。 |
sql_variant | 存储最多 8,000 字节不同数据类型的数据,除了 text、ntext 以及 timestamp。 |
uniqueidentifier | 存储全局标识符 (GUID)。 |
xml | 存储 XML 格式化数据。最多 2GB。 |
cursor | 存储对用于数据库操作的指针的引用。 |
table | 存储结果集,供稍后处理。 |
8、模式与表
每一个基本表都属于某一个模式,一个模式包含多个基本表。
定义基本表所属模式的三种方法:
a:在表名中明显给出模式名;例子:Create Table "Test".Student(......); --Student 所属的模式是 Test。
b:在创建模式时同时创建表;
c:设置所属的模式。
9、修改基本表
SQL用Alter Table语句修改基本表。
语句:Alter Table <表名> -- <表名> 要修改的基本表 [ Add <新列名> <数据类型> [完整性约束] ] --Add子句用于增加新列和新的完整性约束条件 [ Drop <完整性约束名> ] --Drop 子句用于删除指定的完整性约束条件 [ Alter Column <列名> <数据类型> ] --Alter Column 子句用于修改原有的定义,包括修改列名和数据类型 数据类型> 列名> 完整性约束名> 数据类型> 新列名> 表名> 表名>
例子:Alter Table Student Add S_entrance Date; --新增入学时间列 Alter Table Student Alter Column Sage Int; --将年龄的数据类型由(假设是)字符串型改为整数 Alter Table Course Add Unique(Cname); --增加课程名称必须取唯一值的约束条件
10、删除基本表
SQL用Drop Table语句修改基本表。
语句:Drop Table <表名> ; 表名>
例子:Drop Table Student; --如涉及级联,需写存储过程
11、建立索引
建立索引是加快查询速度的有效手段。
语句:Create [ Unique ] [ Cluster ] Index <索引名> On <表名> ( <列名> [ <次序> ] [, <列名> [ <次序> ] ]...); 次序> 列名> 次序> 列名> 表名> 索引名>
解析:<表名>是要建索引的基本表的名称。索引可以建在该表的一列或多列上,各列名之间要用逗号分隔。每个<列名>后面还可以用
<次序>指定索引值的排列次序,可选Asc(升序)或Desc(降序),缺省值为Asc。
Unique 表明此索引的每一个索引值只对应唯一的数据记录。
Cluster表示建立的索引是聚簇索引。聚簇索引是指索引项的顺序与表中记录的物理顺序一致的索引组织。
例子:Create Cluster Index StuName On Student(SName); --将Student表的SName列上建立一个聚簇索引,而且Student表中的记录将按照SName值的升序存放。 Create Unique Index StuSno On Student(Sno); --按Sno 列升序建唯一索引。 Create Unique Index CouCno on Course(Cno); --按Cno 列升序建唯一索引。 Create Unique Index SCno On SC(Sno Asc,Cno Desc); --按Sno 升序和Cno 降序建唯一索引。
用户可以在最经常查询的列上建立聚簇索引以提高查询效率。
在一个基本表上最多只能建立一个聚簇索引。建立聚簇索引后,更新该索引列上的数据时,
往往导致表中记录的物理顺序的变更,代价要大,因此对于经常更行的列不宜建立聚簇索引。
12、删除索引
建立索引是为了减少查询操作的时间,但如果数据增删改频繁,系统会花费更多时间来维护索引,从而降低了查询效率。
这时,可以删除一些不必要的索引。
语句:Drop Index <索引名> ; --删除索引时,系统会同时从数据字典中删去有关该索引的描述。 例子:Drop Index StuName; 索引名>
14、数据查询
Select 语句可以完成简单的单表查询,也可以完成复杂的连接查询和嵌套查询。
语句:Select [ All | Distinct ] < 目标列表达式 > [ , <目标列表达式> ] … From < 表名或视图名 > [ , < 表名或视图名 > ] … [ Where <条件表达式> ] [ Group By <列名1> [ Having <条件表达式> ] ] [ Order By < 列名2 > [ Asc | Desc ] ]; 条件表达式> 列名1> 条件表达式> 目标列表达式>
解析:根据Where子句条件表达式从From子句指定的基本表或视图中找出满足条件的记录,返回结果表。
Group By子句:将结果按<列名1>的值进行分组,该属性列值相等的数据为一个组。通常会在每组中作聚合函数。
如果Group By 子句带Having短句,则只有满足指定条件的组才会予以输出。
Order By子句:结果表要按<列名2>的值升序或降序排列。
15、查询指定的列
通过在Select子句的<目标列表达式>中指定要查询的属性列。
例子:Select Sno,SName From Student; --查询所有学生的学号与姓名。 Select SName,Sno,SDep From Student; --查询所有学生的姓名、学号、所在系。 显示列的先后顺序可以与表中的不一致。可以根据需要变化顺序。
16、查询全部列
两种方法:一是在Select关键字后列出所有列名,可改变显示列的先后顺序。
二是将 <目标列表达式> 指定为 * ,不可改变显示列的先后顺序。
例子:Select * from Student; --查询所有学生的详细记录。 --等同于 Select Sno,SName,SSex,,SAge,SDep From Student;
17、查询经过计算的值
<目标列表达式> 不仅可以是表中的列,也可以是表达式。
例子:Select SName,2018 - SAge From Student; --查询结果的2列是一个算数表达式。当时年份减去学生的年龄得出学生的出生年份。
<目标列表达式> 还可以是字符串常量、函数等。
通过指定别名来改变结果的列标题,对于含算数表达式、常量、函数名的目标列尤为有用。
例子:Select SName, 'Year of Birth:', 2018 - SAge, Lower(SDep) From Student; --指定别名改变结果列的标题 Select SName NAME, 'Year of Birth:', BIRTH,2018 - SAge BIRTHDAY, Lower(SDep) DEPARTMENT From Student;
18、消除取值重复的行
用Distinct 关键字消除重复行。
例子:Select Distinct Sno From Student; --如果不指定Distinct 关键字,缺省值则为All,即有重复行。 Select Sno From SC; --等价于 Select All Sno From SC;
19、Where 语句
查询满足指定条件的数据可通过Where子句来实现。
Where 子句常用的查询条件表:
查询条件 | 谓词 |
比较 | = (等于), > (大于), < (小于), >=(大于等于), <=(小于等于), !=(或), <>(不等于), !>(不大于), !<(不小于); Not+上述比较运算符 |
确定范围 | Between And,Not Between And |
确定集合 | In,Not In |
字符匹配 | Like,Not Like |
空值 | Is Null,Is Not Null |
多重条件(逻辑运算) | And,Or,Not |
例子:Select SName From Student Where SDep='CS'; --RDBMS执行该查询的一种可能过程:对Student表进行全表扫描,取出一条数据,检测该数据的SDep 列的值是否等于‘CS’,如果等取出,否则跳过。
如果学生人数过万,而计算机系的人数是总学生的5%左右,那么可以在Student 表的SDep列上建立索引,
系统会利用该索引找出SDep=‘CS’的数据;这样就避免了对Student表的全表扫描,加快查询速度。但如果学生较少,
索引查找不一定能提高效率,系统仍会使用全表扫描。这由查询优化器按某些规则或估计执行代价来作出选择。
(a)、比较大小
例子:Select SName,SAge From Student Where SAge < 20; --查询20岁一下的学生姓名和年龄。 Select Distinct Sno From SC Where Grade < 60; --当某个学生有多科不及格,只显示出其一个学号。Distinct短语。
(b)、确定范围
谓词Between…And…和Not Between…And…
用来查找属性值在(或不在)指定范围内的数据,其中Between后是范围的下限(低值),And 后是范围的上限(高值)。
例子:Select SName,SDep,SAge From Student SAge Between 20 And 23; --查询年龄在20~23岁(包括20,23)之间的学生数据。 Select SName,SDep,SAge From Student SAge Not Between 20 And 23; --查询年龄不在20~23岁之间的学生数据。
(c)、确定集合
谓词 In 和 Not In
用来查找属性值属于指定集合的数据。
例子:Select SName, SSex From Student Where SDep In ( 'CS' ,'MA','IS'); --查询计算机系(CS)、数学系(MA)和信息系(IS)的学生数据。 Select SName, SSex From Student Where SDep Not In ( 'CS' ,'MA','IS'); --查询不在计算机系(CS)、数学系(MA)和信息系(IS)的学生数据。
(d)、字符匹配
谓词 Like 和 Not Like
用来进行字符串的匹配。
语法:[Not] Like ' <匹配符> ' [ Escape '换码字符'] 匹配符>
解析:查找指定的属性列值与<匹配串>相匹配的数据。<匹配串>可以是一个完整的字符串,也可以含有通配符 % 和 _ .
% (百分号)代表任意长度(长度可以为0)的字符串。例如 A%B 表示以A开头,以B结尾的文艺长度的字符串。AbcdB,AbB,AB等。
_ (下划线)代表任意单个字符。 例如 A_B 表示以A开头,以B结尾的长度为3的任意字符串。 AcB,AfB等。
例子:Select * From Student Where Sno Like '20180418'; --查询学号为20180418的学生数据 --等价于 Select * From Student Where Sno='20180418'; --如果Like 后面的匹配串不含通配符,则可以用=(等于)运算符取代Like 谓词。 Select SName,Sno,SSex From Student Where SName Like '李%'; --查询所有姓李的学生数据。 Select SName From Student Where SName Like '欧阳__'; --查询姓欧阳且全名为3个汉字的学生数据。 数据库字符集为ASCII时一个汉字需要两个_,当字符集为GBK时只需要一个_。 Select SName,Sno From Student Where SName Like '__白'; --查询名字中第2个字为“白”字的学生数据。 Select SName,Sno,SSex From Student Where SName Not Like '刘%'; --查询所有不姓刘的学生数据。
如果用户要查询的字符串本身就含有通配符 % 或 _ , 这时就要使用 Escape '<换码字符>' 短语来对通配符进行转义了。
例子:Select Cno,CCredit From Course Where CName Like 'DB\_Design' Escape '\'; --查询DB_Design 课程数据。
解析 :Escape '\' :“\”为换码字符。“\”后面的字符"_"不再具有通配符的含义,它被转义成了普通的‘_’字符。
例子:Select * From Course Where CName Like 'DB\_%i_ _' Escape '\'; --'DB\_%i_ _' 第一个 _ 前面又换码字符 ‘\’, --所以它被转义成了普通‘_’字符;而 i 后面的两个均没有转换码字符 \, 所以它们仍作为通配符。
(f)、涉及空值的查询
例子:Select Sno, Cno From SC Where Grade Is Null; --分数 Grade 是空值。 查询缺少成绩的学生的数据。 这里的 Is 不能用等号(=)代替。 Select Sno, Cno From SC Where Grade Is Not Null; --查询所有成绩的学生数据。
(g)、多重条件查询
逻辑运算符 And 和 Or 用来联结多个查询条件。 And 的优先级高于Or,但可以用括号改变优先级。
例子:Select SName From Student Where SDep = 'CS' And SAge < 20; --查询计算机科学系年龄在20岁以下的学生数据。 Select SName From Student Where SDep = 'CS' Or SDep = 'MA' OrSDep = 'IS'; --查询计算机系(CS)、数学系(MA)和信息系(IS)的学生数据。
20、Order By子句
用于查询结果按照一个或多个属性列的升序(Asc)或降序(Desc)排序,缺省值为升序。
例子:Select Sno,Grade From SC Where Cno = '3' Order By Grade By Grade Desc; --查询选修了3号课程的学生数据,并且按分数降序排序。 Select * From Student Order By SDep,SAge Desc; --查询所有学生数据,查询结果按所在系的系号升序排序,同系中的按年龄降序排序。
对于空值,排序时显示的次序由具体系统实现来决定。例如按升序排序的数据,空值最后显示;
按降序排序的数据空值则优先显示。
21、聚合函数
聚合函数 | 含义 |
Count ([ Distinct | All ] * ) | 统计数据条数 |
Count ([ Distinct | All ]<列名>) | 统计一列中值的个数 |
Sum ([ Distinct | All ]<列名>) | 计算一列值的总和(此列必须是数值型) |
Avg ([ Distinct | All ]<列名>) | 计算一列值的平均值(此列必须是数值型) |
Max ([ Distinct | All ]<列名>) | 求一列值中的最大值 |
Min ([ Distinct | All ]<列名>) | 求一列值中的最小值 |
如果指定 Distinct 短语,则表示在计算时要取消指定列中的重复值。
如果不指定DIstinct 短语或指定All 短语(All为缺省值),则表示不取消重复值。
例子:Select Count(*) From Student; --查询学生总人数。 Select Count(Distinct Sno) From SC; --查询选修了课程的学生人数。 一个学生要选修多门课程,为避免重复计算学生人数,必须在Count 函数中用Distinct 短语。 Select Avg(Grade) From SC Where Cno='1'; --查询选修1号课程的学生平均成绩。 Select Max(Grade) From SC Where Cno='1'; --查询选修1号课程的学生最高分数。 Select Sum(CCredit) From SC,Course Where Sno = '20180418' And SC.Cno = Course.Cno; --查询学生20180418选修课程的总学分数。
在聚合函数遇到空值时,除Count(*) 外,都跳过空值而只处理非空值。
注意:Where 子句中是不能用聚合函数作为条件表达式的。
22、Group By 子句
用于将查询结果按某一列或多列的值分组,值相等的为一组。分组的目的是为了细化聚合函数的作用对象。
如果未对查询结果进行分组,聚合函数将作用于整个查询结果。分组后的聚合函数将作用于每个组,即每个组都有一个函数值。
例子:Select Cno,Count(Sno) From SC Group By Cno; --求各个课程号及相应的选课人数。 该语句对查询按Cno的值分组, --所有具有相同Cno值的数据为一组,然后对每组用聚合函数(Count)计算,以求得该组的学生人数。
如果分组还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件的组,则可以使用Having 短语指定筛选条件。
例子:Select Sno From SC Group By Sno Having Count(*) > 3; --查询选修了3门以上课程的学生数据。按Sno分组,再用聚合函数统计每组的总数据,取总数据 > 3 的学生数据。
Where 子句与Having 短语的区别在于作用对象不同;
Where子句作用于基本表或视图,从中选择满足条件的数据;
Having 短语作用于组,从中选择满足条件的组。
23、连接查询
一个查询同时涉及两个及以上的表,称之为连接查询。
a、等值与非等值连接查询
连接查询的Where子句中用来连接两个表的条件称为连接条件或连接谓词。
格式:[ <表名1>. ] <列名1> <比较运算符> [ <表名2>. ] <列名2>
[ <表名1>. ] <列名1> Between [ <表名2>. ] <列名2> And [ <表名2>. ] <列名3>
比较运算符:=、>、<、>=、<=、!=(或<>)等。
当连接运算符为=时,称之为等值连接。使用其他运算符时,称之为非等值连接。
连接谓词中的列名称为连接字段;连接条件中的连接字段类型必须是可比的,但名字不必相同。
例子:Select Student.*,SC.* From Student,SC Where Student.Sno=SC.Sno; --查询每个学生及其选修课程的情况
b、自然链接
若在等值连接中把目标列中重复的属性列去掉则为自然连接。