DML、DDL、DCL

子查询:解决不能一步求解。
子查询(内查询)
主查询(外查询)
主查询和子查询可以是:1:n

注意10个问题:

  1. 小括号

  2. 合理的书写风格

  3. 可以在where、select、having、from后面 都可以使用子查询
    select后的子查询必须是单行子查询(只返回一条记录)

  4. 不可以在group by后面使用子查询

  5. 强调from后面的子查询
    把子查询的结果看成一张表。

  6. 主查询和子查询可以不是同一张表;只要子查询返回的结果 主查询可以使用 即可。
    查询部门名称是sales的员工:
    子查询:
    多表查询:连接条件至少n-1条
    优化原则:尽量使用多表查询。

  7. 一般不在子查询中排序;但在top-n分析问题中,必须对子查询排序。
    top-n分析问题:rownum 行号(伪列),只能使用< <= , 不能使用> >= 。
    select rownum,ename,sal from (select * from emp order by sal desc) where rownum<=3 ;

  8. 一般先执行子查询,再执行主查询;但相关子查询例外
    相关子查询:(先执行主查询)
    把主查询中的值 作为参数传递给子查询。
    select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avgsal
    from emp e
    where sal > (select avg(sal) from emp where deptno=e.deptno);

  1. 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符。
    主查询 和 单行子查询 之间,只能使用:
    单行操作符:= < >
    主查询 和 多行子查询 之间,只能使用:
    多行操作符:in(在集合中)、 any(和集合中的任意一个值比较)、 all(和集合中的所有值比较)
    any 和 all 前必须使用一个单行操作符。

  2. 多行子查询中的null值问题:
    not in (a,b,null) 语法错误。等同于 < > ALL

课堂练习:

  1. 找到员工表中工资最高的前三名:select rownum,ename,sal from (select * from emp order by sal desc) where rownum<=3;
    SQL> select rownum,empno,ename,sal
    2 from (select * from emp order by sal desc)
    3 where rownum<=3;

    ROWNUM EMPNO ENAME SAL


     1       7839 KING             5000
     2       7788 SCOTT            3000
     3       7902 FORD             3000

分页:where rownum>=5 and rownum<=8
不成立,因为:rownum 行号(伪列),只能使用< <= , 不能使用> >= 。Oracle行式数据库,取了第一行才能取第二行。
Oracle使用嵌套子查询来实现分页:
select *
from (select rownum r,e1.

from (select * from emp order by sal) e1
where rownum <=8)
where r >=5;

临时表:
手动创建:create global temporary table *****
自动创建:order by 后自动产生
特点:当事务或者会话结束时,表中数据自动删除。

  1. 找到员工表中薪水大于本部门平均薪水的员工: empno ename sal avgsal
    select deptno,avg(sal) avgsal from emp group by deptno;

    DEPTNO AVGSAL


    30 1566.66667
    20       2175
    10 2916.66667

select empno,ename,sal,avgsal 
from emp e,(select deptno,avg(sal) avgsal from emp group by deptno) a
where e.deptno=a.deptno and e.sal>a.avgsal;

 EMPNO ENAME             SAL     AVGSAL

  7698 BLAKE            2850 1566.66667
  7499 ALLEN            1600 1566.66667
  7902 FORD             3000       2175
  7788 SCOTT            3000       2175
  7566 JONES            2975       2175
  7839 KING             5000 2916.66667

相关子查询:(先执行主查询)
把主查询中的值 作为参数传递给子查询。
select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avgsal
from emp e
where sal > (select avg(sal) from emp where deptno=e.deptno);

  1. 统计每年入职的员工个数:(不许使用子查询)
    total 1980 1981 1982 1987
    14 1 10 1 2

    EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO


  7369 SMITH      CLERK           7902 17-12月-80            800                    20
  7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
  7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
  7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
  7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
  7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
  7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
  7788 SCOTT      ANALYST         7566 19-4月 -87           3000                    20
  7839 KING       PRESIDENT            17-11月-81           5000                    10
  7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
  7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20

 EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO

  7900 JAMES      CLERK           7698 03-12月-81            950                    30
  7902 FORD       ANALYST         7566 03-12月-81           3000                    20
  7934 MILLER     CLERK           7782 23-1月 -82           1300                    10


