参考教材《数据库系统:原理、设计与编程(MOOC版)》,陆鑫 张凤荔 陈安龙
选择这本书来学习是因为教材出版时间是2019年3月,比较新,而且出版社是人民邮电出版社,根据我的经验,人民邮电出版社出版的技术类书籍基本都是精品。这本书除了基本概念,关系模型,SQL,数据库设计与实现和管理这些必学内容之外,还包括数据库应用编程和NoSQL数据库的内容。如果我没记错的话,我的学校的数据库课程应该是只教了SQL,别的基本都没教。所以我对这本书的印象挺不错的。
下面是一些笔记。
1. SQL的类型
首先明确一下各种SQL语句的类型分类,让后面的学习不至于那么乱。
-
数据定义语言(Data Definition Language, DDL),用于创建与维护数据库对象,如数据库、数据库表、视图、索引、触发器、存储过程等。该类语句包括创建对象、修改对象和删除对象等语句。如:
CERATE TABLE ... DROP TABLE ... CREATE INDEX ... DROP INDEX ...
-
数据操纵语言DML(Data Manipulation Language, DML),用于对数据库中的数据表或视图进行数据插入、删除、更新等处理。如:
INSERT ... UPDATE ... DELETE ...
-
数据查询语言DQL(Data Query Language, DQL),用于从数据库表中查询或统计数据,但不改变数据。如:
SELECT ...
-
数据控制语言DCL(Data Control Language, DCL),用于DBA用户管理数据库对象的访问权限。如:
GRANT ...
GRANT语句用于授权用户或角色对指定数据库对象的访问权限,此处的数据库对象应该是指1.中的数据库、数据库表、视图等。
-
事务处理语言TPL(Transaction Process Language, TPL),用于数据库事务的编程处理。如:
BEGIN TRANSACTION ... // 事务开始 COMMIT ... // 事务提交 ROLLBACK ... // 事务回退
-
游标控制语言CCL(Cursor Control Language, CCL),用于数据库游标结构的使用,如:
DECLARE CURSOR ... // 用于数据库游标对象声明 FETCH INTO ... // 用于提取游标所指向的缓冲区数据 CLOSE CURSOR ... // 用于关闭游标对象
2. SQL的数据类型
-
字符串型:varchar(n), char(n)
字符串型为若干字符编码构成的字节数据。varchar(n)是可变长度字符串,char(n)是固定长度字符串,varchar(n)比char(n)字段占用更少的内存和硬盘空间,但检索速度慢。 -
整数型:int, smallint
int值范围与CPU字长有关,CPU字长16位时,int整数范围为-32768-32767。smallint为小整数,通常为8位,范围为-128-127。 -
定点数型:numeric(p, d)
p为定点数的总位数,d为定点数的小数位数。该数据类型可以表示带小数的数值。 -
浮点数型:real, double(n, d)
real为单精度浮点数,double(b, d)为双精度浮点数。 -
货币型:money
专门用于货币数据表示。 -
逻辑型:bit
只能取0或1,用于表示真和假。 -
日期型:date
用于表示日期数据的年/月/日
不同的关系数据库还提供一些不同的扩展类型。例如SQL Server的image类型。
各种SQL语句的详细用法在本笔记中不再列出,我打算当用到的时候就去查书,直到熟能生巧,慢慢记住。而不是像应付考试一样一次性背过。
SQL Server的数据类型:
表来源于参考书数据库系统:原理、设计与编程(MOOC版)》,陆鑫 张凤荔 陈安龙。
3. 数据定义SQL语句
由于下列内容有部分代码,为了跟书的内容对应,方便查书,所以下面的3.2.x实际对应书的3.2.x。
3.2 数据库的定义
3.2.1 数据库创建SQL语句
数据库 文档:
https://docs.microsoft.com/zh-cn/sql/relational-databases/databases/databases?view=sql-server-ver15
示例(SQL Server 2019 Express):
USE master;
GO
-- 数据定义SQL语句
-- 创建数据库
CREATE DATABASE HR;
GO
USE HR;
GO
-- 修改数据库属性
-- 重命名
ALTER DATABASE HR MODIFY NAME = MyHR;
GO
-- 删除数据库
USE master;
GO
DROP DATABASE MyHR
3.2.2 数据库表对象的定义
表 文档:
https://docs.microsoft.com/zh-cn/sql/relational-databases/tables/tables?view=sql-server-ver15
(1). 数据库表创建SQL语句
-- 数据库表对象的定义
-- 数据库表创建SQL语句
CREATE TABLE Student
(StudentID char(13) PRIMARY KEY,
StudentName varchar(10) NOT NULL,
StudentGender char(2) NULL,
BirthDay date NULL,
Major varchar(30) NULL,
StudentPhone char(11) NULL);
GO
-
列约束关键词
上述语句使用到了列约束关键词,如PRIMARY KEY,NOT NULL。除了这些基本约束之外,还可以使用UNIQUE、CHECK、DEFAULT等关键词分别约束列取值的唯一性、值范围和默认值。CREATE TABLE Course (CourseID char(4) PRIMARY KEY, CourseName varchar(20) NOT NULL UNIQUE, CourseType varchar(10) NULL CHECK(CourseType IN('基础课', '专业', '选修')), CourseCredit smallint NULL, CoursePeriod smallint NULL, TestMethod char(10) NOT NULL DEFAULT '闭卷考试'); GO
-
表约束关键词
在前面表的创建中,使用列约束关键词PRIMARY KEY定义表的主键,只能定义单列主键,若要定义多列复合主键,则需要使用表约束方式。这种方式通过在创建表的SQL语句中加入CONSTRAINT关键词来标识表约束。CREATE TABLE Plans (CourseID char(4) NOT NULL, TeacherID char(4) NOT NULL, CourseRoom varchar(30), CourseTime varchar(30), Note varchar(50), CONSTRAINT CoursePlan_PK PRIMARY KEY(CourseID, TeacherID)); GO
上述代码创建了一个名叫CoursePlan_PK的复合主键约束。通常使用“_PK”作为主键约束名称后缀。上述代码是在新表中创建复合主键。
在现有表中创建主键:
https://docs.microsoft.com/zh-cn/sql/relational-databases/tables/create-primary-keys?view=sql-server-ver15#to-create-a-primary-key-in-an-existing-table -
表约束定义代理键
在一些情况下,使用代理键代替符合主键,可以方便地对主键操作和提高处理性能。顾名思义,代理键就是再新建一列作为这个表的主键,例如Plans表,可以新建一列CoursePlanID,然后把它约束为主键。
SQL Server的实现:CREATE TABLE Plans (CoursePlanID int IDENTITY(1,1) NOT NULL, CourseID char(4) NOT NULL, TeacherID char(4) NOT NULL, CourseRoom varchar(30), CourseTime varchar(30), Note varchar(50), CONSTRAINT CoursePlan_PK PRIMARY KEY(CoursePlanID)); GO
PostgreSQL的实现:
CREATE TABLE Plans (CoursePlanID serial NOT NULL, CourseID char(4) NOT NULL, TeacherID char(4) NOT NULL, CourseRoom varchar(30), CourseTime varchar(30), Note varchar(50), CONSTRAINT CoursePlan_PK PRIMARY KEY(CoursePlanID)); GO
主键CoursePlanID数据类型为serial,同时系统自动生成plan_courseplanid_seq序列,为代理键CoursePlanID取值。serial是Postgre的4字节自增序列整数,范围为1-2147483647。
-
表约束定义外键
CONSTRAINT关键字不但可以定义主键,也可以定义外键。在执行SQL的表创建语句时,同时也可建立该表与其关联表的参照完整性约束,即约束本表中的外键列取值参照关联表中的主键列值。CREATE TABLE Register (CourseRegID int IDENTITY(1,1) NOT NULL, CoursePlanID int NOT NULL, StudentID char(13), Note varchar(30), CONSTRAINT CourseRegID_PK PRIMARY KEY(CourseRegID), CONSTRAINT CoursePlanID_FK FOREIGN KEY(CoursePlanID) REFERENCES Plans(CoursePlanID) ON DELETE CASCADE, CONSTRAINT StudentID_FK FOREIGN KEY(StudentID) REFERENCES Student(StudentID) ON DELETE CASCADE); GO
(2). 数据库表修改SQL语句
基本语句格式:
ALTER TABLE Student ADD Email varchar(20); -- 增加列
ALTER TABLE Student DROP COLUMN StudentPhone; -- 删除列
包括四种修改方式:
- ADD修改方式,用于增加新列或列完整性约束。
ALTER TABLE <表名> ADD <新列名称><数据类型>[完整性约束];
- DROP修改方式,用于删除指定列或列的完整性约束条件。
ALTER TABLE <表名> DROP COLUMN <列名>;
ALTER TABLE <表名> DROP CONSTRAINT <完整性约束名>;
- RENAME修改方式,用于修改表名称、列名称。
ALTER TABLE <表名> RENAME TO <新表名>;
ALTER TABLE <表名> RENAME <原列名> TO <新列名>;
- ALTER修改方式,用于修改列的数据类型。
ALTER TABLE <表名> ALTER COLUMN <列名> TYPE <新的数据类型>;
(3). 数据库表删除SQL语句
基本语句格式:
DROP TABLE <表名>;
3.2.3 数据表索引对象定义
若一个表中有百万行记录数据,进行查询的时候,最基本的搜索信息方式是全表搜索,即将所有行数据全部列出,与查询条件一一对比,然后返回满足条件的行。这样的开销太大,消耗时间太多,造成大量磁盘I/O操作。因此需要在数据表中建立类似图书目录的索引结构,并将索引列的值及索引指针数据保存在索引结构中。此后在对数据表进行查询时,首先在索引结构中找到符合条件的索引指针值,再根据索引指针快速找到对应的数据记录,可以实现快速检索元组数据。
索引是一种针对表中指定列的值进行排序的数据结构,使用它可以加快表中数据的查询。
在SQL中可以使用数据定义语言创建、修改、删除索引。
(1). 索引对象创建SQL语句
基本格式:
CREATE INDEX <索引名> ON <表名> <(列名[,...,])>;
其中CREATE INDEX
为创建索引语句的关键字;<索引名>为在指定表中针对某列创建的索引的名称。
例:
CREATE INDEX BirthDay_Idx ON Student (BirthDay);
GO
上述代码可以创建学生信息表(Student)的BirthDay_Idx索引。维护索引有一定开销,一般仅对需要快速查询的数据库表相应列建立索引。一般需要为每个表的主键列创建索引。
CREATE INDEX
语句创建的索引,其索引值可能会重复,如果应用不允许有重复索引值,则需要使用如下创建唯一索引的SQL语句格式:
CREATE UNIQUE INDEX BirthDay_Idx ON Student (BirthDay);
(2). 索引对象修改SQL语句
格式:
ALTER INDEX <索引名> RENAME TO <新索引名>;
该格式在SQL Server中似乎无法使用。经过查找资料,通过一下方式实现SQL Server的修改索引名:
EXEC sp_rename N'Student.BrithDay_Idx', N'BDay_Idx', N'INDEX';
GO
第一个参数为表名.索引名,第二个参数为新索引名,第三个参数为INDEX。
官方文档:https://docs.microsoft.com/zh-cn/sql/relational-databases/system-stored-procedures/sp-rename-transact-sql?view=sql-server-ver15
该文档是使用sp_rename来修改各种名字的文档:
--更改表名: old_tabName 改为 new_tabName
sp_rename 'old_tabName','new_tabName'
--更改列名: old_colName 改为 new_colName
sp_rename 'tabName.old_colName','new_colName','COLUMN'
--更改索引名: old_indName 改为 new_indName
sp_rename 'tabName.old_indName','new_indName','INDEX'
--更改类型名: old_typeName 改为 new_typeName
sp_rename 'tabName.old_typeName','new_typeName','USERDATATYPE'
(3). 索引对象删除SQL语句
格式:
DROP INDEX <索引名>;
实际使用时在SQL Server中不行,改为DROP INDEX <表名.索引名>;
便可以运行。
DROP INDEX Student.BDay_Idx;
GO
或许这并不是在SQL Server中的通用写法,还需日后学习。