1. SQL概述
SQL,结构化查询语言,重要性不必在赘述了,基本上开发软件没有不用到的,此外在一些大数据也有广泛的应用。SQL主要包含数据定义语言(DDL)、数据操纵语言(DML)以及数据控制语言(DCL)【感觉没什么太大用处】。SQL不仅支持独立使用还支持嵌入到通用程序设计语言中。其中,DDL主要负责基本表、视图、模式等等的定义修改和删除;DML主要就是查询、更新(插入、删除、修改)表或者视图这些对象,关系代数也基本都会投射到这上面来;DCL主要是创建用户、修改密码、分配权限这些数据库层面上的操作。
在SQL中,关系被称为表,SQL的表有两类:基本表和导出表,基本表就不必解释,导出表即通过查询表达式求值时,直接或者间接从一个或者多个基本表中导出而来,视图表是命名的导出表。
2.数据定义
1)表的创建
关于数据定义,首先就是基本表的创建、修改和删除。SQL使用 CREATE TABLE 语句创建基本表,下面是创建一个Teachers表的SQL语句:
CREATE TABLE Teachers
(Tno CHAR(7) PRIMARY KEY,
Tname CHAR(10) NOT NULL,
Sex CHAR(2) CHECK(Sex = '男' OR Sex ='女'),
Birthday DATE,
Title CHAR(6),
Dno CHAR(4),
FOREIGN KEY (Dno) REFERENCES Departments(Dno));
从第二行起即为定义属性的信息,基本格式如:<列名> <类型> [DEFAULT <缺省值>] [<列约束>,…, <列约束>],【统一说明[X]表示可以缺省,而<X>表示需进一步定义】。
第一列是属性名称;
类型代表该列在SQL中的数据类型,而SQL中的内置数据类型包括:CHAR(n) 长度为n的定长字符串,默认为长度1,全称为CHARACTER; VARCHAR(n)最大长度为n的变长字符串,默认长度为1,全称CHARACTER VARYING,VARCHAR与CHAR的主要区别是定长字符串不论你输入字符串是长是短,分配的存储空间是一定的,而变长字符串会根据输入的大小占用的空间是可变的,显然会更加灵活一些;BIT(n)定长二进位串,默认为长度1;BIT VARYING(n) 最大长度为n的变长二进位串,默认长度为1;INT整型,全称INTEGER;SMALLINT小整数;NUMERIC(p,d) p为有效数字的定点数,其中小数点右边占d位;DEC(p,d)全称DECIMAL,好像和NUMERIC没太大区别(未经查证);FLOAT(n) 精度至少为n的浮点数;REAL 实数,其中REAL=FLOAT(24);DOUBLE PRECISION双精度实数,精度比REAL高;DATE日期,包括年月日,格式为YYYY-MM-DD;TIME时间,包括时分秒,格式为HH:MM:SS,TIME(n)可以表示更加精确的单位,意即秒后取n位;TIMESTAMP时间戳,是DATE和TIME的结合,TIMESTAMP(n)表示秒后取n位;INTERVAL时间间隔;
缺省值即定义该列没有赋值时默认的取值,可以省略;列约束可以在每列上定义零个或者多个约束条件,约束该列的取值,例如上面示例中的PRIMARY KEY代表主键,不能取空,不能重复;NOT NULL代表不能为空;CHECK(条件)指明该列的值必须满足的条件,其中<条件>是一个布尔表达式;除此之外,常用的列约束还有UNIQUE表示该列上的值唯一,说明该列是候选码;
最后一行是表约束,常见格式是[,<表约束1>,…,<表约束n>],常见的表约束和列约束大致相同只不过是plus版本,比如主码PRIMARY KEY(A1,…,Ak)代表这些属性共同构成主码,UNIQUE和主码的使用方法差不多。而比较复杂的可能是外码设置上,它具有如下格式:FOREIGN KEY (A1,…,Ak) REFERENCES <外表名称> (<外表的主码>) [<参照的触发动作>],<参照的触发动作>表示违反参照完整性时数据库应该采取什么方式的操作,当然外键声明可以有不止一条,可以将其视为多个列约束,以逗号分开即可。
2)表的修改(添加列、删除列、添加表约束、删除表约束)
而表的修改主要使用ALTER语句,我们可以添加列 ALTER TABLE <表名> ADD [COLUMN] <列定义>,比如在Courses中添加一个新的列Pno表示课程号,可以使用语句
ALTER TABLE Courses ADD Pno CHAR(10) PRIMARY KEY;
有添加列,自然就会有删除列的操作,DROP关键词隆重登场,以后关于删除我们还会用到它哦,基本格式比较简单 ALTER TABLE <表名> DROP [COLUMN] <列名> {CASCADE|RESTRICT},比如我们再把上面添加的列删除:
ALTER TABLE Courses DROP COLUMN Pno;
对于CASCADE表示级联,删除成功后会将依赖于该列的数据库对象(比如视图)一并删除。RESTRICT表示受限,即当该列没有数据库对象依赖时,才能删除成功。
除了添加、删除之外,还能对已存在的列进行表约束的添加和删除:ALTER TABLE <表名> ADD <表约束定义>;ALTER TABLE <表名> DROP CONSTRAINT <表约束定义>;{CASCADE|RESTRICT},其实只要出现删除几乎就会出现它们俩,这是为了保证数据库完整性约束的必要之举。
补充:其实还有一个修改或这删除列的缺省值,ALTER TABLE <表名> ALTER [COLUMN] <列名> {SET DEFAULT <缺省值> | DROP DEFAULT}
3)表的删除
最喜欢这种简单的SQL语句啦!!
DROP TABLE <表名> {CASCADE|RESTRICT}
摊手,就是这么简介高效。
3.数据查询
查询是最重要的数据库操作,没有之一!而在SQL中查询时通过SELECT语句来实现的。SELECT语句的基本形式为:
SELECT [ALL|DISTINCT] <选择序列>
FROM <表引用>,…,<表引用>
[WHERE <查询条件>]
[GROUP BY <分组列>,…,<分组列> [HAVING <分组选择条件>] ]
[ORDER BY <排序列> [ASC|DESC],…,<排序列> [ASC|DESC]]
好长啊,不过分解来看也就五个语句,分别是SELECT,FROM ,WHERE ,GROUP BY 以及ORDER BY,其中只有SELECT和FROM是必须的,而其他均为可选,我们也按照这个思路进行展开。
1)SELECT+FROM进行简单查询
SELECT即为投影运算,形式为:SELECT [ALL|DISTINCT] <选择序列>,先接ALL或者DISTINCT修饰,分别代表不删除和删除相应的重复行,当然可以不写,默认为ALL咯。选择序列“要选择的属性”,属性之间以逗号分开,如果结果包含所有属性,可以使用*表示。
FROM语句相当于笛卡儿积运算,列出需要查询的基本表和导出表,表之间中间用逗号隔开,基本格式:FROM <表引用>,…,<表引用>,为什么不是表名而是表引用呢?表名只是其中一种表引用,但是因为还用另一种用法,即重命名表名,具体形式为:<表名> [AS] <表别名>,用于SELECT+FROM+WHERE结构中区分重复出现的同一张表。
SELECT+FROM是最基本的查询操作,当然这样只能从同一张表中进行查询,比如在Courses表中查询所有课程的名称,并重命名为X,且删除重复的课程名,具体语句为:
SELECT DISTINCT Cname AS X
FROM Courses;(关于SQL中分号问题,其实经过我的观察是很开放的,并没有明确的规则来确定是否加分号,可能需要视情而定,但是在程序中嵌入一般都不需要分号,这样会报错的)
2)SELECT+FROM+WHERE进行查询
WHERE可以进行更加复杂的查询,后跟一个布尔表达式,包括比较表达式(>、<、=、>=、<=、<>、!=)、BETWEEN表达式、IN表达式、LIKE表达式等等。我们一一来看,对于比较表达式其实就是比较大小。
例如查寻考试成绩不合格的学生学号:
SELECT DISTINCT Sno
FROM SC
WHERE Grade < 60;
BETWEEN表达式可以表示一个范围,例如查询出生年份在1997-2000年的学生的姓名和专业:
SELECT Sname,Cname
FROM Student
WHERE Year (NOT) BETWEEN 1997 AND 2000;(加上not的表示不在这个范围年份的学生学号或者专业)
BETWEEN AND表达式一般都可以用AND或者OR连接的比较表达式表示。
SELECT Sname,Cname
FROM Student
WHERE Year >= 1997 AND <=2000;(Year < 1997 OR >2000和上面加NOT语句之后表达的意思一样)
IN表达式用于判别给定的元素是否在给定的集合中,自然NOT IN表示不在集合中胡返回TRUE。基本形式为<值表达式> [NOT] IN (<值表达式列表>),前面的值表达式通常是属性,后面的值表达式通常就是指具体值,多个值组成所谓的集合,中间用逗号分隔并用括号括住。
例如查询计算机科学与技术和软件工程两个专业的学生学号和姓名
SELECT Sno,Sname
FROM Student
WHERE Speciality IN (‘计算机科学与技术’,‘软件工程’);(字符串表达式记得加上单引号)
LIKE表达式能够模糊地查询出相似的字符串值,最常用的两种是已知若干字符、已知其中若干字符和位置并了解全部字符串的长度。
第一种使用%代表不定长的字符,例如查询所有姓李的学生的姓名
SELECT Sname
FROM Student
WHERE Sname LIKE ‘李%’ (若以李结尾则可改为‘%李’)
%使用时不确定性比较高,信息较多时可以使用_表示一个字符,然后用已知字符和_字符共同表示出目标字符串,例如查询‘数据’开头,并且四个汉字的课程名称
SELECT Cname
FROM Courses
WHERE Cname LIKE ‘数据_ _ _ _’(汉字占两个字符,因此需用四个_表示剩下的两个汉字)
但是想必做过简单开发的同学都知道,这时间肯定会出现转义问题,当你要查的值本省身就'_'或者'%'字符时那就必须要进行‘转义’,就像C语言的 \ 一样,SQL中是ESCAPE语句,比如查询C_开头的课程:
SELECT Cname
FROM Courses
WHERE Cname LIKE 'C\_%' ESCAPE '\'(ESCAPE定义\为转义字符,因此C\_%中的_将被转义,不在作为通配符使用)
此外,还有NULL表达式可以查询属性上是否为空
SELECT Sno
FROM SC
WHERE Grade IS NULL;