select to_char(hiredate,'yyyy'),count(*) from emp group by to_char(hiredate,'yyyy');

select count(*) as "total",
       sum(case to_char(hiredate,'yyyy') when '1980' then 1 else 0 end) as "1980",
       sum(case to_char(hiredate,'yyyy') when '1981' then 1 else 0 end) as "1981",
       sum(case to_char(hiredate,'yyyy') when '1982' then 1 else 0 end) as "1982",
       sum(case to_char(hiredate,'yyyy') when '1987' then 1 else 0 end) as "1987"
from emp;


 TOTAL       1980       1981       1982       1987

    14          1         10          1          2

select count(*) as "total",
       sum( decode(to_char(hiredate,'yyyy'), '1980', 1, 0) ) as "1980",
       sum( decode(to_char(hiredate,'yyyy'), '1981', 1, 0) ) as "1981",
       sum( decode(to_char(hiredate,'yyyy'), '1982', 1, 0) ) as "1982",
       sum( decode(to_char(hiredate,'yyyy'), '1987', 1, 0) ) as "1987"
from emp;

行转列:
wm_concat(varchar2) 组函数

SQL> select deptno,wm_concat(ename) names from emp group by deptno;

DEPTNO NAMES

    10 CLARK,MILLER,KING
    20 SMITH,FORD,ADAMS,SCOTT,JONES
    30 ALLEN,JAMES,TURNER,BLAKE,MARTIN,WARD

集合运算:
并集:union 公共部分只要一次
union all 公共部分要两次
交集:intersect
差集:minus

集合运算的注意问题:

  1. 参与运算的各个集合必须列数相同且类型一致,
    列数不一样,补成一样的,根据列的类型使用:to_number(null)、to_char(null)
  2. 采用第一个集合作为最后的表头
  3. order by 永远在最后
  4. 可以使用括号()

select * from emp where deptno=10
union 或者 union all
select * from emp where deotno=20;

group by 增强:
group by rollup(a,b)

sql执行时间:
set timing on/off

sql优化原则:尽量不要使用集合运算。


sql语句的类型:

  1. DML(增删改查)
    select语句:DQL
  2. DDL(数据定义语言):create table、alter table、drop table、truncate table、
    create/drop view、sequence(序列)、index、synonym(同义词)
  3. DCL(数据控制语言):grant授权、revoke撤销权限,管理用户的安全。
  • insert:
    隐式插入null值
    显示插入null值

preparedStatement:
预编译一条带有?的sql

地址符&,相当于?
insert into emp(empno,ename,sal,deptno) values(&empno,&ename,&sal,&deptno);
输入 empno 的值:

select empno,ename,&c from emp;
select empno,ename,sal from &t;

批处理:

创建表:
create table emp10 as select * from emp where 1=2;

海量拷贝数据:数据移动

  1. 数据泵(datapump)--> plsql
  2. sql*Loader
  3. (数据仓库)由很多个数据库组成的比较大的数据库,外部表的方式。
  4. 可传输的表空间
  • update:注意加where条件,否则处理的是整张表。
    数据完整性:创建在这张表的约束。
  • delete:注意加where条件,否则删除的是整张表。
    区别:
  1. 逐条删除。
    truncate:先摧毁表结构,在创建表结构。

2.最根本的区别:
delete语句是DML语句,truncate是DDL语句。

DML可以回滚,DDL不可以回滚。
  1. delete不会释放空间,truncate会。
    10M的表,用delete清空后,表空间还是10M。
  2. delete可以闪回(flashback),truncate不可以。
    commit后想要恢复,就需要使用闪回。
  3. delete会产生碎片();truncate不会。
    Oracle插入数据的顺序是从后往前。
    指针:HWM 高水位线,下次插入数据的位置。
    delete删掉后空间不会释放,下次插入的数据还插到指针指向的高水位线。所以会产生空间间隙,形成许多碎片。
    碎片产生后影响读取的速度。

去掉碎片:

  1. alter table emp move;
  2. 导出exp、expdp 和 导入imp、impdp。
    exp -help 帮助文档。

