DDL 数据定义语言
DDL是对数据库对象进行操作的语言
数据库对象包括:表、视图、索引、序列
CREATE TABLE employee(
id NUMBER(4),
name VARCHAR2(20),
gender CHAR(1),
salary NUMBER(6,2),
job VARCHAR2(30),
deptno NUMBER(2)
)
查看表结构
DESC employee
删除表
DROP TABLE employee
数据库中的所有数据类型的默认值都是NULL,在创建表的时候可以使用DEFAULT为某个字段单独指定一个默认值
数据库中的字符串字面量是使用单引号的,虽然SQL语句本身不区分大小写,但是字符串的值区分大小写的!
CREATE TABLE employee(
id NUMBER(4),
name VARCHAR(20) NOT NULL,
gender CHAR(1)DEFAULT 'M',
birth DATE,
salary NUMBER(6,2),
job VARCHAR(30),
deptno NUMBER(2)
)
修改表
1:修改表名
2:修改表结构
修改表名:
RENAME employee TO myemp
DESC myemp
修改表结构
1:添加新的字段
2:修改现有字段
3:删除现有字段
增加字段
ALTER TABLE myemp
ADD(
hiredate DATE DEFAULT SYSDAT
)
DESC myemp
删除字段
ALTER TABLE myemp
DROP(hiredate)
修改字段
可以修改字段的类型,长度,默认值,是否非空
修改表结构都应当避免在表中有数据以后进行
若表中有数据,修改表中字段时尽量不要修改类型,
若修改长度尽量增大避免减小,否则可能导致失败
ALTER TABLE myemp
MODIFY(
job VARCHAR2(40) DEFAULT 'CLERK'
)
DESC myemp
DML语句
DML是对表中的数据进行的操作
DML伴随事物控制(TCL)
DML包含操作:
增、删、改
INSERT INTO myemp
(id, name, salary, deptno)
VALUES
(1, 'jack', 5000, 10)
SELECT * FROM myemp //查找表
提交可以按按钮
或者写COMMIT
INSERT INTO myemp
(id, name, job, birth )
VALUES
(1003, 'donna', 'MANAGER',
TO_DATE('2009-09-01', 'YYYY-MM-DD')
)
UPDATE语句
修改表中数据
修改表中要使用的WHERE添加过滤条件
这样才会只将满足条件的记录进行修改,否则是全表所有数据都修改
UPDATE myemp
SET salary=6000,gender='F', name='rose'
WHERE id=1
DELETE语句
删除表中数据,删除数据通常也要添加WHERE语句来限定要删除数据的条件
否则就是清空表操作!
DELETE FROM myemp
WHERE name='rose'
课后作业:
8.
CREATE TABLE Account(
ID NUMBER(9) NOT NULL,
RECOMMENDER NUMBER(9),
LOGIN_NAME VARCHAR2(30) NOT NULL,
LOGIN_PASSWD VARCHAR2(8) NOT NULL,
STATUS CHAR(1) NOT NULL,
CREATE_DATE DATE DEFAULT SYSTEM,
PAUSE_DATE DATE,
CLOSE_DATE DATE,
REAL_NAME VARCHAR2(20) NOT NULL,
IDCARD_NO CHAR(18) NOT NULL,
BIRTHDAY DATE,
GENDER CAHR(1) NOT NULL,
OCCUPATION VARCAHR2(50),
TELEFHONE VARCHAR2(15),
EMAIL VARCHAR2(50),
MAILADDRESS VARCHAR2(50),
ZIPCODE CHAR(6),
QQ VARCHAR2(15),
LAST_LOGIN_TIME Date,
LAST_LOGIN_IP VARCHAR2(15)
)
9.
1)
RENAME Account TO t_account
2)
ALTER TABLE t_account
ADD(
bak VARCHAR2(50)
)
3)
ALTER TABLE t_account
MODIFY(
bak VARCHAR2(40) DEFAULT 'login'
)
4)
ALTER TABLE t_account
DROP(bak)
10.
INSERT INTO t_account
(ID,LOGIN_N,LOGIN_PASSWD,CREATE_DATE,REAL_NAME,IDCADE_NO,TELEPHONE)
VALUE
(1,'shiyl',256528,'2018-1-28','shiyuanli',410381194302236523,136669351234)
11.
UPDATE t_account
SET LOGIN_PASSWD=801206
WHERE ID=1
12.
DELETE FROM t_account
WHERE ID=1
13.
CREATE TABLE emp(
empno NUMBER(4,0),
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4,0),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2,0)
)
CREATE TABLE dept(
deptno NUMBER(2,0),
dname VARCHAR2(14 BYTE),
loc VARCHAR2(13 BYTE)
)
14.
INSERT INTO emp
(empno,ename,job,mgr,hiredate,sal,comm.deptno)
VALUE
(7369,'SMITH','CLEAK',7902,TO_DATE('1980-12-17', 'YYYY-MM-DD'))
day02
SELECT语句
用于查询表中的数据
SELECT字句后面跟的是要查询的字段,可以包括表中的具体字段,函数或者表达式
FROM字句用来指定数据来源的表
WHERE字句用来添加过滤条件,这样做的结果是只将满足条件的记录查询出来
SELECT字句中使用表达式
查看每个员工的年薪?
SELECT ename,sal*12
FROM emp
字符串函数
CONCAT()函数,用来连接字符串
SELECT CONCAT(ename,sal)
FROM emp
在两个字段之间加上逗号
SELECT CONCAT(CONCAT(ename, ','), sal)
FROM emp
实现这个拼接有一个简单的方法,用||相当于加号
SELECT ename || ',' || sal
FROM emp
LENGTH函数,查看字符串长度
SELECT ename,LENGTH(ename)
FROM emp
UPPER, LOWER, INITCAP
将字符串转换成全大写,全小写以及首字母大写
对于INITCAP而言,可以使用空格隔开多个单词,那么每个单词首字母都会大写
伪表:dual
当查询的内容不和表中的任何数据有关系,可以使用伪表,伪表只会查询出一条记录
SELECT UPPER('helloworld')
LOWER('HELLOWORLD')
INITCAP('HELLO WORLD')
FROM dual
TRIM,LTRIM,RTRIM
TRIM去除当前字符串中两边的指定重复字符,LTRIM仅去除左侧的,RTRIM则仅去除右侧的
SELECT TRIM('e' FROM 'eeeliteeee')
FROM dual
SELECT LTRIM('eeeeliteeee' , 'e')
FROM dual
SELECT LTRIM('esrrersrrliteeeee' 'res')
FROM dual
LPAD,RPAD补位函数
SELECT LPAD(sal, 5, '$')//$$sal
FROM emp
SELECT RPAD(sal, 5, '$')//sal$$
FROM emp
SUBSTR截取字符串
数据库中的下标都是从1开始的
第三个参数不指定则是截取到末尾,指定的长度若超过实际可以截取的内容也是截取到末尾
第二个参数可以是负数,表示从右到左开始数,但第三个参数不可以是负数
SELECT
SUBSTR('thinking in java', 13, 4 )
FROM dual
INSTR(char1, char2,[n, m])函数
查找char2在char1中的位置
n为从第几个字符开始检索
m为第几次出现
n,m不写则默认都是1
SELECT
INSTR('thinking in java', 'in', 4,1)
FROM dual
数值函数
ROUND(n, m)四舍五入
SELECT ROUND(45.68, 2) FROM dual 45.68
SELECT ROUND(45.678, 0) FROM dual 46
SELECT ROUND(55.678, -1) FROM dual 60
TRUNC(n, m)截取数字(易混)
SELECT TRUNC(45.678, 2) FROM dual 45.67
SELECT TRUNC(45.678, 0) FROM dual 45
SELECT TRUNC(45.678, -1) FROM dual 40
SELECT TRUNC(45.678, -2) FROM dual 0
MOD(m, n)求余数
SELECT ename,sal, MOD(sal, 1000)
FROM emp
CEIL, FLOOR
向上取整和向下取整
SELECT CEIL(45.678) FROM DUAL//46
SELECT FLOOR(45.678) FROM DUAL//45
SELECT CEIL(45) FROM DUAL//45
SELECT CEIL(45) FROM DUAL//45
SELECT CEIL(-45.1) FROM DUAL//-45
SELECT CEIL(-45.1) FROM DUAL//-46
查看scott员工的信息?
SELECT ename, sal, deptno
FROM emp
WHERE ename=UPPER('scott')
SYSDATE, SYSTIMESTAMP
SYSDATE对应数据库一个内部函数,该函数返回一个表示当前系统时间的DATE类型值
SYSTIMESTAMP返回的是一个表示当前系统时间的时间戳类型的值
SELECT SYSDATE FROM dual
SELECT SYSTIMESTAMP FROM dual
TO_DATE函数
可以将字符串按照给定的日期格式解析为一个DATE类型的值
SELECT
TO_DATE('2008-08-08 20:08:08', 'YYYY-MM-DD HH24:MI:SS')
FROM
dual
在日期格式字符串中凡不是英文,符号,数字的其他字符,都需要使用双引号括起来
SELECT
TO_DATE('2008年08月08日 20:08:08', 'YYYY"年"MM"月"DD"日" HH24:MI:SS')
FROM
dual
日期的计算
日期可以与一个数字进行加减法,这相当于加减指定的天
两个日期可以进行减法,差为相差的天
SELECT SYSDATE-hiredate
FROM emp
输入自己生日:1992-08-02
查看到今天为止活了多少天?
SELECE SYSDATE- TO_DATE('1992-08-02', 'YYYY-MM-DD')
FROM dual
TO_CHAR():可以将DATE按照给定的格式转换为字符串
SELECT
TO_CHAR(SYSDATE,'2008-08-08 08:08:20')
FROM
dual
SELECT
TO_CHAR(
TO_DATE('2008-08-08', 'RR-MM-DD'),
'YYYY-MM-DD'
)
FROM dual
ADD_MONTHS(date,i)
对给定日期加上指定的月,若i为负数则是减去
查看每个员工入职20周年纪念日
SELECT
ename,ADD_MONTNS(hiredate,12*20)
FROM
emp
计算两个日期之间相差的月,计算是根据date1-date2得到的
查看每个员工至今入职多少个月了?
SELECT
ename,MONTHS_BETWEEN(SYSDATE,hiredate)
FROM
Emp
NEXT _DAY(date,i)
返回给定日期的第二天开始一周
之内的指定周几的日期
i:1表示周日,2表示周一,以此类推
SELECT NEXT_ DAY(SYSDATE,7)
FROM dual
LEAST,GREATEST
求最小值与最大值,除了
日期外,常用的数字也可以比较大小
SELECT
LEAST(SYSDATE ,TO_ DATE('2008-08-05’,‘YYYY-MM-DD'))
FROM dual
EXTRACT()提取给定日期中指定
时间分量的值
SELECT EXTRACT(YEAR FROM SYSDATE)
FROM dual
查看1980年入职的员工
SELECT ename,hiredate FROM emp
WHERE EXTRACT(YEAR FROM hiredatep)=1980
空值函数
NVL(argl,arg2)
当arg1为NULL,函数返回arg2的值若不为NUL,则返回arg1本身
所以该函数的作用是将NULL值替换为一个非NULL值.
查看每个人的绩效情况,即:
有绩效的,显示为"有绩效"
绩效为NULL的,则显示为"没有绩效"
NVL2(argl,arg2,arg3)
当arg1不为NULL,则函数返回arg2当arg1为NULL,则函数返回arg3
该函数是根据一个值是否为NULL来返回两个不同结果.
DQL查询语句
SELECT子句中可以使用函数或表达式
那么结果集中对应的该字段名就是这个
函数或表达式,可读性差,为此可以为这样
的字段添加别名,那么结果集会以这个别名
作为该字段的名字。
别名本身不区分大小写,而且不能含有空格.
若希望别名区分大小写或含有空格,那么可以
在别名上使用双引号括起来.
AND的优先级高于OR,可以通过括号
来提高OR的优先级
SELECT ename,sal*12 xxx
FROM emp
LIKE用于模糊匹配字符串,支持两个
通配符:
_:单一的一个字符
%:任意个字符
查看名字第二个字母是A最后一个字母是N的?
SELECT ename
FROM emp
WHERE ename LIKE ‘_A%N’
IN和NOT IN
判断是否在列表中或不在列表中
SELECT ename,job FROM emp
WHERE job IN('MANAGER','CLERK');
SELECT ename,job FROM emp
WHERE deptno NOT IN(10,20);
IN和NOT IN常用来判断子查询的结果
BETWEEN...AND…
判断在一个区间范围内
工资在1500到3000之间的员工
SELECT ename,sal
FROM emp
WHERE Sal BETWEEN 1500 AND 3000
ANY和ALL是配合>,>=,<,<=一个列表使用的.
ANY(list):大于列表中最小的
>ALL(list):大于列表中最大的
<ANY(list):小于列表中最大的
<ALL(list):小于列表中最小的
ANY和ALL常用于子查询.
使用函数或者表达式最为过滤条件
SELECT ename,sal,job
FROM emp
WHERE ename = UPPER('scott');
SELECT ename,sal,job
FROM emp
WHERE sal*12 >100000;
DISTINCT关键子
对结果集中指定字段值重复的记录进行去重
查看公司有哪些职位?
SELECT DISTINCT job
FROM emp
多字段去重,是对这些字段值的组合进行去重
SELECT DISTINCT job,deptno
FROM enp
排序
ORDER BY子句
ORDER BY可以根据其后指定的
字段对结果集按照该字段的值进行
升序或者降序排列.
ASC:升序,不写默认就是升序
DESC:降序.
查看公司的工资排名:
SELECT ename,sal
FROM emp
ORDER BY sal DESC
ORDER BY按照多个字段排序
ORDER BY首先按照第一个字段的排序
方式对结果集进行排序,当第一个字段
有重复值时才会按照第二个字段排序
方式进行排序,以此类推.每个字段都可以
单独指定排序方式
SELECT ename, deptno, sal
FROM emp
ORDER BY deptno DESC, sal DESC
排序的字段中含有NULL值,NULL被认作最大值.
SELECT ename,comm
FROM emp
ORDER BY comm DESC
聚合函数
聚合函数也叫多行函数,分组函数
聚合函数是对结果集某些字段的值进行统计的
MAX,MIN
求给定字段的最大值与最小值
查看公司的最高工资与最低工资是多少?
SELECT MAX(sal),MIN(sal)
FROM emp
AVG和SUM
求平均值和总和
SELECT AVG(sal),SUM(sal)
FROM emp
COUNT函数
COUNT函数不是对给定的字段的值进行
统计的,而是对给定字段不为NULL的记录
数统计的.
实际上所有聚合函数都忽略NULL值统计.
SELECT COUNT(ename)
FROM emp
通常查看表的记录数可以使用COUNT(*)
SELECT COUNT(*)FROM emp
查看平均绩效
SELECT AVG(NVL(comm,0)),SUM(comm)
FROM emp
分组
GROUP BY子句
GROUP BY可以将结果集按照其后指定
的字段值相同的记录看做一组,然后配合
聚合函数进行更细分的统计工作.
查看每个部门的平均工资?
SELECT AVG(sal),deptno
FROM emp
GROUP BY deptno
GROUP BY也可以根据多个字段分组
分组原则为这几个字段值都相同的记录看做一组
查看同部门同职位的平均工资?
SELECT AVG(sal),job,deptno
FROM emp
GROUP BY job,deptno
当SELECT子句中含有聚合函数时,那么凡不在聚合函数中的其他单独字 段都必须出现
GROUP BY子句中,反过来则不是必须的.
查看部门的平均工资,前提是该部门的平均
工资高于2000
WHERE中不能使用影合函数作为过滤
条件,原因是过滤时机不对
WHERE是在数据库检索表中数据时,对
数据逐条过滤以决定是否查询出该数据
时使用的,所以WHERE用来确定结果集
的数据.
使用聚合函数的结果作为过滤条件,那么
一定是数据从表中查询完毕(WHERE在查询过程中发挥作用)得到结果集, 并且分组完毕才进行聚合函数统计结果,得到后才可以对
分组进行过滤,由此可见,这个过滤时机是在
WHERE之后进行的.
聚合函数的过滤条件要在HAVING子句中使用
HAVING必须跟在GROUP BY子句之后.HAVING
是用来过滤分组的.
SELECT AVG (sal), deptno
FROM emp
GROUP BY deptno
HAVING AVG (sal)>2000
查看平均工资高于2000的部门的
最高工资和最低工资分别是多少?
SELECT MAX(sal),MIN(sal),deptno
FROM emp
GROUP BY deptno
HAVING AVG(sal)>2000
查询语句执行顺序
查询语句的执行顺序依下列子句次序
1.from子句:执行顺序为从后往前、从右到左
.数据量较少的表尽量放在后面
2.where子句:执行顺序为自下而上、从右到左
.将能过滤掉最大数量记录的条件写在Where子句的最右
3.group by-执行顺序从左往右分组
最好在GROUP BY前使用WHERE将不需要的记录在GROUP BY之前过滤 掉
4.having子句:消耗资源
.尽量避免使用,HAVING会在检索出所有记录之后才对结果集进行过滤,需要排序等操作
5.select子句:少用*号,尽量取字段名称。
.ORACLE在解析的过程中,通过查询数据字典将*号依次转换成所有的列名,消耗时间
6.order by子句:执行顺序为从左到右排序,消耗资源
关联查询
从多张表中查询对应记录的信息
关联查询的重点在于这些表中的记录
的对应关系,这个关系也称为连接条件
查看每个员工的名字以及其所在部门的名字?
SELECT ename,dname
FROM emp,dept
WHERE emp.deptno=dept.deptno
用别名代替表名
SELECT e. ename,d. dname, e. deptno
FROM emp e, dept d
WHERE e. deptno-d. deptno
当两张表有同名字段时,SELECT子句中
必须明确指定该字段来自哪张表.在关联
查询中,表名也可以添加别名,这样可以简化
SELECT语句的复杂度
关联查询要添加连接条件,否则会产生笛卡尔积笛卡尔积通常是一个无意 义的结果集,它的记录数是所有参与查询的表的记录数乘积的结果。要避免 出现,数据量大时极易出现内存溢出等现象。N张表关联查询要有至少N-1 个连接条件。
SELECT e.ename,d.dname,e.deptno
FROM emp e,dept d
查看在NEW YORK工作的员工?
SELECT e.ename,d.deptno
FROM emp e,dept d
WHERE e.deptno-d.deptno
AND d.loc='NEW YORK
查看工资高于3000的员工的名字
工资,部门名以及所在地?
SELECT e. ename, e. sal d. dname, d. loc
FROM emp e, dept d
WHERE e. deptno=d. deptno AND e. sal>3000
SELECT e. ename, d. dname
FROM emp e JOIN dept d
ON e. deptno=d. deptno
JOIN XXXX X
ON d. XXX=X. XXX
WEERE d. dname=‘SALES’
查看SALES部门的员工名字以及部门的名字
SELECT e.ename,d.dname
FROM emp e JOIN dept d
ON e.deptno=d.deptno
WHERE d.dname=‘SALES’
不满足连接条件的记录是不会在关联
查询中被查询出来的.
外链接除了会将满足链接条件的记录查询
出来之外,还会将不满足链接条件的记录也
查询出来.
外链接分为:
左外链接:以JOIN左侧表作为驱动表(所有数据都会被查询出来),那么 当该表中的某条记录不满足链接条件时来自右侧表中的字段全部填NULL.
右外链接:以JOIN右侧表作为驱动表(所有数据都会被查询出来),那么 当该表中的某条记录不满足链接条件时来自左侧表中的字段全部填NULL.
全外链接:左外连接和右外连接的集合
左外链接的简写(右外链接也可以,但全外链接不行) (+)在哪边就补null
SELECT e. ename, d. dname
FROM emp e JOIN dept d
ON e. deptno (+)=d. deptno
自连接
自连接即:当前表的一条记录可以对应当前表自己的多条记录
自连接是为了解决同类型数据但是又存在上下级关系的树状结构数据时使 用.
查看SMITH的上司在哪个城市工作?
SELECT e.ename,m.ename,m.deptno,d.loc
FROM emp e,emp m,dept d
WHERE e.mgr=m.empno
AND m.deptno=d.deptno
AND e.ename='SMITH’
或
select e.ename, m.ename, m.deptno, d.loc
from emp e join emp m
on e.mgr=m.empno
join dept d
on m.deptno=d.deptno
where e.ename='SMITH'
高级查询
子查询
子查询是一条SELECT语句,但它是嵌套在其他SQL语句中的,为的是给该 SQL提供数据以支持其执行操作。
查看谁的1资高于CLARK?
SELECT ename,sal
FROM enp
WEERE sal>(SELECT sal FROM emp
WERE ename='CLARK)
查看谁的工资高于CLARK?
SELECT ename,sal
FROM emp
WEIERE sal>(SELECT sal FROM emp WHERE ename='CLARK')
查看与CLARK同职位的员工?
SELECT ename,job
FROM emp
WERE job=(SELECT job FROM emp WHERE ename='CLARK')
在DDL中使用子查询
可以根据子查询的结果集快速创建一张表
创建表employee,表中字段为:
empno,ename,job,sal,deptno,dname,loc
数据为现有表中emp与dep对应的数据
数据为现有表中emp与dept对应的数据
CREATE TABLE employee
As
SELECT e.empno,e.ename,e.job,e.sal,e.deptno,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno=d.deptno(+)
创建表时若子查询中的字段有别名则该表
对应的字段就使用该别名作为其字段名,
当子查询中一个字段含有函数或表达式,那么
该字段必须给别名.
CREATE TABLE employee
AS
SELECT e. empno id, e. ename name e. job, e. sal*12 salary,
e. deptno, d. dname, d. loc
FROM emp e, dept d
WHERE e. deptno-d. deptno (+)
DML中使用于查询
将CIARK所在部门的所有员工删除
DELETE FROM employee
WHERE deptno=(SELECT deptno
FROM employee
WHIERE name='CLARK')
查找薪水比整个机构平均薪水高的员工
SELECT deptno,ename,sal
FROM emp e
WHERE sal >(SELECT AVG(sal)FROM emp)
子查询根据查询结果集的不同分为:
单行单列子查询:常用于过滤条件,可以配合
=,>,>=,<,<=使用
多行单列子查询:常用于过滤条件,由于查询出多个值,在判断=时要用IN,
判断>,>=等操作要配合ANY,ALL
多行多列子查询:常当做一张表看待.
查询与SALESMAN同部门的其他职位员工:
SELECT ename,job,deptno
FROM emp
WHERE deptno IN(SELECT deptno
FROM emp
WHERE job='SALESMAN’ )
AND job<>'SALESMAN'
查看比职位是CLERK和SALESMAN工资都高的员工?
SELECr ename,sal
FROM emp
WHERE sal> ALL(SELECT sal FROM emp
WHERE job IN('CLERK','SALESMAN')|
EXISTS后面跟一个子查询,当该子查询可以查询出至少一条记录时,则 EXISTS表达式成立并返回 true
Not exists
查看每个部门的最低薪水是多少?前提是该部门的最低薪水要高于30号部 门的最低薪水
SELECT MIN(sal),deptno
FROM emp
GROUP BY deptno
HAVING MIN(sal)>(SELECT MIN(sal)
FROM emp
Where deptno=30)
子查询在FROM子句中的使用
当一个子查询是多列子查询,通常将该子查询的结果集当做一张表看待并 基于它进行二次查询.
查看比自己所在部门平均工资高的员工?
SELECT e. ename, e. sal, e. deptno
FROM emp e, (SELECT AVG (sal) avq_sal, deptno
FROM emp
GROUP BY deptno) t
WERE e. deptno=t. deptno AND e. sal>t. avg_sal
在SELECT子句中使用子查询,可以将查询的结果当做外层查询记录中的 一个字段值显示
SELECT e.ename,e.sal,
(SELECT d.dname FROM dept d WEIERE d.deptno = e.deptno)deptno
FROM emp e
分页查询是将查询表中数据时分段查询,而不
是一次性将所有数据查询出来.有时查询的数据量非常庞大,这会导致系统 资源消耗大,响应速度长,数 据冗余严重.
为此当遇到这种情况时一般使用分页查询解决。数据库基本都支持分页, 但是不同数据库语法不同(方言).
ROWNUM不存在与任何一张表中,但是所有的表都可以查询该字段.该字 段的值是随着查询自动生成的,方式是:每当可以从表中查询出一条记录 时,该字段的值即为该条记录的行号,从1开始逐次递增.
SELECT ROWNUM, empno, ename, sal, job
FROM emp
在使用ROWNM对结果集进行编号的查询过程中不能使用ROWNUM做>1 以上的数字判断,否则将查询不出任何数据.
查工资在6到10名的员工信息
SELECT *
FROM (SELECI ROWNUM rn, empno, ename, sal, job
FROM emp )
WHERE rn BETWEEN 6 AND 10
或者
SELECT *
FROM (SELECT ROWNUM rn,t.*
FROM(SELECT empno, ename, sal
FROM emp
ORDER BY sal DESC) t)
WEERE rn BETWEEN 6 AND 10
SELECT *
FROM (SELECT ROWNUM rn,t.*
FROM (SELECT empno, ename, sal
FROM emp
ORDER BY sal DESC) t
WHERE ROWNUM <=10)
WHERE rn>=6
计算区间公式
pagesize:每页显示的条目数
page:页数
star:(page-1)*pagesize+1
end:pagesize*page
java中这样写:
int start = (page-l) * pagesize+1;
int end =pagesize* page;
string sgl = "SELECT * "+
"FROM (SELECT ROWNUM rn,t.*"+
“ FROM (SELECT empno, ename, sal"+
“ FROM emp t ”+
“ ORDER BY sal DESC) t "+
“ WHERE ROWNUM <="+end+") "+
"WHERE rn>="+start;
DECODE函数,可以实现分之效果的函数
SELECT ename, job, sal,
DECODE (job,
‘MANAGER', sal * 1.2,
' ANALYST', sal * 1.1,
SALESMAN', Sal * 1.01,
sal
) bonus
From emp
DECODE函数基本语法
DECODE(expr,search1,resultl[,search2,result2..][ default])
DECODE用于比较参数expr的值,如果匹配到哪一个
search条件,就返回对应的result结果可以有多组search和result的对应关系, 如果任何一个search条件都没有匹配到,则返回最后default的值
default参数是可选的,如果没有提供default参数值,当没有匹配到时,将返 回NULL.
和DECODE函数功能相似的有CASE语句,实现类似于if-else的操作。
SELECT ename,job,sal,
CASE job WHEN'MANAGER' THEN sal*1.2
WHEN'ANALYST' THEN sal*1.1
WHEN'SALESMAN' THEN sal*1.05
ELSE sal END
bonus
FROM emp;
DECODE在GROUP BY分组中的应用可以将字段值不同的记录看做一组.
统计人数,将职位是"MANAGER","ANALYST"
看作一组,其余职业看作另一组分别统计人数.
SELECT COUNT (*)
DECODE (job,"MANAGER', 'VIP', ANALYST', 'VIP', ’OTHER')
FROM emp
Group by DECODE (job,"MANAGER', 'VIP', ANALYST', 'VIP', ’OTHER')
排序
SELECT deptno, dname, loc
FROM dept
ORDER BY
DECODE (dname,
OPERATIONS",1,
'ACCOUNTING’,2
‘SALES’,3)
排序函数
排序函数允许对结果集按照指定的字段分组
在组内再按照指定的字段排序,最终生成组内
编号.
ROW NUMBER()函数生成组内连续且唯一的数字:查看每个部门的工 资排名?
SELECT
ename, sal, deptno,,
ROW _NUMBER() OVER (
PARTITION BY deptno
ORDER BY sal DESC ) rank
FROM emp
RANK函数,生成组内不连续也不唯一的数字,同组内排序字段值一样的记录,生成的数字也一样.
SELECT
ename, sal, deptno,,
rank() OVER (
PARTITION BY deptno
ORDER BY sal DESC ) rank
FROM emp
DENSE RANK函数生成组内连续但不唯一的数字.
SELECT
ename,sal,deptno,
DENSE _RANK()OVER(
PARTITION BY deptno
ORDER BY sal DESC) rank
From test
集合操作:合并结果集
格式: 结果集1
并 /全并/交/差(union/union all/intersect/minus)
结果集2
查看每天营业额?
select year_id, month_id, day_id, sum(sales_value)
from sales_tab_zx
group by year_id, month_id, day_id
order by year_id, month_id, day_id
查看每月营业额?
select year_id, month_id, sum(sales_value)
from sales_tab_zx
group by year_id, month_id
order by year_id, month_id
查看每年营业额?
select year_id , sum(sales_value)
from sales_tab_zx
group by year_id
order by year_id
查看总营业额?
selectsum(sales_value)
from sales_tab_zx
高级分组函数
高级分组函数用在GROUP BY子句中,每个高级分组函数都有一套分组策略.
ROLLUP():分组原则,参数逐次递减,一直到所有参数都不要,每一种分组都统计一次结果并且并在一个结果集显示.
GROUP BY ROLLUP(a,b,c)
等价于:
GROUP BY a,b,c
UNION ALL
GROUP BY a,b
UNION ALL
GROUP BY a
UNION ALL
全表
查看每天,每月,每年以及总共的营业额?
select year_id, month_id, day_id, sum(sales_value)
from sales_tab_zx
group by rollup(year_id,month_id,day_id)
CUBE():每种组合分一次组
分组次数:2的参数个数次方
GROUP BY CUBE(a,b,c)
abc
ab
bc
ac
a
b
a
全表
select year_id, month_id, day_id, sum(sales_value)
from sales_tab_zx
group by cube(year_id,month_id,day_id)
order by year_id, month_id, day_id
GROUPING SETS:每个参数是一种分组方式,然后将这些分组统计后并在一个结果集显示.
仅查看每天与每月营业额?
select year_id, month_id, day_id, sum(sales_value)
from sales_tab_zx
group by grouping sets((year_id,month_id,day_id),(year_id,month_id))
day05
视图是数据库对象之一
所有数据库对象名字不能重复,所以
视图名字一般是以"v"开头
视图在SQL语句中体现的角色与表相同
但是视图并不是一张真实存在的表,而
只是对应一个SELECT语句的查询结果集,
并将其当做表看待而已.
使用视图的目的是简化SQL语句的复杂度,
重用子查询,限制数据访问.
创建视图
该视图包含的数据为10号部门的员工信息
CREATE VIEW v_ emp_ 10
AS
SELECT empno, ename, sal, deptno
FROM emp
WHERE deptno=10
查看视图数据:
SELECT * FROM V_ emp_ 10
视图对应的子查询中的字段若含有函数
或者表达式,那么该字段必须指定别名.
当视图对应的子查询中的字段使用了别名,
那么视图中该字段就用别名来命名.
修改视图
由于视图仅对应一个SELECT语句,所以修改视图就是替换该SELECT语句而已.
create or replace view v_test_10
as
select empno id, ename name, sal salary, deptno
from test
where deptno=10
select * from v_test_10
desc v_test_10
视图分为简单视图与复杂视图
简单视图:对应的子查询中不含有
关联查询,查询的字段不包含函数,
表达式等,没有分组,没有去重.
反之则是复杂视图.
对视图进行DML操作
仅能对简单视图进行DML操作.
对视图进行DML操作就是对视图数据来源的基础表进行的操作.
插入
INSERT INTO v_test_10
(id,name,salary,deptno)
values
(1001,'jack',2000,10)
select * from v_test_10
select * from test
修改
update v_test_10
set salary=3000
where name='jack'
删除
delete from v_test_10
where name='jack'
对视图的DML操作就是对基表操作,那么
操作不当可能对基表进行数据污染
视图对ROSE不可见(deptno不等于10)
insert into v_test_10
(id,name,salary,deptno)
values(1002,'rose',3000,20)
更新同样存在更新后对数据不可控
的情况
UPDATE V_ enp _10
SET deptno=20
删除不会对基表产生数据污染
delete from v_test_10
where deptno=20
WITH CHECK OPTION
为视图添加检查选项,可以保证对视图
的DML操作后视图对其可见,否则不许
进行该DML操作,这样就避免了对基表
进行数据污染
create or replace view v_test_10
as
select empno id, ename name, sal salary, deptno
from test
where deptno=10
with check option
为视图添加只读选项,那么该视图
不允许进行DML操作.
数据字典(查看创建过的表和视图)
select object_name
from user_objects
where object_type='view'
查看数据库语句
select text
from user_views
查看所有建过的表
select table_name
from user_tables
复杂视图
创建一个含有公司部门工资情况的视图,
内容为:部门编号,部门名称,部门的最高,
最低,平均,以及工资总和信息.
create view v_dept_sal
as
select d.deptno,d.dnmae,
min(e.sal) min_sal,
max(e.sal) max_sal,
avg(e.sal) avg_sal,
sum(e.sal) sum_sal
from test e, dept d
where e.deptno=d.deptno
group by d.deptno, d.dname
查看谁比自己所在部门平均工资高?
SELECT e.ename,e.sal,e.deptno
FROM emp e,v _dept_ sal v
WHERE e.deptno=v.deptno AND e.sal>v.avg _sal
删除视图v_emp.10
DROP VIEW v_emp_10;
视图虽然是存放在数据字典中的独立对象,但视图仅仅是基于表的一个查 询定义,所以对视图的删除不会导致基表数据的丢失,不会影响基表数据
序列
序列也是数据库对象之一。
作用是生成一系列数字。
序列常用与为某张表的主键字段
提供值使用.
CREATE SEQUENCE seq_ emp_ id
START WITH 1
INCREMENT BY 1
序列支持两个伪列:
NEXTVAL:获取序列下一个值
若是新创建的序列,那么第一次调用返回的是
START WITH指定的值,以后每次调用都会得到
当前序列值加上步长后的数字.
NEXTVAL会导致序列发生步进,且序列不能回退.
CURRVAL:获取序列当前值,即:最后一次调用NEXTVAL后得到的值, CURRVAL不会导致步进.但是新创建的序列至少调用一次NEXTVAL后才 可以使用CURRVAL.
select seq_test_id.nextval
from dual
select seq_test_id.currval
from dual
使用序列为EMP表中信插入的数据提供
主键字段的值
insert into test
(empno, ename, sal, job, deptno)
values
(seq_test_id.nextval, 'rose', 3000, 'clerk',10)
删除序列
DROP SEQUENCE seq_emp_id
索引
索引是数据库对象之一
索引是为了提高查询效率
素引的统计与应用是数据库自动完成的
只要数据库认为可以使用某个已创建的
素引时就会自动应用.
单列索引
create index idx_test_ename on test(ename)
多列索引
create index idx_test_job_sal on test(job,sal)
select empno, ename, sal, job
from test
order by job, sal
修改和删除索引
如果经常在索引列上执行DML操作,需要定期重建索引,
DROP INDEX index_name;
删除索引idx_emp_ename
DROP INDEX idxemp_ename;
合理使用索引提升查询效率
·为经常出现在WHERE子句中的列创建索引
·为经常出现在ORDER BY、DISTINCT后面的字段建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致
·为经常作为表的连接条件的列上创建索引·不要在经常做DML操作的表上建立索引
·不要在小表上建立索引
·限制表上的索引数目,索引并不是越多越好
·删除很少被使用的、不合理的索引
·如果经常在索引列上执行DML操作,需要定期重建索引,提高索引的空间利用率:
ALTER INDEX index_ name REBUILD;
·重建索引idx_emp_ename
ALTER INDEX idx_emp_ename REBUILD;
约束的类型
·约束条件包括:
-非空约束(Not Null),简称NN
-唯一性约束(Unique),简称UK
-主键约束(Primary Key),简称PK
-外键约束(Foreign Key),简称FK
-检查约束(Check),简称CK
create table employees
(
eid number(6),
name varchar(30) not null,
salary number(7,2),
hiredate date constraint employees_hiredate_nn not null
)
约束
修改表时添加非空约束
·可以在建表之后,通过修改表的定义,添加非空约束:
ALTER TABLE employees
MODIFY(eid NUMBER(6)NOT NULL)
取消非空约束
如果业务要求取消某列的非空约束,可以采用重 建表或者修改表的方式:
ALTER TABLE employees
MODIFY(eid NUMBER(6)Rul);
唯一性约束
唯一性约束可以保证表中该字段的值任何一条记录都不可以重复,NULL除外.
create table employees1
(
eid number(6),
name varchar2(30),
email varchar2(50),
salary number(7,2),
hiredate date,
constraint employees_email_uk unique(email)
)
insert into employees1
(eid, name, email)
values
(2,'jack','jack@qq.com')
·在建表之后增加唯一性约束条件:
ALTER TABLE employees1
ADD CONSTRAINT employees_name_uk UNIQUE(name)
主键(Primary Key)约束条件从功能上看相当于非空
(NOT NULL)且唯一(UNIQUE)的组合
主键选取的原则
·主键应是对系统无意义的数据
·永远也不要更新主键,让主键除了唯一标识一行之外,再无其他的用途
·主键不应包含动态变化的数据,如时间戳
·主键应自动生成,不要人为干预,以免使它带有除了唯一标识一行以外的意义
·主键尽量建立在单列上
在建表时添加主键约束条件:
create table employees6
(
eid number(6) primary key,
name varchar2(30),
email varchar2(50),
salary number(7,2),
hiredate date
)
insert into employees6
(eid, name)
values
(3,'jack')
建表后创建主键约束条件,并自定义约束条件名称ALTER TABLE employees3
ADD CONSTRAINT employees3_eid_pk PRIMARY KEY(eid)
外键约束对性能的降低
如果在一个频繁DML操作的表上建立外键,每次DML操作,都将导致数据库自动对外键所关联的对应表做检查,产生开销,如果已在程序中控制逻辑,这些判断将增加额外负担,可以省去
外键确定了主从表的先后生成关系,有时会影响业务逻辑
关联不一定需要外键约束
·保证数据完整性可由程序或触发器控制
·简化开发,维护数据时不用考虑外键约束
·大量数据DML操作时不需考虑外键耗费时间
添加外键约束
·先建表,在建表后建立外键约束条件
CREATE TABLE employees4(
eid NUMBER(6),
name VARCHAR2(30),
salary NUMBER(7,2),
deptno NUMBER(4)
);
ALTER TABLE employees4
ADD CONSTRAINT employees4_deptno_fk
FOREIGN KEY(deptno)REFERENCES dept(deptno);
添加检查约束
·员工的薪水必须大于2000元
ALTER TABLE employees4
ADD CONSTRAINT employees4_salary_check CHECK(salary>2000);
·正常插入数据
INSERT INTO employees4(eid,name,salary,deptno)
VALUES(1236,'donna noble',2500,40);
·试图修改职员的薪水为1500元,更新失败
UPDATE employees4 SET salary=1500
WHERE eid=1236;