- 1. 什么是数据库
- 2. 为什么需要数据库
- 3. 数据库的安装和卸载
- 4. 预备知识
- 5. 必备的一些操作
- 6. 数据库是如何解决数据存储问题的
- 6.1 表的相关数据
- 6.2 学会create table命令
- 6.3 什么是约束
- 6.4 表和约束的区别
- 6.5 什么是关系
- 6.6 主键
- 6.7 外键
- 6.8 查询【最重要,难度最大】
- 6.9 视图
- 6.10 事务
1. 什么是数据库
- 狭义:存储数据的仓库
- 广义:可以对数据存储和管理的软件以及数据本身
-
2. 为什么需要数据库
几乎所有的应用软件的后台都需要数据库
- 数据库存储数据占用空间小,容易持久保存
- 存储比较安全
- 容易维护和升级
- 数据库移植比较容易
- 简化对数据的操作
- 为将来学Oracle做准备
-
3. 数据库的安装和卸载
SQL2000,解决挂起问题
-
4. 预备知识
4.1 学习数据库必须先学习数据库原理
4.2 学习SQL2005必须先学习一门编程语言吗
4.3 数据结构和数据库的区别
- 数据库是在应用软件级别研究数据的存储和操作—外层、硬盘
-
4.4 什么是连接
4.5 有了编程语言为什么还需要数据库
对内存数据操作时是编程语言的强项,但对硬盘数据操作时是编程语言的弱项
-
4.6 建议初学者从三个方面学习数据库
数据库是如何存储数据的
- 了解字段、记录、表、
- 知道约束(主键、外键、维一键、非空、check、default、触发器)
- 数据库是如何操作数据的
- 明白指令(insert、update、delete、TL_SQL)
- 掌握储存过程、函数、触发器
数据库是如果显示数据的
了解数据库:后缀mdf是数据文件,后缀ldf是日志文件
- 系统数据库:默认4个库,不要增删改查,放置不动即可
-
5.2 如果删除数据库
选中数据库,右键删除数据库,DATA文件夹中mdf和ldf文件一并删除
5.3 如果附加和分离数据库
选中需要分离的数据库,右键任务-分离,勾选删除连接、更新数据信息后确定
选中数据库,右键附加,添加在DATA中找到分离的mdf文件,确定即可
5.4 如何登陆用户名和命名
5.5 如何创建用户
6. 数据库是如何解决数据存储问题的
6.1 表的相关数据
6.1.1 字段
6.1.2 记录
6.1.3 表
6.1.4 表、字段和记录的关系
6.1.5 列
6.1.6 属性
6.1.7 元祖
6.2 学会create table命令
6.2.1 利用对象资源管理器新建表
6.2.2 利用命令新建表
6.2.2.1 创建一个dept表并赋值查询
—创建表
USE scott
CREATE TABLE dept
(
deptno INT PRIMARY KEY
,dname NVARCHAR(20) NOT NULL
,loc NVARCHAR(50)
);
—赋值并查询
INSERT INTO dept (deptno,dname,loc) VALUES
(10,Accounting,NewYork)
,(20,Research,Dallas)
,(30,Sales,Chicago)
,(40,Operations,Boston)
,(50,Advertisement,BeiJing);
SELECT * FROM dept;6.2.2.2 创建一个emp表并赋值查询
—创建表
USE scott
CREATE TABLE emp
(
empno INT CONSTRAINT pk_emp_empno PRIMARY KEY
,ename NVARCHAR(20) NOT NULL
,iob NVARCHAR(20) NOT NULL
,mgr INT
,hiredate DATETIME NOT NULL
,sal INT NOT NULL
,comm INT
,deptno INT CONSTRAINT fk_dept_deptno FOREIGN KEY REFERENCES dept(deptno)
);
—赋值并查询
INSERT INTO emp (empno,ename,iob,mgr,hiredate,sal,comm,deptno) VALUES
(7369,SMITH,CLERK,7902,1981-12-17,800,NULL,20)
,(7499,ALLEN,SALESMAN,7698,1981-02-20,1600,300,30)
,(7521,WARD,SALESMAN,7698,1981-02-22,1250,500,30)
,(7566,JONES,MANAGER,7839,1981-04-02,2975,NULL,20)
,(7654,MARTIN,SALESMAN,7698,1981-09-28,1250,1400,30)
,(7698,BLAKE,MANAGER,7839,1981-05-01,2850,NULL,30)
,(7782,CLARK,MANAGER,7839,1981-06-09,2450,NULL,10)
,(7788,SCOTT,ANALYST,7655,1981-04-19,3000,NULL,20)
,(7839,KING,PRESIDENT,NULL,1981-11-17,5000,NULL,10)
,(7844,TURNER,SALESMAN,7698,1981-09-08,1500,0,30)
,(7876,ADAMS,CLERK,7788,1987-05-23,1100,NULL,20)
,(7900,JAMES,CLERK,7698,1981-12-03,950,NULL,30)
,(7902,FIRD,ANALYST,7566,1982-12-03,3000,NULL,10)
,(7934,MILLER,CLERK,7782,1982-01-23,1300,NULL,10);
SELECT * FROM emp;6.2.2.3 创建一个salgrade表并赋值查询
—创建表
USE scott
CREATE TABLE salgrade
(
grade INT CONSTRAINT pk_salgrade_grade PRIMARY KEY
,losal INT NOT NULL
,hisal INT NOT NULL
);
—赋值并查询
INSERT INTO salgrade (grade,losal,hisal) VALUES
(1,700,1200)
,(2,1201,1400)
,(3,1401,2000)
,(4,2001,3000)
,(5,3001,9999);
SELECT * FROM salgrade;6.2.2.4 创建一个班级表
CREATE TABLE banji
(
banji_id INT PRIMARY KEY
,banji_num INT NOT NULL
,banji_name NVARCHAR(100)
)6.2.2.5 创建一个教师表
CREATE TABLE jiaoshi
(
jiaoshi_id INT PRIMARY KEY
,jiaoshi_name NVARCHAR(100)
)6.2.2.6 第三张表,用来模拟班级和教师的关系
CREATE TABLE banji_jiaoshi_mapping
(
banji_id INT CONSTRAINT fk_banji_id FOREIGN KEY REFERENCES banji(banji_id)
,jiaoshi_id INT CONSTRAINT fk_jiaoshi_id FOREIGN KEY REFERENCES jiaoshi(jiaoshi_id)
,kecheng NVARCHAR(50)
,CONSTRAINT pk_banji_id_jiaoshi_id PRIMARY KEY (banji_id,jiaoshi_id,kecheng)
)6.3 什么是约束
定义:对一个表中的字段操作的限制
分类:
- 主键约束:不允许重复元素,避免数据冗余;实体完整性
- 外键约束:保证了本事物所关联的其他事务一定是存在的;引用完整性
- check约束:保证事物属性的取值在合法的范围之内(emp_sal INT CHECK(emp_sal>=1000 AND emp_sal<=8000) )
- default约束:保证事物的属性一定有一个值(emp_sex NCHAR(1) DEFAULT (‘男’)—()可以省略)
- 唯一约束:保证事物属性的取值不允许重复,但允许其中有一列且仅有一列为空(emp_name NVARCHAR(20) UNIQUE NOT NULL)
- NOT NULL约束:要求用户必须为该属性赋一个值,否则语法出错
6.4 表和约束的区别
数据库是通过表来解决事物的存储的问题
- 数据库是通过约束来解决事物取值的有效性和合法性的问题
-
6.5 什么是关系
定义:模拟表和表之间的联系
- 实现方式:通过设置不同形式的外键来体现表和表之间的不同关系
分类(假设是A表和B表):
定义:能够维一标示一个事物的一个字段或者多个字段的组合。
附注:
- 含有主键的表叫做主键表
- 主键通常都是整数,不建议用字符串(如果主键用于集群式服务,才可以考虑用字符串当主键)
- 主键的值通常都不允许修改,除非本记录被删除
- 主键不能为空值,
- 主键不要定义成id,而要定义成表名Id或是表名_id
- 主键一般用代理主键(一般是单独添加一个整型编号当主键字段),不要用业务主键
- IDENTITY标识列,主键自动增长,用户不需要为IDENTITY修饰的主键赋值
- IDENTITY(m, n) m表示初始值,n表示每次自动增加的值,m和n要么同时指定,要不都不指定
- IDENTITY(m, n) m和n若指定,默认值是(1,1)
- 数据类型是整型的列才能被定义成标识列,通常与PRIMARY KEY一起用作表的维一标识符
- 非主键也可以被定义成IDENTITY,但不推荐
6.7 外键
定义:如果一个表中的若干个字段是来源于另外若干个表的主键,则若这干个字段就叫外键
附注:
- 外键是联系一个表和另一个表,体现事务与事务质检的关系
- 外键通常来自另外表的主键而不是唯一键,因为唯一键可能为NULL
- 含有外键的表交外键表,外键字段来自的哪一张表叫做主键表
如果要删除表,先删外检表再删主键表,若先删主键表会报错(导致外键表中的数据引用失败)
6.8 查询【最重要,难度最大】
6.8.1 计算列
a. 事例:SELECT sal*12 AS “年薪” FROM emp;
b. 注意:别名只能用双引号,不能用单引号括起来
c. 概况:看懂一个程序分三步,第一步流程(执行语句先后顺序),第二步语句功能,最后找表实验一下6.8.2 distinct【不允许重复的】
a. 事例:SELECT DISTINCT deptno FROM emp;—过滤掉重复的部门编号,只保留有区别的部门编号
SELECT DISTINCT comm FROM emp;—去重后的奖金明细,若有多个NULL和0,只保留一个
SELECT DISTINCT deptno,comm FROM emp;—将部门编号和奖金组合进行过滤
SELECT deptno,DISTINCT comm FROM emp;—error,逻辑上有冲突6.8.3 between【在某个范围】
a. 事例:SELECT FROM emp WHERE sal >= 1500 AND sal <= 3000; 等价于
SELECT FROM emp WHERE sal BETWEEN 1500 AND 3000;—工资在1500到3000的员工的所有信息
SELECT FROM emp WHERE sal < 1500 OR sal > 3000;—工资小于1500或大于3000的员工所有信息
SELECT FROM emp WHERE sal NOT BETWEEN 1500 AND 3000; 等价于以上筛选6.8.4 in【属于若干个孤立的值】
a. 事例:SELECT FROM emp WHERE sal IN (1500,3000);—工资是1500或是工资是3000的员工的所有信息
SELECT FROM emp WHERE sal = 1500 OR sal = 3000; 等价于以上筛选
SELECT FROM emp WHERE sal NOT IN (1500,3000);—工资即不是1500也不是3000的员工信息
SELECT FROM emp WHERE sal <> 1500 AND sal <> 3000; 等价于以上筛选
b. 说明:数据库中不等于有两种表达方式:!=、<> 推荐使用第二种
对或取反是并且,对并且取反是或6.8.5 top【最前面的若干个记录】
a. 事例:SELECT TOP 2 FROM emp;—查询员工表前两行的所有信息
SELECT FROM emp WHERE ROWNUM < 3;—Oracle中查询员工表前两行的所有信息
SELECT TOP 15 PERCENT FROM emp;—查询全部记录15%行的所有员工信息(有小数增加一条记录)
SELECT TOP 4 FROM emp WHERE sal BETWEEN 1500 AND 3000 ORDER BY sal DESC;
—查询工资在1500到3000之间(包括1500和3000)的员工中工资最高的按降序排序的员工信息
b. 说明:分页查询后边还会详细介绍6.8.6 null【没有值或是空值】
a. 事例:SELECT FROM emp WHERE comm IS NULL;—查询奖金为空的所有员工的信息
SELECT FROM emp WHERE comm IS NOT NULL;—查询奖金不为空的所有员工的信息
SELECT ename,sal12+comm AS “年薪” FROM emp;—error
SELECT ,sal*12+ISNULL(comm,0) AS “年薪” FROM emp;—查询员工的年薪等所有信息
b. 说明:NULL不能参与<>、!=、=的运算,可以参与is、not is的运算
NULL和0是不一样的,NULL表示空值、没有值,0表示一个确定的值
NULL不能参与任何数学运算,否则结果只能为NULL
ISNULL(comm,0)—如果comm是NULL,就返回0,否则返回comm
任何类型的数据都允许为NULL6.8.7 order by【以某个字段排序】
a. 事例:SELECT FROM emp ORDER BY sal;—查询所有的员工信息,按工资升序排序
SELECT FROM emp ORDER BY deptno,sal;—查询所有员工信息,先按部门升序,再按工资升序
SELECT * FROM emp ORDER BY deptno desc,sal;—查询所有员工信息,先部门降序,再工资升序
b.说明:ORDER BY a,b —a,b都是升序
ORDER BY a ,b DESC —a升序,b降序
ORDER BY a DESC,b —a降序,b升序
ORDER BY a DESC,b DESC —a降序,b降序
asc是升序,默认可以不写,desc是降序
为一个字段指定的排序标准并不会对另一个字段产生影响
强烈建议为每一个字段指定排序的标准6.8.8 模糊查询【某个字段中含某个字符,搜索时使用】
a. 格式:SELECT 字段的集合 FROM 表名 WHERE 某个字段的名字 LIKE 匹配的条件
b. 事例:SELECT FROM emp WHERE ename LIKE ‘%A%’;—查询名字中含有字母A的所有的员工的信息
SELECT FROM emp WHERE ename LIKE ‘A%’;—查询名字中首字母是A的所有的员工的信息
SELECT FROM emp WHERE ename LIKE ‘%S’;—查询名字中尾字母是S的所有的员工的信息
SELECT FROM emp WHERE ename LIKE ‘A%’;—查询名字中第二个字母是A的所有员工信息
SELECT * FROM emp WHERE ename LIKE ‘[A-C]%’;—名字中第二个字母是A或B或C的员工信息
SELECT FROM emp WHERE ename LIKE ‘_[^A-B]%’;—名字第二个字母不是A也不是B的员工信息
SELECT FROM emp WHERE ename LIKE ‘%\%%’ ESCAPE ‘\’;—查询名字中含有符号%的员工信息
SELECT * FROM emp WHERE ename LIKE ‘%_%’ ESCAPE ‘\’;—查询名字中含有符号的员工信息
c. 说明:匹配的条件通常含有通配符
匹配的条件必须用单引号括起来,不能省略,也不能用双引号
通配符:% —表示任意0个或多个字符
—表示任意单个字符
[a-f] —a到f中的任意单个字符
[a,f] —a或f中的任意单个字符
[^a-c] —不是a、b、c中的任意单个字符
其他符号:与(&)、非(~)、或(|)、异或(^)、转义字符()6.8.9 聚合函数【多行记录返回一个值,结合分组使用,不分组默认整体】
a. 函数分类:单行函数:每一行返回一个值,比如LOWER()是单行函数
多行函数:多行返回一个值,比如MAX()是多行函数(聚合函数属于多行函数)
b. 聚合函数分类:MAX() —最大值
MIN() —最小值
AVG() —平均值
COUNT() —求个数
c. 事例:SELECT LOWER(ename) AS “小写姓名” FROM emp;—将员工名称字母转换成小写的并查询
SELECT UPPER(ename) AS “大写姓名” FROM emp;—将员工名称字母转换成大写的并查询
SELECT MAX(sal) AS “最多工资” FROM emp;—查询员工表中的最多工资
SELECT COUNT() AS “个数” FROM emp;—查询员工信息表中的所有记录的个数,返回值是14
SELECT COUNT(deptno) AS “部门个数” FROM emp;—查询员工信息表中的部门个数,返回值是14
SELECT COUNT(DISTINCT deptno) FROM emp;—查询员工信息表中的不同的部门个数,返回值是3
SELECT COUNT(comm) FROM emp;—查询员工奖金的个数,返回值是4,NULL值不会被统计
SELECT MAX(sal) AS “最高工资”,MIN(sal) AS “最低工资”,COUNT() AS “员工数” FROM emp;
d. 说明:COUNT(*) —返回表中所有记录的个数
COUNT(字段名) —返回字段值非空的记录的个数,重复的记录也会被当做有效数据统计
COUNT(DISTINCT 字段名) —返回字段不重复并且非空的记录的个数
单行函数和多行函数不能混用6.8.10 group by【对表中记录按字段分组】
a. 格式:GROUP BY 字段的集合
b. 事例:SELECT deptno, AVG(sal) AS “平均工资” FROM emp GROUP BY deptno;—查询部门及其平均工资
SELECT deptno, job, AVG(sal) AS “平均工资” FROM emp GROUP BY deptno, job ORDER BY deptno;
—查询部门职业的平均工资,按部门分组
c. 说明:使用了GROUP BY,则SELECT中只能出现分组后的整体信息,不能出现组内的详细信息
GROUP BY a, b, c—先按a分组,若a相同按b分组,若b相同再按c分组,最终统计最小分组的信息6.8.11 having【对分组后的信息进行过滤】
a. 事例:SELECT deptno, AVG(sal) AS “平均工资”
FROM emp
GROUP BY deptno
HAVING AVG(sal) > 2000;
—查询部门平均工资大于2000的部门编号及部门平均工资
SELECT deptno, AVG(sal) AS “平均工资”
FROM emp
WHERE ename NOT LIKE ‘&A%’
GROUP BY deptno
HAVING AVG(sal) > 2000;
—查询名字中不包含字母A的人员部门且部门平均工资大于2000的部门编号及平均工资
SELECT deptno, AVG(sal) AS “平均工资”, COUNT(*) AS “部门人数”
FROM emp
WHERE sal > 1000
GROUP BY deptno
HAVING AVG(sal) > 2000;
—查询工资大于1000且平均工资大约2000的部门编号,部门平均工资和部门人数
b. 说明:SELECT语句基本结构包含8个子句,且这些子句的顺序是固定的,否则编译时出错
- SELECT语句基本结构:SELECT TOP 数字 字段名
INTO 表C —将查询结果定义到一个新表
FROM 表A
JOIN 表B
ON A、B表连接条件
WHERE 条件
GROUP BY 分组
HAVING 分组后过滤
ORDER BY 分组后排序
1. WHERE和HAVING都是对数据过滤,只保留有效的数据,且子句中都不允许出现别名1. WHERE是对原始的记录过滤,HAVING是对分组后的记录过滤,且WHERE必须放到HAVING前边1. HAVING子句是用来对分组之后的数据进行过滤,因此使用HAVING时通常先使用GROUP BY子句1. 若果没使用GROUP BY子句,但使用了HAVING,意味着HAVING把所有的记录当成一组进行过滤1. HAVING子句出现的字段必须是分组之后组内的整体信息,不能是组内的详细信息1. 尽管SELECT子句中可以出现别名,但是HAVING子句中不能出现,只能使用原始的字段名称
6.8.12 连接查询
6.8.12.1 定义:
将两个或两个以上的表按一定条件连接起来,从中检索出满足条件的数据
6.8.12.2 分类:
6.8.12.2.1 内连接【重难点】
1. SELECT ··· FROM A, B 的用法1. 事例:SELECT * FROM emp, dept;--查询员工和部门表的所有字段1. 说明:emp是14行8列,dept是5行3列,查询结果是70(14*5)行11(8+3)列(笛卡尔积)2. SELECT ··· FROM A, B WHERE ··· 的用法1. 事例:SELECT * FROM emp, dept WHERE empno = 7369;--查询员工编号是7369的所有信息1. 说明:查询结果是5行11列3. SELECT ··· FROM A JOIN B ON ··· 的用法1. 事例:SELECT "E".ename AS "员工姓名", "D".dname AS "部门名称"
FROM emp “E”
JOIN dept “D” —JOIN是连接
ON “E”.deptno = “D”.deptno; —ON是连接条件
—查询员工表中的员工姓名和部门表中的部门名称
2.说明:查询结果是14行2列。JOIN必须和ON配套使用,有JOIN必要有ON
iv.SELECT ··· FROM A, B WHERE ··· 与 SELECT ··· FROM A JOIN B ON ··· 的比较
1. 事例:SELECT * FROM emp, dept WHERE emp.deptno = dept.deptno;等价于
SELECT * FROM emp JOIN dept ON emp.deptno = dept.deptno;—查询结果14行11列
—查询工资大于2000的员工姓名和部门的名称
SQL92实现方式 SQL99实现方式
SELECT “E”.ename, “D”.dname SELECT “E”.ename, “D”.dname
FROM emp “E”,dept “D” FROM emp “E”
WHERE “E”.sal > 2000 JOIN dept “D”
AND “E”.deptno = “D”.deptno; ON “E”.deptno = “D”.deptno
WHERE “E”.sal > 2000;
2.说明:第一个是SQL92标准,第二个是SQL99标准,推荐使用SQL99标准。 因为ON和WHERE可以做不同分工,ON指定连接条件, WHERE对连接之后的临时表的数据进行分析。
v. SELECT、FROM、WHERE、JOIN、ON、GROUP BY、ORDER BY、TOP、HAVING的混合使用
1. 事例:--把工资大约1500的所有员工,按部门分组,把部门平均工资大于2000的前2个部门的部门编号、部门名称、部门平均工资的等级输出,按等级降序排序
SELECT “T”.*, “S”.grade
FROM(
SELECT TOP 2 “E”.deptno, “D”.dname, AVG(“E”.sal) AS “avg_sal”
FROM emp “E”
JOIN dept “D”
ON “E”.deptno = “D”.deptno
JOIN salgrade “S”
ON “E”.sal BETWEEN “S”.losal AND “S”.hisal
WHERE “E”.sal > 1500
GROUP BY “E”.deptno, “D”.dname
HAVING AVG(“E”.sal) > 2000
ORDER BY AVG(“E”.sal) DESC
) “T”
JOIN salgrade “S”
ON “T”.”avg_sal” BETWEEN “S”.losal AND “S”.hisal;
等价于:
SELECT “T”.deptno, “D”.dname, “T”.”avg_sal”, “S”.grade
FROM dept “D”
JOIN (
SELECT TOP 2 deptno, AVG(sal) AS “avg_sal”
FROM emp
WHERE sal > 1500
GROUP BY deptno
HAVING AVG(sal) > 2000
ORDER BY “avg_sal” DESC
) “T”
ON “D”.deptno= “T”.deptno
JOIN salgrade “S”
ON “T”.”avg_sal” BETWEEN “S”.losal AND “S”.hisal;
vi. 习题:
1. --求出工资比2000大的每个部门的员工姓名、部门名称、薪水和薪水的等级
SELECT “E”.ename, “D”.dname, “E”.sal, “S”.grade
FROM emp “E”
JOIN dept “D”
ON “E”.deptno = “D”.deptno
JOIN salgrade “S”
ON “E”.sal >= “S”.losal AND “E”.sal <= “S”.hisal;
2.—求出每个员工的姓名,部门编号,薪水和薪水登记
SELECT “E”.ename, “E”.deptno, “E”.sal, “S”.grade
FROM emp “E”
JOIN salgrade “S”
ON “E”.sal >= “S”.losal AND “E”.sal <= “S”.hisal;
等价于
SELECT emp.ename, emp.deptno, emp.sal, salgrade.grade
FROM emp
JOIN salgrade
ON emp.sal BETWEEN salgrade.losal AND salgrade.hisal;
3.—查找每个部门的部门编号,该部门所有员工的平均工资及平均工资等级
SELECT “T”.deptno, “T”.avg_sal, “S”.grade
FROM (
SELECT deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
) “T”
JOIN salgrade “S”
ON “T”.avg_sal BETWEEN “S”.losal AND “S”.hisal;
—等价于
SELECT “T”., “S”.grade
FROM salgrade “S”
JOIN (
SELECT deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
) “T”
ON “T”.avg_sal BETWEEN “S”.losal AND “S”.hisal;
—等价于
SELECT “T”.deptno, “T”.avg_sal, “S”.grade
FROM salgrade “S”, (
SELECT deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
) “T”
WHERE “T”.avg_sal BETWEEN “S”.losal AND “S”.hisal;
4.—查找每个部门的编号,部门名称,该部门所有员工的平均工资及平均工资等级
SELECT “T”.deptno, “D”.dname, “T”.avg_sal, “S”.grade
FROM (
SELECT deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
) “T”
JOIN salgrade “S”
ON “T”.avg_sal BETWEEN “S”.losal AND “S”.hisal
JOIN dept “D”
ON “T”.deptno = “D”.deptno;
5.—查出emp表中所有领导的所有信息
SELECT FROM emp
WHERE empno IN (SELECT mgr FROM emp);—6行
6.—查出emp表中所有非领导的所有信息
SELECT FROM emp
WHERE empno NOT IN (SELECT mgr FROM emp);—error(mgr中有NULL)
SELECT FROM emp
WHERE empno NOT IN (SELECT mgr FROM emp WHERE mgr IS NOT NULL);—8行
7.—求出平均薪水最高的部门的编号和部门的平均工资
SELECT TOP 1 deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
ORDER BY AVG(sal) DESC;
—等价于
SELECT “E”.
FROM(
SELECT deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
) “E”
WHERE “E”.”avg_sal” =
(
SELECT MAX(“avg_sal” )
FROM (
SELECT deptno, AVG(sal) AS “avg_sal”
FROM emp
GROUP BY deptno
) “T”
);
8.—把工资最低员工排除后工资最低的前三人的姓名、工资、部门编号、部门名称、工资等级
SELECT TOP 3 “T”.ename, “T”.sal, “T”.deptno, “D”.dname, “S”.grade
FROM(
SELECT
FROM emp “E”
WHERE sal > (SELECT MIN(sal) FROM emp)
) “T”
JOIN dept “D”
ON “T”.deptno = “D”.deptno
JOIN salgrade “S”
ON “T”.sal BETWEEN “S”.losal AND “S”.hisal
ORDER BY “T”.sal ASC;
—等价于
SELECT TOP 3 “E”.ename, “E”.sal, “E”.deptno, “D”.dname, “S”.grade
FROM emp “E”
JOIN dept “D”
ON “E”.deptno = “D”.deptno
JOIN salgrade “S”
ON “E”.sal BETWEEN “S”.losal AND “S”.hisal
WHERE “E”.sal <> (SELECT MIN(sal) FROM emp)
ORDER BY “E”.sal ASC;
9.—输出姓名名称中不包含字母A的工资最高的前三名的员工的姓名,工资,工资等级和部门名称
SELECT TOP 3 “E”.ename, “E”.sal, “S”.grade, “D”.dname
FROM emp “E”
JOIN dept “D”
ON “E”.deptno = “D”.deptno
JOIN salgrade “S”
ON “E”.sal BETWEEN “S”.losal AND “S”.hisal
WHERE “E”.ename NOT LIKE ‘%A%’
ORDER BY “E”.sal DESC;
—等价于
SELECT TOP 3 T0.ename, T0.sal, T1.grade, T2.dname
FROM emp T0
JOIN salgrade T1
ON T0.sal BETWEEN T1.losal AND T1.hisal
JOIN dept T2
ON T0.deptno = T2.deptno
WHERE T0.ename NOT LIKE ‘%A%’
ORDER BY sal DESC;
6.8.12.2.2 外连接
1. 格式:LEFT JOIN、RIGHT JOIN
6.8.12.2.3 完全连接
1. 格式:FULL JOIN
6.8.12.2.4 交叉连接
1. 格式:CROSS JOIN
6.8.12.2.5 自连接
1. 定义:一张表自己和自己连接起来查询数据1. 事例:--求薪水最高的员工信息
—自连接查询
SELECT FROM emp
WHERE empno NOT IN (
SELECT DISTINCT T0.empno
FROM emp T0, emp T1
WHERE T0.sal < T1.sal
);
—嵌套查询
SELECT FROM emp
WHERE sal =(
SELECT TOP 1 sal
FROM emp
ORDER BY sal DESC
);
—聚合函数查询
SELECT * FROM emp WHERE sal = (SELECT MAX(sal) FROM emp);
6.8.12.2.6 联合【UNION】
1. 定义:表和表之间的数据以纵向的方式连接在一起1. 事例:--输出每个员工的姓名,工资和上司的姓名
SELECT “E1”.ename, “E1”.sal, “E2”.ename AS “上司的姓名”
FROM emp “E1”
JOIN emp “E2”
ON “E1”.mgr = “E2”.empno
UNION
SELECT ename, sal, ‘已是最大BOSS’
FROM emp
WHERE mgr IS NULL
UNION
SELECT ename, sal, ‘未找到上司姓名’
FROM emp
WHERE mgr NOT IN (SELECT empno FROM emp);
iii. 说明:之前讲的连接都是横向连接,UNION联合是纵向连接
若干个SELECT子句要联合成功的话,需要满足两个条件:
1. 若干个SELECT子句输出的数据列数必须是相同的1. 若干个SELECT子句输出的数据类型应该是兼容的
6.8.13 嵌套查询(oracle中讲)
6.8.14 分页查询
事例:—输出工资最高的前三个员工的所有信息
SELECT TOP 3 FROM emp ORDER BY sal;—先执行ORDER BY ,再执行TOP
—工资从高到底排序,输出工资是低4-6的员工的信息
SELECT TOP 3 FROM emp
WHERE empno NOT IN (SELECT TOP 3 empno FROM emp ORDER BY sal DESC)
ORDER BY sal DESC;
—工资从高到底排序,输 出工资是低7-9的员工的信息
SELECT TOP 3 FROM emp
WHERE empno NOT IN (SELECT TOP 6 empno FROM emp ORDER BY sal DESC)
ORDER BY sal DESC;
—工资从高到底排序,输出工资是低10-12的员工的信息
SELECT TOP 3 FROM emp
WHERE empno NOT IN (SELECT TOP 9 empno FROM emp ORDER BY sal DESC)
ORDER BY sal DESC;
—工资从高到底排序,输出工资是低13-15的员工的信息
SELECT TOP 3 * FROM emp
WHERE empno NOT IN (SELECT TOP 12 empno FROM emp ORDER BY sal DESC)
ORDER BY sal DESC;总结:—假设每页显示n条记录,当前要显示的是第m页,表名是A,主键是A_id
SELECT TOP n FROM A
WHERE A_id NOT IN (SELECT TOP (m-1)n A_id FROM emp);6.9 视图
6.9.1 为什么需要视图
简化查询,避免代码的冗余(避免书写重复的SQL语句)
6.9.2 什么是视图
视图从代码看是一个SELECT语句,从逻辑上看被当做一个虚拟表
6.9.3 视图的格式格式:CREATE VIEW v$_视图名称 AS SELECT 语句
说明:SELECT 语句的前面不能添加BEGIN,SELECT 语句的后面不能添
6.9.4 视图的优点
简化查询,争取数据的保密性
6.9.5 视图的缺点
增加了数据库维护的成本,简化了查询
不能加快查询的速度
6.10 事务
定义:一系列操作,要不全部执行成功,要么全部执行失败
- 特征:原子性、一致性、隔离性、持久性
- 事务是用来研究什么的:避免数据处于不合理的中间地带、转账
- 事务和线程关系:事务也是通过锁来解决很多问题的,线程同步就是通过锁来解决问题的
- 事务和第三方的关系:直接使用事务库的难度很大,一般是借用第三方的插件实现的