测试速度:
set feedback off
@d:\xx.sql //导入sql脚本
set timing on
delete from testdelete; / drop table testdelete;
Oracle中是delete快。因为Oracle有个功能 undo数据(还原数据)。
mysql中是truncate快。

删除表:
drop table testdelete purge; 不经过回收站直接删除。

事务:
由一个或多个DML语句组成
DDL语句: 把前面的DML语句给提交了。
DCL:

本地事务(之前学的)
全局事务
发短信验证码给,给一个账户+钱,另一个账户-钱。
JTA,全局事务/分布式事务,spring支持jta。

事务的标志:

  1. 事务的起始标志:事务中第一条DML语句。
  2. 结束标志:提交(显示提交commit,隐式提交:正常退出、DDL语句、DCL语句)、
    回滚(显示rollback,隐式:非正常退出、掉电、宕机)

控制事务:
定义保存点:savepoint a;
回滚到保存点:rollback to savepoint a;

隔离级别:
因为数据库支持并发访问。

Oracle中支持3种隔离级别:
sql99标准:
read commited(默认)
serializable (串行化,单线程)
orale自己的:
read only


DDL语句:

管理数据库的对象:10个对象

数据类型:
ROWID 行地址(伪列)字符串,相当于指针指向数据文件.dbf

创建表:
create table emp10 as select * from emp where 1=2;
条件为假,只拷贝表结构到新表。

创建视图:
create view emp10 as select * from emp where deptno=10;

修改表:alter table tablename

追加新列 + add

修改列,+modify

删除列,+ drop column

重命名列,+ rename column name1 to name2

重命名表
rename table1 to table2;

drop table tablename [purge];
并没有真的删除表,只是给它加一个标志recyclebin_name,删到了回收站里面。

Oracle回收站:
show recyclebin

purge recyclebin; 清空回收站

select * from "recyclebin_name";
可以查到回收站的表的内容

管理员是没有回收站的。

sqlplus sys/orcl as sysdba

管理员密码忘了,随便写一个密码就可以登录
用户名也忘了,也可以随便写一个就能登录。

从回收站恢复,第四天的闪回。
flashback table table1 to before drop;

约束:
列级约束:
not null
unique 唯一性的索引
primary key
foreign key
check约束,检查性约束。
create table tab1
(tid number,
gender varchar2 check (gender in ('男','女'))
sal number check (sal>0)
);
constraint ming check (sal>0)

表级约束:联合主键

外键约束;
foreign key
reference
on delete cascade
on delete set null

create table stu
(sid number constraint sid_primary_key primary key,
sname varchar2 constraint sname_not_null not null,
email varchar2 constraint email_unique unique,
cid number constraint foreign key cid_classes_fk references classes(cid) on delete set null
);


其他数据库对象:

  1. 视图:
    权限不足
    grant create view to scott

with check option
通过视图只能操作看得见的数据。
不建议通过视图对表进行修改。
受到限制
子查询中含有xxx,不能通过视图做insert/update/delete
with read only 只读

视图是不缓存数据的,是个逻辑上的概念,虚表。

物化视图,可以缓存数据。

  1. 序列:数组[20] -- 内存,提高效率。
    auto_increment功能一样

create sequence sename;

increment by 1, 步长
nocycle
cache 默认20

两个伪列:nextval、curval(第一次不要使用这个)
回滚、系统异常、多个表同时使用同一序列,会造成序列裂缝,不连续。

修改序列,只影响。。。
删除序列

  1. 索引:(可以提高查询速度 是 必要条件,但是不是充分条件)
    主键就是唯一性的索引。
    一本书的目录。
    create index myindex on emp(deptno);
    索引表:目录
    可以在多个列创建索引。

索引类型:

  1. B树索引(默认)平衡树,insert、update、delete(OLTP)
  2. 位图索引 --> 矩阵,行和列,select(OLAP 商品推荐)
    create bitmap index *** on ***
  1. 同义词(别名):
    为表或视图起别名,就叫同义词。

create synonym myemp for emp;

grant create [public] synonym to scott

create synonym myemp2 for hr.employees;

私有同义词:默认
公有同义词:grant create public synonym to scott
grant select on hr.employees to scott;

select count(*) from myemp2;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容