一. SQL数据定义语言(DDL)
数据库中关系集合必须由数据库定义语言DDL来定义,包括:数据库模式、关系模式、每个属性的值域、完整性约束、每个关系的索引值、关系的物理存储结构。
SQL数据定义语言包括:
- 数据库的定义:创建、修改、删除
- 基本表的定义:创建、修改、删除
- 视图的定义:创建、删除
- 索引的定义:创建、删除
1. 数据库的定义
数据库与其对象(基本表、视图、索引、约束等)之间的关系
数据库作为一个整体存在在外存的物理文件中。
物理文件有两种:
- 数据文件:存放数据库中的对象数据
- 日志文件:存放用于恢复数据库的冗余数据
(1). 数据库的创建
当创建一个数据库,与该数据库相关的描述信息会存入到系统的数据字典(即数据库系统表)中。
--创建数据库
create database 数据库名
[
on --创建数据文件
(
)
log on --创建日志文件
(
)
]
--一般直接创建数据库,使用默认格式就可以
(2). 数据库的修改
语法:
alter database 数据库名
{
}
注:一次只能修改一项数据功能
(3). 数据库的删除
删除数据库时,系统会同时从数据库系统表中将该数据库的描述信息一起删除,有的数据库系统还自动删除与数据库相关联的物理文件
语法:
drop database 数据库名
2. 基本表的定义
(1).SQL中的基本数据类型是:
- 整型:int(4B)、smallint(2B)
- 实型:float、real(4B)
- 字符型:char(n) 表示定长字符、nchar(n)表示定长的支持汉子的字符、varchar(n) 表示可设置最大长度为n的字符、nvarchar(n)表示支持汉子并且最大长度为n的字符
- 二进制型:binary(n)、varbinary(n)
- 逻辑型:bit,只能取0和1,不允许为空
- 货币型:money(8B,4位小数)、small money(4B,2位小数)
- 时间型:datetime(4B,从1753-01-01开始)、smalldatetime(4B,从1900-01-01开始)
(2).创建基本表
1. 用SQL命令建立基本表(包括主键和外键)和约束
建表
create table dept
(
dept_id int primary key,
dept_name nvarchar(100) not null,
dept_address nvarchar(100)
)
create table emp
(
emp_id int constraint pk_emp_id_hahaha primary key,
emp_name nvarchar(20) not null,
emp_sex nchar(1),
dept_id int constraint fk_dept_id_heihei foreign key references dept(dept_id)
)
--注意主键和外键还可以这样设置
/*
emp_id int,
dept_id int,
constraint 主键名 primary key(emp_id),
constraint 外键名 foreign key(dept_id) references dept(dept_id)
*/
--当建立一个由3个属性构成的命名主码约束以及3个命名外码约束
/*
constraint 主键名 primary key(studentNo, courseNo, termNo),
constraint 外键名1 foreign key(studentNo) references Student(studentNo)
constraint 外键名2 foreign key(courseNo) references Course(courseNo)
constraint 外键名3 foreign key(termNo) references Term(termNo)
*/
建立约束
约束1:
--check约束:保证事物属性的取值在合法范围内
create table student
(
stu_id int primary key,
stu_sal int check (stu_sal>=1000 and stu_sal<=8000)
)
举例:sex字段只能取男或女
create table student
(
studentNo char(7) primary key not null,
sex char(2) null check(sex in('男','女'))
)
约束2:
--default约束:保证事物属性一定会有一个值
create table student2
(
stu_id int primary key,
stu_sex nchar(1) default '男'
--在数据库中字符串是必须用' '括起来,模拟一个对象(表、约束)的名字用" "
)
insert into student2(stu_id) values(1)
约束3:
--unique约束:保证了事物属性的取值不允许重复,但允许其中有一列为空
create table student3
(
stu_id int primary key,
stu_name nvarchar(200) unique not null --unique约束和not null约束可以组合使用
)
insert into student3 values(1, '张三')--OK
insert into student3 values(2, '李四')--OK
insert into student3 values(3, '张三')--error,违反了唯一约束
(3). 基本表的修改
语法:
--增加列(新增的一列的值为空值)
alter table 表名
add 列名 数据类型
-- 增加约束
alter table 表名
add constraint 约束名 约束(列名)
-- 删除约束
alter table 表名
drop 约束名
-- 修改列的数据类型
alter table 表名
alter column 列名 新的数据类型
(4). 基本表的删除
删除基本表时,系统会同时从数据库系统表中将该基本表的描述一起删除
语法:
drop table 表名 [restrict|cascade]
--若选择restrict,则该基本表的删除有限制条件,即该基本表不能有视图、触发器、以及被其他基本表所引用(如检查约束check、外码约束foreign key)
--若选择cascade,则该基本表的删除没有限制条件,在删除基本表的同时,也删除建立在该表上的所有索引、完整性约束、触发器、视图
注意:SQL Server不支持[restrict|cascade]选项,其删除的限制条件在创建基本表的时候就定义了
3. 视图的定义
视图是一个虚表,是从一个或几个基本表(或视图)中导出的表,在数据库系统中仅存放了创建视图的语句,不存放视图对应的数据。
当基本表中的数据发生变化时,从视图中查询出的数据也随之变化
在设计基本表结构的时候,为了减少数据的冗余存放,往往只存放基本数据,凡是可以由基本表导出的数据,都存放在视图上面
视图的主要作用
- 简化查修,避免了书写大量重复的SQL语句
- 使用户能以多种角度看待同一数据库模式
- 对重构数据库模式提供了一定程度的逻辑独立性
- 能够对数据库中的机密数据提供一定程度的安全保护
- 适当的利用视图可以更清晰的表达查询
视图的优点
- 简化查询
- 增加数据的保密性
视图的缺点
- 增加了数据库维护的成本(原表数据改变,视图表也要改变)
- 只能简化查询,不能加快查询速度
注意的问题
-
创建视图的select语句必须为所有计算列指定别名
--error create view v$_a as select avg(asl) from emp; --ok create view v$_a as select avg(asl) as "avg_sal" from emp;
-
视图不是物理表,是虚拟表
-
不建议通过视图更新视图所依附的原始数据
(1). 创建视图
数据库管理系统在执行create view语句时,只是把创建的视图的语句存入数据库系统表中并不会执行其中子查询语句
只有在对视图进行查询时,才会按创建视图的语句从基本表中将数据查询出来
语法:
create view 视图名[(列名1, 列名2, ..., 列名n)]
as
子查询语句 (其中不允许含有order by字句和distinct短语)
[with check option]
-- 注1:
省略列名时,视图列名自动取子查询语句查询出来的列名
以下三种情况必须写列名
1. 子查询中的某个目标列是聚合函数或表达式
2. 子查询中出现了多表连接中名称相同的列名
3. 视图中需要为某列去新的名称时
-- 注2:
添加with check option时,数据库管理系统会在对数据库进行更新
(插入、删除、修改)操作时进行合法性检查,
只有当满足要求的操作才被允许执行
建立视图的两种方式:
-
方式一:建立在一个或多个基本表上的视图
行列子集视图:视图是基于一个基本表创建的,且保留了主码属性
举例:
创建一个包含每门课程的课程编号、课程名称、选课人数和选课平均成绩的视图ScoreView。 --出现问题:create view 必须是批处理中的第一条语句。 --产生原因:也就是说,你可能在这段代码之前还有其他的语句是同时在处理。 --解决办法: --1、在create view语句之前加上go语句 --2、在新建的一个窗口里面写create view语句 写法一: go create view ScoreView as select Score.courseNo, courseName, count(*) 选课人数, avg(score) 平均成绩 from Score, Course where Score.courseNo=Course.courseNo group by Score.courseNo, courseName 写法二: go create view ScoreView(courseNo, courseName, courseCount, courseAvg) as select Score.courseNo, courseName, count(*), avg(score) from Score, Course where Score.courseNo=Course.courseNo group by Score.courseNo, courseName
-
方式二:建立在视图上的视图
(2). 查询视图
查询视图是对视图最主要的操作
从用户角度看:查询视图与查询基本表的方式完全一样
从系统角度看:查询视图过程如下
- 进行有效检查,检查查询中涉及的基本表和视图是否存在
- 从数据库系统表中取出创建视图的语句,将创建视图的子查询与用户的查询结合起来,转换成等价的对表的查询
- 执行改写后的查询
举例:
select *
from StudentView1999 --基于视图的查询
where classNo='CS1610'
--对于该查询,系统首先进行有效性检查,判断视图是否存在,如果存在,
--则从数据库系统表中取出该创建视图的语句,将创建视图的子查询语句与用户查询结合起来
--转换后的查询如下
select *
from Student
where year(birthday)=1999 and classNo='CS1601'
(3). 视图更新
由于视图是一个虚表,不实际存放数据,对视图的更新,最终要转换为对基本表的更新,因此,如果创建视图的语句不包含表达式,或聚合运算,或消除重复值运算,则不能对视图进行更新操作
定义:视图更新指通过视图来插入、删除、修改基本表中的数据
注:对视图进行更新操作限制比较多,建立视图的作用不是利用视图来更新数据的,而是简化查询,以及一定程度的安全保护,所以尽量不要对视图执行更新操作
(4). 删除视图
语法:
drop view 视图名 [cascade]
--注:caseade是级联删除的意思,表示从数据库系统中删除指定视图及其视图上导出的视图
--删除原始的基本表,但是没有删除依附在原始表上的视图,使用此视图会报错
4. 索引的定义
数据库中如果数据有序,则可以大大提升检索的速度
对基本表中的记录进行排序有两种方案:
- 对记录进行物理上的重新组织(这点非常难做)
- 不改变物理顺序,通过建立索引来实现数据记录的重新排列,称为逻辑排序
SQL语句提供索引定义语句对基本表建立索引,有系统自动维护
建立索引之后,系统存储数据时会自动选择合适的索引作为存储路径
一个基本表可以建立多个索引,从不同角度加快查询速度,如果建立索引太多,给数据维护带来较大的系统开销
索引记录的组成:
- 搜索码值:按搜索码值进行排序,但不改变基本表中记录的物理顺序
- 指针
索引和基本表分别存储:
如班级表class中按所属学院建立的索引InstitutuIdx,它与class表的关系
(1). 索引的建立
语法:
create [unique] [clustered|nonclustered]
index 索引名
on 表名(列名1[asc|desc], 列名2[asc|desc])
-- 其中unique:建立唯一索引
-- clustered|nonclustered表示建立聚集|非聚集索引,默认非聚集索引
-- asc|desc 表示升序|降序
(2). 索引的删除
索引是由系统自动维护,但是如果对基本表经常进行增、删、改操作,使得系统花费大量时间维护索引,降低了对基本表的更新操作速度,这时候就可以删除索引了
语法:
drop index 索引名
on 表名
注:删除索引的同时,系统会从系统表中将该索引的描述信息一起删除
二. SQL数据更新语言(DML)
SQL数据更新语句包括3条:插入(insert)、删除(delete)、修改(update)
这3条语句用于对基本表的元组进行增删改。
1. 插入数据
SQL插入语句是将新的元组插入到基本表中,有两种方式:
(1). 插入一个元组
语法:
-- 方式一
insert into 表名(列名1, 列名2, ....., 列名n) values('值1', '值2', ....., '值n')
--此方式按指定顺序和指定列插入相应的数值,有些没有列出的属性列自动取空值或者默认值
-- 方式二
insert into 表名 values('值1', '值2', '值3', ......, '值n')
--此方式必须按顺序对应所有列来插入数据
(2). 插入子查询的结果(插入多个元组)
-- 方式一
insert into 表名
select *
from ...
where ...
-- 此语句功能是将子查询中的数据按照被插入表的对应列进行插入数据
-- 方式二
insert into 表名(列名1, 列名2, ....., 列名n)
select 列名1, 列名2, ....., 列名n
from ...
where ...
-- 此语句的功能是将查询的指明列中的数据插入到表中,其余列自动取空值或者默认值
2. 删除数据
语法:
-- 方式一:删除基本表
delete from 表名
注:
delete:只删除表中的所有记录,相当于对表进行清空操作,并不删除表本身
drop: 要把表本身给删除掉
-- 方式二:删除基本表中的某些元组
delete from 表名
where 被删除元组所满足的条件
3. 修改数据
语法:
update 表名
set 列名1=需要改成的值, 列名2=需要改成的值, ..., 列名n=需要改成的值
where 被修改元组所满足的条件
三. 数据库编程
现代数据库管理系统如SQL Server、Oracle等对SQL进行了扩展,引入了编程技术来解决更复杂的操作,主要包括:流程控制语句、游标、触发器、存储过程
1. T-SQL语言
(1). 表达式
变量
-
SQL serve变量的分类:
局部变量:在变量名前加一个@符号
全局变量:在变量名前加两个@符号 -
SQL server声明了若干系统全局变量,这些可以直接使用
常用的系统全局变量如以下几种:
@@ERROR:当事务成功时返回0,否则为最近一次错误号 @@rowcount:返回受上一语句影响的行数