ORACLE_笔记_练习题目

一.plsql用法网址及时复习

extract()函数----用于截取年、月、日、时、分、秒

https://www.cnblogs.com/xqzt/p/4477239.html

case when 不同位置用法不同,可用于求显示等级、及格率等

https://www.cnblogs.com/soundcode/p/5549901.html

merge into

https://www.cnblogs.com/kongxc/p/9237941.html

https://www.cnblogs.com/kongxc/p/9237941.html

where 和having 的区别

https://www.cnblogs.com/jameshappy/archive/2012/05/23/2515034.html

constraint约束

https://blog.csdn.net/qqww120102/article/details/79791396

trigger触发器

producers存储过程

consequences序列

index索引

cursor游标

 

 

 

二.写SQL前注意点:

0.查询字段必要的加注释,取名字

1.单表查询不要取别名

2.别名不要用关键字

3.表不多时候用 A B C D E 取别名而不用缩写

4.聚集函数多和分组函数group by 联用求均值

5.分类后求第几个一般用row_num()rank函数 而不用 group by

*6.exists 查询效率一般比in 高 因为in不走索引,in适合外表大内表小  exists 适合外表小内表大。(只要内表和外表有关联ID 就可以使用)

用exists 替换步骤 优化sql如下例:

   假如有一个表user,它有两个字段id和name,我们要查询名字中带a的用户信息:

 a. 最简单的SQL:select * from user where name like '%a%';

 b. 使用IN的SQL:select u.* from user u where u.id in (select uu.id from user uu where uu.name like '%a%');

  我们现在将使用IN的SQL修改为使用EXISTS的SQL该怎么写呢?

 c. 一开始我直接将u.id in 替换为EXISTS,获得如下语句,发现把结果全部查询出来了 :

    select u.* from user u where exists(select uu.id from user uu where uu.name like '%a%');

  d.最终末尾加上关联        

    select u.* from user u where exists (select uu.id from user uu where uu.name like '%a%' and uu.id=u.id);

    原因解释:

    总结:EXISTS子查询可以看成是一个独立的查询系统,只为了获取真假逻辑值,EXISTS子查询与外查询查询的表是两个完全独立的毫无关系的表(当第二个表中的name中有包含a的姓名存在,那么就执行在第一个表中查询所有用户的操作),当我们在子查询中添加了id关联之后,EXISTS子查询与外查询查询的表就统一了,是二者组合组建的虚表,是同一个表(这样当子查询查询到虚表中当前行的uu.name中包含a时,则将虚表当前行中对应的u.id与u.name查询到了)

  所以一切的重点就在这个ID关联之上,添加ID关联,数据库会先将两张表通过ID关联组合成一张虚表,所有的查询操作都在这张虚表上完成,操作的是同一张表,当然就不会出现之前的那种情况了!

例子使用exists语句显示BLAKE所在部门的其他所有雇员,但是不要显示BLAKE

WHERE EXISTS(子查询) ,子查询返回的的是TRUE OR FALSE 即使是 

SELECT * FROM DEPR WHERE EXISTS (SELECT NULL)

--正确写法 关键在于内表外表相同组成的同一虚表

SELECT *

  FROM EMP B  关键点

 WHERE EXISTS

 (SELECT *

          FROM EMP C     --关键点

         WHERE C.EMPNO = B.EMPNO

           AND C.ENAME <> 'BLAKE'

           AND C.DEPTNO =

               (SELECT A.DEPTNO FROM EMP A WHERE A.ENAME = 'BLAKE'))

 

7.lpad( string, padded_length, [ pad_string ] ) 填充在左侧使其左对齐  rpad 填充在右测  一般price习惯lpad对齐,pad_string不指定默认是空格

8. NUMBER 四则运算 要注意 用NVL(EX1,EX2) 因为number+null=null,如果ex1为空返回ex2,如果ex1 不为空返回ex1,作用就是不返回空值  

*9.重点掌握 row_number()rank 自主平时多找练习做

10. case when 两种表现形式,3位置不同的用法:10.1 SELECT CASE WHEN 用法 10.2 WHERE CASE WHEN...  10.3 GROUP BY  

CASE WHEN salary <= 500 THEN '1' WHEN ....

11.left join 易错点 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。

where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

总结:如果想要查询某列所在行所有信息,不要在where 后加过分的限制条件,

12.对时间操作多用round(to_number(to_char(sysdate,'yyyy')),2)  ;插入时间字符串 转换成 date类型到数据库中:to_date('2019/1/1','yyyy-mm-dd')

*13.merge into TABLE_A USING TABLE_B  用B表更新A表 一般用法: 有多种模式  1.正常模式先插入再修改  2.只插入 3.只修改

MERGE INTO A_MERGE A USING (select B.AID,B.NAME,B.YEAR from B_MERGE B) C ON (A.id=C.AID)

WHEN MATCHED THEN

UPDATE SET A.YEAR=C.YEAR

WHEN NOT MATCHED THEN

INSERT(A.ID,A.NAME,A.YEAR) VALUES(C.AID,C.NAME,C.YEAR); 

commit;

14.where 和 having的区别

它们的相似之处就是定义搜索条件,不同之处是where子句为单个筛选而having子句与组有关,而不是与单个的行有关。

最后:理解having子句和where子句最好的方法就是基础select语句中的那些句子的处理次序:where子句只能接收from子句输出的数据,而having子句则可以接受来自group by,where或者from子句的输入。

15.TABLE_A LEFT JOIN TABLE_B ON A.AID=B.AID 查询数量为A表中每个AID×B表对应的AID的数量和+A表中有而B表中没有的数量=总查询数量,如果加上了where 则会更少

SELECT  DEPT.DEPTNO FROM DEPT LEFT JOIN EMP ON EMP.DEPTNO=DEPT.DEPTNO 查询到15条信息

SELECT  DEPT.DEPTNO FROM DEPT RIGHT JOIN EMP ON EMP.DEPTNO=DEPT.DEPTNO 查询到14条信息因为是以EMP为基础

SELECT  DEPT.DEPTNO FROM DEPT LEFT JOIN EMP ON EMP.DEPTNO=DEPT.DEPTNO WHERE EMP.DEPTNO=DEPT.DEPTNO 查询到14条信息 本来左连接有15条数据,但是where 对结果进行筛选去掉了单独的deptno=40这个数据,因为它没有和EMP表关联

 

SELECT * FROM EMP LEFT JOIN DEPT ON EMP.DEPTNO=DEPT.DEPTNO  14条数据,因为以EMP为基础

SELECT * FROM EMP RIGHT JOIN DEPT ON EMP.DEPTNO=DEPT.DEPTNO 15条数据,因为以DEPT为基础 但是结果左边会出现空值,所以把两个表交换一下位置再重新用左连接

 

 

 

 

 

 

 

/*1.  没有使用子查询的理由; 

查询老师:谌燕 ,所教授的课程;

*/

SELECT hc.COURSE_NO, hc.COURSE_NAME

  FROM HAND_COURSE hc

 WHERE TEACHER_NO =

       (SELECT TEACHER_NO FROM HAND_TEACHER WHERE TEACHER_NAME = '谌燕');

 

 

select h.*,rowid from hzd_table h where h.age between 18 and 28

 

select HT.*  from HZD_TABLE HT where HT.NAME like '%a_%' escape 'a';

select distinct  sysdate  "aa" ,rowid from dual 

select sysdate||sysdate  "aa" ,rowid from dual 

 

select to_char(sysdate),to_char(sysdate,'yyyy-MM-dd HH24:mm:ss'), to_date(sysdate),to_date(to_char(sysdate,'yyyy-MM-dd'),'yyyy-MM-dd')from dual 

where to_char(sysdate,'yyyy-MM-dd')='2019-11-02'

 

 

三.触发器

------------------------------------------触发器trigger 测试----------------------------------------------------

create or replace trigger update_hzd_table_trigger 

after 

       update on hzd_table

       for each row

begin dbms_output.put_line('触发器测试')  ;

  end;

 

update hzd_table ht set ht.age=19 where ht.age<55

 

select h.*,length(h.id),length(h.name),length('hzd1') aa,length('Oracle'),rowid from hzd_table h

 

 

-------------------------服务器端使用哪种编码   GBK 一个中文16位占用2字节,UTF-8 32位 一个中文占用三个字节-----------

select userenv('language') from dual;

select h.*,length('GBK一个汉字占用两个字节') ,rowid from hzd_table h

select h.*,lengthb('GBK一个汉字占用两个字节') ,rowid from hzd_table h

 

 

四.建表 建立CONSTRAINT约束,建立序列SEQUENCE 插入数据自增

DROP TABLE HZD_STUDENT;

CREATE TABLE HZD_STUDENT (

SID NUMBER(10)   CONSTRAINT CON_SID_PK PRIMARY KEY ,

SNAME VARCHAR(255),

SDESCRIPTION VARCHAR(255)

)

--ALTER 重新、定义、改变命名表字段等

ALTER table hzd_table modify sid not null

 

CREATE SEQUENCE HZD_STUDENT_SID_SEQ

INCREMENT BY 1 

START WITH 1;

 

insert into HZD_STUDENT(SID,SNAME,SDESCRIPTION)values(HZD_STUDENT_SID_SEQ.Nextval,'张三','测试序列和主键约束');

 

SELECT ROWID, HZD_TABLE.* FROM HZD_TABLE

SELECT * FROM HZD_STUDENT

 --根据 B表信息修改A表信息 这是错误的写法会把所有的数据都修改

UPDATE  HZD_TABLE  A

SET  NAME ='测试修改数据'

WHERE    EXISTS

(SELECT *

FROM  HZD_STUDENT  B

WHERE  A.SID = B.SID)

 

 

SELECT * FROM HZD_TABLE A WHERE EXISTS (SELECT * FROM HZD_STUDENT B WHERE B.SID=A.SID AND AGE=19)

 

五.序列例子

-----------------------------------------------序列sequence实现自增长,在插入的时候用-----------------------------------------------

/*步骤:

1.建表某表Student

2.建立序列,名字最后有格式

3.插入数据 用Student_stuId_Seq.Nextval插入 如: insert into Student(stuId,Stuname) values(Student_stuId_Seq.Nextval,'张三');

*/

完整子如下例:

--例创建示例表 --

create table Student(

    stuId number(9) not null,

    stuName varchar2(20) not null,

    stuMsg varchar2(50) null

);

  

  -- 创建序列  Student_stuId_Seq --

 create sequence Student_stuId_Seq

 increment by 1

 start with 1

 minvalue 1

 maxvalue 999999999;

 

 -- 更改序列  Student_stuId_Seq--

/* alter sequence Student_stuId_Seq

    increment by 2  

    minvalue 1

    maxvalue 999999999;*/

 

 --获取序列自增ID --

 select Student_stuId_Seq.Nextval 自增序列ID from dual;

 

 -- 删除序列 -- 

/* drop sequence Student_stuId_Seq;*/

 

 --调用序列,插入Student数据 --

 insert into Student(stuId,Stuname) values(Student_stuId_Seq.Nextval,'张三');

 insert into Student(stuId,Stuname) values(Student_stuId_Seq.Nextval,'李四');

 --查询插入的数据 --

 select student.* from Student

 

 

六.约束CONSTRAINT

-----------------------------------------------约束constraint-----------------------------------------------

https://blog.csdn.net/qqww120102/article/details/79791396

约束按照创建方式分为:表级约束和列级约束

表级约束:指创建表的时候,定义完全部列后。在最后指定约束对应的列

列级约束:指创建表的时候,定义为列立即定义该列对应的约束

 

数据库约束有五种:

1.主键约束(PRIMARY KEY)   :相当于UNIQUE+NOT NULL   语法:alter table table_name add constraint [constraint_type_name ] [constraint_type](column)

2.唯一性约束(UNIQUE)       :alter table table_name add constraint constraint_name unique(column_name);

3.非空约束(NOT NULL)       :alter table table_name modify column_name constraint constraint_name not null ;

4.外键约束(FOREIGN KEY)    :

5.检查约束(CHECK)          :

 

-- https://blog.csdn.net/qqww120102/article/details/79791396

/*主键约束(primary key)

外键约束(foreign key)

唯一性约束(unique)

非空约束(not null)

检查约束(check)*/

 

1.主键约束==UNIQUE+NOT NULL

--增加主键约束

alter table table_name add constraint constraint_name primary key(column_name);

--删除主键约束

SQL> alter table table_name drop constraint constraint_name;

alter table table_name drop primary key;

 

2.唯一性约束(UNIQUE)

--增加唯一约束

alter table table_name add constraint constraint_name unique(column_name);

--删除唯一约束

alter table table_name drop constraint constraint_name;

 

3.非空约束(NOT NULL)

--增加非空约束

alter table table_name modify column_name constraint constraint_name not null ;

--删除非空约束

alter table table_name modify column_name constraint constraint_name null;

 

4.外键约束(FOREIGN KEY)

第一种方式简单粗暴,删除的时候,级联删除掉子表中的所有匹配行,在创建外键时,通过 on delete cascade 子句指定该外键列可级联删除:

SQL> alter table 外键表名 add constraint constraint_name foreign key(外键表列) references 参照表 (参照表列) on delete cascade;

 

第二种方式,删除父表中的对应行,会将对应子表中的所有匹配行的外键约束列置为NULL,通过 on delete set null 子句实施:

SQL> alter table 外键表名 add constraint constraint_name foreign key(外键表列) references 参照表 (参照表列) on delete set null;

删除外键约束

SQL> alter table table_name drop constraint constraint_name;

————————————————

版权声明:本文为CSDN博主「大辰」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qqww120102/article/details/79791396

 

5.检查约束(CHECK)

添加约束

SQL> alter table table_name add constraint constraint_name check(具体约束内容);

删除约束

SQL> alter table table_name drop constraint constraint_name;

 

添加、修改默认值

alter table table_name modify column_name default 具体内容;

删除默认值

alter table table_name modify column_name default null;

 

 

 

--主键约束 alter table table_name add constraint [constraint_type_name ] [constraint_type](column)

alter table books add constraint books_pk primary key (id);

--唯一约束

alter table table_name add [constraint constraint_name] unique(column_name);

 

删除约束

删除unique约束

删除列上的unique约束,可以使用alter table...drop语句,形式如下:

alter table table_name drop unique(column_name)

如果约束有名称,也可以使用指定名称的方式删除该约束,语句形式如下:

alter table table drop constraint constraint_name;

 

SELECT HT.* ,ROWID FROM HZD_TABLE HT

alter table HZD_TABLE add constraint con primary key (id);

 

 

七时间转换

-----------------------------------------oracle timestamp和日期 timestamp和字符串互转 ---------------------

Oracle 日期类型timestamp(时间戳)和date类型使用

 

1、获取系统时间的语句(ssxff6获取小数点后面六位) 

select sysdate,systimestamp,to_char(systimestamp, 'yyyymmdd hh24:mi:ssxff6'), 

  to_char(systimestamp, 'yyyymmdd hh24:mi:ss.ff6') from dual;  

 

2、字符型转成timestamp 

select to_timestamp('2011-09-14 12:52:42.123456789', 'syyyy-mm-dd hh24:mi:ss.ff') from dual; 

 

3、timestamp转成date型 

select cast(to_timestamp('2011-09-14 12:52:42.123456789', 'syyyy-mm-dd hh24:mi:ss.ff') as date) timestamp_to_date from dual;  

 

4、date型转成timestamp 

select cast(sysdate as timestamp) date_to_timestamp from dual;  

 

5、两date的日期相减得出的是天数,而两timestamp的日期相减得出的是完整的年月日时分秒小数秒 

select sysdate-sysdate,systimestamp-systimestamp from dual; 

 

select extract(day from inter) * 24 * 60 * 60 +   

  extract(hour from inter) * 60 * 60 + extract(minute from inter) * 60 +   

    extract(second from inter) "seconds" from 

  select to_timestamp('2011-09-14 12:34:23.281000000', 'yyyy-mm-dd hh24:mi:ss.ff') -   

    to_timestamp('2011-09-14 12:34:22.984000000', 'yyyy-mm-dd hh24:mi:ss.ff') inter from dual 

); 

 

select extract(second from to_timestamp('2011-09-14 12:34:23.281000000', 'yyyy-mm-dd hh24:mi:ss.ff'))- 

  extract(second from to_timestamp('2011-09-14 12:34:22.984000000', 'yyyy-mm-dd hh24:mi:ss.ff')) from dual; 

 

注:所以,timestamp要算出两日期间隔了多少秒,要用函数转换一下。 

to_char函数支持date和timestamp,但是trunc却不支持TIMESTAMP数据类型。 

select systimestamp-systimestamp from dual

select sysdate,systimestamp,to_char(systimestamp, 'yyyy-mm-dd hh24:mi:ssxff6'), 

to_char(systimestamp, 'yyyymmdd hh24:mi:ss.ff6') from dual;  

 

 

-----------------------------extract (year from sysdate)用于截取时分秒 获取日期间隔---------------------------------------------------------

select extract(second from to_timestamp('2011-09-14 12:34:23.281000000', 'yyyy-mm-dd hh24:mi:ss.ff')),

  extract(second from to_timestamp('2011-09-14 12:34:22.984000000', 'yyyy-mm-dd hh24:mi:ss.ff')) from dual; 

  

  

  

只可以从一个date类型中截取年月日

select  extract (year from sysdate) year, extract (month from sysdate) month, extract (day from sysdate) day from  dual;

 

从timestamp中获取年月日时分秒

select 

 extract(year from systimestamp) year

,extract(month from systimestamp) month

,extract(day from systimestamp) day

,extract(minute from systimestamp) minute

,extract(second from systimestamp) second

,extract(timezone_hour from systimestamp) th

,extract(timezone_minute from systimestamp) tm

,extract(timezone_region from systimestamp) tr

,extract(timezone_abbr from systimestamp) ta

from dual

 

获取两个日期之间的具体时间间隔

获取两个日期之间的具体时间间隔,extract函数是最好的选择

select

extract (day from dt2 - dt1) day,

extract (hour from dt2 - dt1) hour,

extract (minute from dt2 - dt1) minute,

extract (second from dt2 - dt1) second

from

(

select

to_timestamp ('2011-02-04 15:07:00','yyyy-mm-dd hh24:mi:ss') dt1,

to_timestamp ('2011-05-17 19:08:46','yyyy-mm-dd hh24:mi:ss') dt2

from

dual

)

 

例题:

Create Table  HAND_STUDENT

(

 STUDENT_NO Varchar2(10) Not Null,

 STUDENT_NAME Varchar2(20),

 STUDENT_AGE Number,

 STUDENT_GENDER Varchar2(5),

 OBJECT_VERSION_NUMBER Number Default 1 Not Null,

 CREATION_DATE DATE Default Sysdate Not Null,

 CREATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATE_DATE DATE Default Sysdate Not Null,

 LAST_UPDATE_LOGIN NUMBER

);

-- Add comments to the table

comment on table  HAND_STUDENT is '学生信息表';

-- Add comments to the columns

comment on column  HAND_STUDENT.STUDENT_NO is '学号';

comment on column  HAND_STUDENT.STUDENT_NAME is '姓名';

comment on column  HAND_STUDENT.STUDENT_AGE is '年龄';

comment on column  HAND_STUDENT.STUDENT_GENDER is '性别';

comment on column  HAND_STUDENT.OBJECT_VERSION_NUMBER is '行版本号,用来处理锁';

 

-- Create/Recreate indexes

Create Unique Index  HAND_STUDENT_U1 On  HAND_STUDENT(STUDENT_NO);

 

 

Create Table  HAND_TEACHER

(

 TEACHER_NO Varchar2(10) Not Null,

 TEACHER_NAME Varchar2(20),

 MANAGER_NO Varchar2(10),

 OBJECT_VERSION_NUMBER Number Default 1 Not Null,

 CREATION_DATE DATE Default Sysdate Not Null,

 CREATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATE_DATE DATE Default Sysdate Not Null,

 LAST_UPDATE_LOGIN NUMBER

);

-- Add comments to the table

comment on table  HAND_TEACHER is '教师信息表';

-- Add comments to the columns

comment on column  HAND_TEACHER.TEACHER_NO is '教师编号';

comment on column  HAND_TEACHER.TEACHER_NAME is '教师名称';

comment on column  HAND_TEACHER.MANAGER_NO is '上级编号';

comment on column  HAND_TEACHER.OBJECT_VERSION_NUMBER is '行版本号,用来处理锁';

 

-- Create/Recreate indexes

Create Unique Index  HAND_TEACHER_U1 On  HAND_TEACHER(TEACHER_NO) ;

 

Create Table  HAND_COURSE

(

 COURSE_NO Varchar2(10) Not Null,

 COURSE_NAME Varchar2(20),

 TEACHER_NO Varchar2(10) Not Null,

 OBJECT_VERSION_NUMBER Number Default 1 Not Null,

 CREATION_DATE DATE Default Sysdate Not Null,

 CREATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATE_DATE DATE Default Sysdate Not Null,

 LAST_UPDATE_LOGIN NUMBER

);

-- Add comments to the table

comment on table  HAND_COURSE is '课程信息表';

-- Add comments to the columns

comment on column  HAND_COURSE.COURSE_NO is '课程号';

comment on column  HAND_COURSE.COURSE_NAME is '课程名称';

comment on column  HAND_COURSE.TEACHER_NO is '教师编号';

comment on column  HAND_COURSE.OBJECT_VERSION_NUMBER is '行版本号,用来处理锁';

 

-- Create/Recreate indexes

Create Unique Index  HAND_COURSE_U1 On  HAND_COURSE(COURSE_NO);

 

 

Create Table  HAND_STUDENT_CORE

(

 STUDENT_NO Varchar2(10) Not Null,

 COURSE_NO Varchar2(10) Not Null,

 CORE Number,

 OBJECT_VERSION_NUMBER Number Default 1 Not Null,

 CREATION_DATE DATE Default Sysdate Not Null,

 CREATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATED_BY NUMBER Default -1 Not Null,

 LAST_UPDATE_DATE DATE Default Sysdate Not Null,

 LAST_UPDATE_LOGIN NUMBER

);

-- Add comments to the table

comment on table  HAND_STUDENT_CORE is '学生成绩表';

-- Add comments to the columns

comment on column  HAND_STUDENT_CORE.STUDENT_NO is '学号';

comment on column  HAND_STUDENT_CORE.COURSE_NO is '课程号';

comment on column  HAND_STUDENT_CORE.CORE is '分数';

comment on column  HAND_STUDENT_CORE.OBJECT_VERSION_NUMBER is '行版本号,用来处理锁';

 

-- Create/Recreate indexes

Create Unique Index  HAND_STUDENT_CORE_U1 On  HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO);

 

/*******初始化学生表的数据******/

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s001','张三',23,'男');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s002','李四',23,'男');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s003','吴鹏',25,'男');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s004','琴沁',20,'女');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s005','王丽',20,'女');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s006','李波',21,'男');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s007','刘玉',21,'男');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s008','萧蓉',21,'女');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s009','陈萧晓',23,'女');

insert into HAND_STUDENT(STUDENT_NO,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER) values ('s010','陈美',22,'女');

commit;

/******************初始化教师表***********************/

insert into HAND_TEACHER(TEACHER_NO,TEACHER_NAME,MANAGER_NO) values ('t001', '刘阳','');

insert into HAND_TEACHER(TEACHER_NO,TEACHER_NAME,MANAGER_NO)  values ('t002', '谌燕','t001');

insert into HAND_TEACHER(TEACHER_NO,TEACHER_NAME,MANAGER_NO)  values ('t003', '胡明星','t002');

commit;

/***************初始化课程表****************************/

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c001','J2SE','t002');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c002','Java Web','t002');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c003','SSH','t001');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c004','Oracle','t001');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c005','SQL SERVER 2005','t003');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c006','C#','t003');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c007','JavaScript','t002');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c008','DIV+CSS','t001');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c009','PHP','t003');

insert into HAND_COURSE(COURSE_NO,COURSE_NAME,TEACHER_NO) values ('c010','EJB3.0','t002');

commit;

/***************初始化成绩表***********************/

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s001','c001',58.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s002','c001',80.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s003','c001',81.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s004','c001',60.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s001','c002',82.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s002','c002',72.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s003','c002',81.9);

insert into HAND_STUDENT_CORE(STUDENT_NO,COURSE_NO,CORE) values ('s001','c003','59');

commit;

 

/**

alter table HAND_STUDENT_CORE add constraint FK_STUDENT_NO foreign key(STUDENT_NO) REFERENCES HAND_STUDENT(STUDENT_NO);

alter table HAND_STUDENT_CORE add constraint FK_COURSE_NO foreign key(COURSE_NO) REFERENCES HAND_COURSE(COURSE_NO);

alter table HAND_COURSE add constraint FK_TEACHER_NO foreign key(TEACHER_NO) REFERENCES HAND_TEACHER(TEACHER_NO);**/

 

改写:

1.  没有使用子查询的理由; 

 

查询老师:谌燕 ,所教授的课程;

 

SELECT hc.COURSE_NO, hc.COURSE_NAME

  FROM HAND_COURSE hc

 WHERE TEACHER_NO =

       (SELECT TEACHER_NO FROM HAND_TEACHER WHERE TEACHER_NAME = '谌燕');

     

 

2.  自定义更新语句,没有判断版本号,没有更新版本号+who字段

更新学生s001对应的课程 c002 成绩为 82.8

 

UPDATE HAND_STUDENT_CORE 

   SET CORE = 82.8

 WHERE STUDENT_NO = 'S001'

   AND COURSE_NO = 'c002';

   

--PDATE HAND_STUDENT_CORE 

   SET CORE = 82.8,

   OBJECT_VERSION_NUMBER =OBJECT_VERSION_NUMBER+1,

   LAST_UPDATED_BY = &userid,

   LAST_UPDATE_DATE = sysdate,

 

 WHERE STUDENT_NO = 'S001'

   AND COURSE_NO = 'c002'

and  OBJECT_VERSION_NUMBER=1

 

 

3.  子查询滥用,重复的子查询请简化;

查询学生s001 对应的成绩+教师编号+课程名称+课程编号

 

SELECT hsc.COURSE_NO,

       (select COURSE_NAME

          from HAND_COURSE i

         where i.COURSE_NO = hsc.COURSE_NO) COURSE_NAME,

       (select TEACHER_NO

          from HAND_COURSE j

         where j.COURSE_NO = hsc.COURSE_NO) TEACHER_NO,

       hsc.CORE

  FROM HAND_STUDENT_CORE hsc

  where hsc.STUDENT_NO = 's001';

  

 

SELECT hsc.COURSE_NO,

       (select COURSE_NAME

          from HAND_COURSE i

         where i.COURSE_NO = hsc.COURSE_NO) COURSE_NAME,

       (select TEACHER_NO

          from HAND_COURSE j

         where j.COURSE_NO = hsc.COURSE_NO) TEACHER_NO,

       hsc.CORE

  FROM HAND_STUDENT_CORE hsc

  where hsc.STUDENT_NO = 's001';

 

4.  条件语句中直接使用 case when,性能差,建议子查询封装

core 分数等级在 70分以下,差; 70-80分,良; 80分以上,优;

查询出所有成绩等级为"差"的学生及对应课程分数;

 

SELECT hs.STUDENT_NAME,

       hsc.COURSE_NO,

       (CASE

         WHEN hsc.CORE > 80 THEN

          '优'

         WHEN hsc.CORE > 70 THEN

          '良'

         ELSE

          '差'

       END) type,

       hsc.CORE

  FROM HAND_STUDENT_CORE hsc, hand_student hs

 where hsc.STUDENT_NO = hs.STUDENT_NO

   and (CASE

         WHEN hsc.CORE > 80 THEN

          '优'

         WHEN hsc.CORE > 70 THEN

          '良'

         ELSE

          '差'

       END) = '差' ;

 

     

     

5.  列名的函数运算,将不走索引

查询出所有加10分后,分数还低于80分的学生成绩;

 

SELECT hs.STUDENT_NAME, hsc.STUDENT_NO, hsc.COURSE_NO, hsc.CORE

  FROM HAND_STUDENT_CORE hsc, hand_student hs

 WHERE hsc.STUDENT_NO = hs.STUDENT_NO

   and hsc.core + 10 < 80

 order by hs.STUDENT_NAME;

 

 

 

 

6.  重复的SQL建议使用子查询整个进行封装 or 合适的方式进行改写;

 

查询老师:刘阳,所教授的课程;

 

SELECT hc.COURSE_NO,

       hc.COURSE_NAME,

       hc.TEACHER_NO,

       (SELECT TEACHER_NAME

          FROM HAND_TEACHER ht

         where hc.TEACHER_NO = ht.TEACHER_NO) TEACHER_NAME

  FROM HAND_COURSE hc

 WHERE 1 = 1

   and (SELECT TEACHER_NAME

          FROM HAND_TEACHER ht

         where hc.TEACHER_NO = ht.TEACHER_NO) = '刘阳';

 

 

 

7.Group by 与 distinct 混用

 

SELECT DISTINCT STUDENT_NO, COURSE_NO

  FROM HAND_STUDENT_CORE

 GROUP BY STUDENT_NO, COURSE_NO;

 

 

 

8.  内层的Group by 没有任何的限制条件,只能走全表扫描,建议改成子查询

计算学生的成绩总分;  

大数据量,比如50万左右的数据可以明显看出执行计划上的差别,小数据量比如10几行可能错误的写法还更快,全表扫描比走索引快;

 

select hs.STUDENT_NO, hs.STUDENT_NAME, hc.cores

  from hand_student hs

  left join (SELECT STUDENT_NO, sum(CORE) cores

               FROM HAND_STUDENT_CORE

              GROUP BY STUDENT_NO) hc

    on hs.STUDENT_NO = hc.STUDENT_NO;

  

  

9.  内层子查询的Group by 没有限制条件走全表扫描,外层where条件可作为限制,建议移到内层,走索引查询;内层多余的查询字段请去除,只使用有用的字段

 

 

select COURSE_NO, sum(core)

  from (select STUDENT_NO, COURSE_NO, core

          from HAND_STUDENT_CORE

        union ALL

        select STUDENT_NO, COURSE_NO, core

          from HAND_STUDENT_CORE) a

 where 1 = 1

   and a.student_no = 's001'

 group by COURSE_NO;

 

 

10. 存在全表扫描,可以如何提速;

 

SELECT hsc.COURSE_NO, hc.COURSE_NAME, hc.TEACHER_NO, hsc.CORE

  FROM HAND_STUDENT_CORE hsc, HAND_COURSE hc 

with (index(hsc.COURSE_NO))

 where hsc.COURSE_NO = 'c001'

   and hc.COURSE_NO = hsc.COURSE_NO; 

 

 

 

 

 

---------------------------2019/11/4 黄泽东SQL练习 BY PLSQL-----------------------------------------

取合适的别名,字段不要取关键字

表少的时候最好是A B C D E

 

 

 

1.关键字:ROW_NUMBER

题目:请按渠道的首付酬金进行排序,找出排名为第3的渠道编码

 

CREATE TABLE DD_TABLE1

(

  GROUP_ID         VARCHAR (10), --渠道编码

  PARAM_NAME       VARCHAR (10), --酬金类别

  VALUE             INTEGER,     --酬金金额

  OP_TIME          VARCHAR(100), --操作时间

  OP_NOTE          VARCHAR(100) --操作说明

);

 

Insert into DD_TABLE1

   (GROUP_ID,PARAM_NAME,VALUE,OP_TIME,OP_NOTE)

 Values

   ('51124', '首付酬金',789,'2008-07-17-09.23.01.000000', '运行状态正常');

Insert into DD_TABLE1

   (GROUP_ID,PARAM_NAME,VALUE,OP_TIME,OP_NOTE)

 Values

   ('51124', '按质支付',900,'2008-06-06-14.03.02.000000', '此渠道为三星级,5%分成比例');

Insert into DD_TABLE1

   (GROUP_ID,PARAM_NAME,VALUE,OP_TIME,OP_NOTE)

 Values

   ('51124', '分时见效',1000,'2008-08-20-22.05.48.000000', '二返三返发展酬金');

Insert into DD_TABLE1

   (GROUP_ID,PARAM_NAME,VALUE,OP_TIME,OP_NOTE)

 Values

   ('51124', '首付酬金',789,'2008-07-17-09.23.01.000000', '运行状态正常');

Insert into DD_TABLE1

   (GROUP_ID,PARAM_NAME,VALUE,OP_TIME,OP_NOTE)

 Values

   ('51124', '按质支付',900,'2008-06-06-14.03.02.000000', '此渠道为三星级,5%分成比例');

Insert into DD_TABLE1

   (GROUP_ID,PARAM_NAME,VALUE,OP_TIME,OP_NOTE)

 Values

   ('51124', '分时见效',1000,'2008-08-20-22.05.48.000000', '二返三返发展酬金');

   

--select * from (select rownum r,a.* from DD_TABLE1 a where rownum <=3 order by value) where r >= 3;   

--答案:

/*select t.GROUP_ID

  from (select rownum r, a.*

          from DD_TABLE1 a

         where rownum <= 3

         order by value) T

 where r >= 3;*/

 

row_number()函数 可排序也可分组

答案:

select *  from( 

select A.*,row_number()over(partition by PARAM_NAME order by GROUP_ID desc) RN

from DD_TABLE1 A  where A.PARAM_NAME='首付酬金') B

WHERE   RN=3

 

 

2.请写出查询 xjt1 表中存在xjt2表存在用户号码

   请写出查询 xjt1 表中不存在xjt2表存在用户号码

 

CREATE TABLE XJT1

(PHONE_NO INTEGER,                                                 --电话号码

NAME VARCHAR(20),                                                     --姓名

OPEN_TIME VARCHAR(50)                                                  --办理时间

);

INSERT INTO XJT1  VALUES (13909092110, 'a', '20090101');

INSERT INTO XJT1  VALUES (13795923070, 'b', '20100101');

INSERT INTO XJT1  VALUES (13890912880, 'c', '20070912');

INSERT INTO XJT1  VALUES (13778926770, 'd', '20100101');

INSERT INTO XJT1  VALUES (13458825100, 'e', '20060901');

 

CREATE TABLE XJT2

(PHONE_NO INTEGER     ,                                            --电话号码

 NAME VARCHAR (20),                                                     --姓名

 OPEN_TIME VARCHAR (50)                                                     --办理时间

);

 

INSERT INTO XJT2  VALUES (13458825100, 'a', '20060901');

INSERT INTO XJT2  VALUES (13778926770, 'b', '20100101');

INSERT INTO XJT2  VALUES (15284182050, 'c', '20070912');

INSERT INTO XJT2  VALUES (15181199330, 'd', '20100102');

INSERT INTO XJT2  VALUES (15196978260, 'e', '20100101');

--答案

select *

  from XJT1 A

 where exists (select 1 from XJT2 B where A.PHONE_NO = B.PHONE_NO);

 

select *

  from XJT1 A

 where not exists (select 1 from XJT2 B where A.PHONE_NO = B.PHONE_NO);

 

   

 3.关键字:CASE WHEN

题目:添加一列 显示以下信息

第一类:集团成员数<20户的,且集团离网率<=15% 显示为A

第二类:20户≤集团成员数<50户的,且集团离网率<=10% 显示为 B

第三类:50户≤集团成员数<100户的,且集团离网率<=6% 显示为C

第四类:100户≤集团成员数<200户的,且集团离网率<=4% 显示为D

第五类:集团成员数>=200户的,且集团离网率<=2%显示为E

其他显示为X

 

 

CREATE TABLE PDJ_GROUP

(

  GROUP_DETAIL_ID    INTEGER,   --集团编号

  CNT                INTEGER,   --集团成员数

  RATE               DECIMAL(10,2)--集团离网率

);

INSERT INTO PDJ_GROUP VALUES(76451,15,0.01);

INSERT INTO PDJ_GROUP VALUES(76452,45,0.04);

INSERT INTO PDJ_GROUP VALUES(76451,65,0.03);

INSERT INTO PDJ_GROUP VALUES(76452,100,0.08);

INSERT INTO PDJ_GROUP VALUES(76453,120,0.07);

INSERT INTO PDJ_GROUP VALUES(76453,200,0.1);

INSERT INTO PDJ_GROUP VALUES(76451,267,0.15);

INSERT INTO PDJ_GROUP VALUES(76452,35,0.04);

INSERT INTO PDJ_GROUP VALUES(76453,10,0.07);

INSERT INTO PDJ_GROUP VALUES(76454,78,0.08);

 

--答案:

SELECT A.*,

       CASE

         WHEN A.CNT < 20 AND A.RATE <= 0.15 THEN

          'A'

         WHEN A.CNT >= 20 AND A.CNT < 50 AND A.RATE <= 0.1 THEN

          'B'

         WHEN A.CNT >= 50 AND A.CNT < 100 AND A.RATE <= 0.06 THEN

          'C'

         WHEN A.CNT >= 100 AND A.CNT < 200 AND A.RATE <= 0.04 THEN

          'D'

         WHEN A.CNT >= 200 AND A.RATE <= 0.02 THEN

          'B'

          ELSE 'X'

       END "哈哈"

  FROM PDJ_GROUP A

 

 

 

4.请写出查询 dm_call_cdr_201005 表中字段 CALL_DURATION_M 通话分钟数最大的前6条记录,同时把 START_DATETIME 字段替换成日期型

   

   相关SQL

   CREATE TABLE  dm_call_cdr_201005 

(

  OP_TIME                 DATE   NOT NULL,

  OPPOSITE_NUMBER_OFF  VARCHAR(24),

  CALL_DURATION_M       VARCHAR (10),

  PHONE_NO               VARCHAR (12),

  IMEI                    VARCHAR (20),

  START_DATETIME        VARCHAR (26)

);

 

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'15908496676','23','13778900540','353966012877970','2010-05-05-00.05.15.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'15884113553','9' ,'13795820590','352373020164580','2010-05-05-00.06.08.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'13980392801','34','13558964110','355573023963220','2010-05-05-00.05.40.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'13778974438','23','13547714170','351580020086900','2010-05-05-00.03.53.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'15281445099','65','13629037850','352774014171470','2010-05-05-00.01.07.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'18784125110','6' ,'15884147720','359337036713310','2010-05-05-00.01.32.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'15883141643','33','15183129560','359659021720010','2010-05-05-00.00.36.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'15987035963','5' ,'15281444970','359753006625340','2010-05-05-00.01.37.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'1008611','13','15281401350','351818030078720','2010-05-05-00.02.47.000000');

insert into  dm_call_cdr_201005 values(to_date('2010-05-05','yyyy-mm-dd'),'18783176278','1' ,'13558953850','358380013494970','2010-05-05-00.02.04.000000');

 

--答案

select B.*

  from (select A.* ,cast(to_timestamp(A.START_DATETIME, 'syyyy-mm-dd hh24:mi:ss.ff') as date) timestamp_to_date

          from dm_call_cdr_201005 A

         order by to_number(CALL_DURATION_M) desc) B

 where rownum <= 6;

 

--select t.*  from dm_call_cdr_201005 t where rownum<=6 order by to_number(CALL_DURATION_M) desc;

--select * from table1 where rownum<=10

--select t.*  from dm_call_cdr_201005 t

 

 

5. 根据用户表、区县归属表,利用用户表里面的区县归属ID,请首先为区县ID创建索引,再以用户表为基础表。请查出用户属于翠屏区的所有工号。

 

  相关sql

  --用户表

  CREATE TABLE  BA_USER

(

ID                NUMBER(10),

  NAME              VARCHAR(80),

  LOGIN_NAME        VARCHAR(20),

  DISTRICT_ID       VARCHAR(10),

  IS_LOCKED         NUMBER(1)

);

insert into BA_USER VALUES(18,'郑宜萍','kaaf49','33',0 );

insert into BA_USER VALUES(19,'马亮', 'kaaf65','1044919',0);

insert into BA_USER VALUES(20,'罗悟', 'kbba01','53',0);

insert into BA_USER VALUES(21,'张贤敏','kbba03','53',0);

insert into BA_USER VALUES(22,'黄雪梅','kbba05','53',0);

 

--区县归属表

CREATE TABLE  BA_DISTRICT

(

  ID         VARCHAR(10)                  NOT NULL,

  PARENT_ID  VARCHAR(10),

  NAME       VARCHAR(255)                 NOT NULL,

  IN_USE     NUMBER(1)                          NOT NULL

);

 

insert into BA_DISTRICT values('12',' ','宜宾',1);

insert into BA_DISTRICT values('33','12','翠屏区',1);

insert into BA_DISTRICT values('1044919','33','城郊片区',1);

insert into BA_DISTRICT values('1002968','33','李庄片区',1);

insert into BA_DISTRICT values('53','12','宜宾县',1);

insert into BA_DISTRICT values('1044920','53','宜宾县渠道组',1);

insert into BA_DISTRICT values('121170','53','白花片区',1);

 

 

--为区县ID创建索引

--答案

CREATE INDEX IDX_BA_DISTRICT_ID ON BA_DISTRICT (ID)

 

--SELECT BU.* FROM  BA_USER BU LEFT JOIN BA_DISTRICT BD ON BU.DISTRICT_ID=BD.ID WHERE BD.NAME='翠屏区'

--查出用户属于翠屏区的所有工号

--答案

SELECT A.LOGIN_NAME as "翠屏区用户的工号"

  FROM BA_USER A

  LEFT JOIN BA_DISTRICT B

    ON A.DISTRICT_ID = B.ID

 WHERE B.NAME = '翠屏区'

 

 

 

 

 

 ---------------------------2019/11/4 黄泽东SQL练习2 BY PLSQL-----------------------------------------

 CREATE TABLE EMP(

 EMPNO NUMBER(4),

 ENAME VARCHAR2(10),

 JOB VARCHAR2(9),

 MGR NUMBER(4),

 HIREDATE DATE,

 SAL NUMBER(7,2),

 COMM NUMBER(7,2),

 DEPTNO NUMBER(2)

 )

INSERT INTO EMP VALUES(7369,'SMITH','CLERK',7902,to_date('1980-12-17','yyyy-mm-dd'),800,'',20);

INSERT INTO EMP VALUES(7499,'ALLEN','SALESMAN',7902,to_date('1981-2-20','yyyy-mm-dd'),1600,'',30);

INSERT INTO EMP VALUES(7521,'WAED','SALESMAN',7902,to_date('1981-2-22','yyyy-mm-dd'),1250,'',30);

INSERT INTO EMP VALUES(7566,'JONES','MANAGER',7902,to_date('1981-4-2','yyyy-mm-dd'),2975,'',20);

INSERT INTO EMP VALUES(7654,'MARTIN','SALESMAN',7902,to_date('1981-9-28','yyyy-mm-dd'),1250,'',30);

INSERT INTO EMP VALUES(7698,'BLAKE','MANAGER',7902,to_date('1981-5-1','yyyy-mm-dd'),2850,'',30);

INSERT INTO EMP VALUES(7782,'CLARK','MANAGER',7902,to_date('1981-6-9','yyyy-mm-dd'),2450,'',10);

INSERT INTO EMP VALUES(7788,'SCOTT','ANALYST',7902,to_date('1987-4-19','yyyy-mm-dd'),3000,'',20);

INSERT INTO EMP VALUES(7839,'KING','PRESIDENT',7902,to_date('1981-11-17','yyyy-mm-dd'),5000,'',10);

INSERT INTO EMP VALUES(7844,'TURNER','SALESMAN',7902,to_date('1981-9-8','yyyy-mm-dd'),1500,'',30);

INSERT INTO EMP VALUES(7876,'ADAMS','CLERK',7902,to_date('1987-5-23','yyyy-mm-dd'),1100,'',20);

INSERT INTO EMP VALUES(7900,'JAMES','CLERK',7902,to_date('1981-12-3','yyyy-mm-dd'),950,'',30);

INSERT INTO EMP VALUES(7902,'FORD','ANALYST',7902,to_date('1981-12-3','yyyy-mm-dd'),3000,'',20);

INSERT INTO EMP VALUES(7934,'MILLER','CLERK',7902,to_date('1982-12-23','yyyy-mm-dd'),1300,'',10);

 

CREATE TABLE DEPT(

DEPTNO NUMBER(4),

DNAME VARCHAR2(14),

LOC VARCHAR2(13)

);

INSERT INTO DEPT VALUES(10,'ACCOUNTING','NEW YORK');

INSERT INTO DEPT VALUES(20,'RESEARCH','DALLAS');

INSERT INTO DEPT VALUES(30,'SALES','CHICAGO');

INSERT INTO DEPT VALUES(40,'OPERATIONS','BOSTON');

 

SELECT ROWID, A.* FROM EMP A;

SELECT * FROM DEPT

 

------------------------------------题目及答案------------------------ 

1.请查找出雇员名称为ALLEN的部门和地址信息

SELECT B.DEPTNO 部门, B.LOC 地址信息

  FROM EMP A

  LEFT JOIN DEPT B

    ON A.DEPTNO = B.DEPTNO

 WHERE A.ENAME = 'ALLEN';

2.请找出出生年月在1985年以后,并且薪水在2000以上的人员信息

--一般不用extra 截取特定的年月日

/*SELECT *

  FROM EMP

 WHERE EXTRACT(YEAR FROM HIREDATE) > 1985

   AND SAL > 2000;*/

   

  SELECT *

  FROM EMP

 WHERE to_number(to_char(HIREDATE,'yyyy'))> 1985

   AND SAL > 2000;

 

3.在CHICAGO的员工工资提升10%,在DALLAS的员工工资提升20%,请使用case或者decode函数

--方法一case

SELECT B.LOC 地区,

       CASE

         WHEN B.LOC = 'CHICAGO' THEN

          SAL * (1 + 0.1)

         WHEN B.LOC = 'DALLAS' THEN

          SAL * (1 + 0.2)

         ELSE

          SAL

       END 工资

  FROM EMP A

  LEFT JOIN DEPT B

    ON A.DEPTNO = B.DEPTNO;

-- decode方法

语法:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值)

  SELECT B.LOC 地区,

         DECODE(B.LOC,'CHICAGO',SAL * (1 + 0.1),'DALLAS',SAL * (1 + 0.2),SAL) 工资

    FROM EMP A

    LEFT JOIN DEPT B

      ON A.DEPTNO = B.DEPTNO;

4.新进员工 张三,1988年3月15号出生,工资1200,经理是CLARK

自己加条件补充

 

显示所有雇员的平均工资、总计工资、最高工资、最低工资

SELECT ROUND(SUM(SAL) / COUNT(*), 2) 平均工资,

       SUM(SAL) 总计工资, MAX(SAL) 最高工资, MIN(SAL) 最低工资

  FROM EMP

  

5.使用exists语句显示BLAKE所在部门的其他所有雇员,但是不要显示BLAKE

WHERE EXISTS(子查询) ,子查询返回的的是TRUE OR FALSE 即使是 

SELECT * FROM DEPR WHERE EXISTS (SELECT NULL)

--正确写法

SELECT *

  FROM EMP B

 WHERE EXISTS

 (SELECT *

          FROM EMP C

         WHERE C.EMPNO = B.EMPNO

           AND C.ENAME <> 'BLAKE'

           AND C.DEPTNO =

               (SELECT A.DEPTNO FROM EMP A WHERE A.ENAME = 'BLAKE'))

 

 

;

/*SELECT B.DEPTNO

  FROM DEPT B

 WHERE NOT exists (SELECT A.DEPTNO

          FROM EMP A

         WHERE A.DEPTNO = B.DEPTNO

           AND A.ENAME = 'BLAKE')

*/

/*思路 1.查询其他所有雇员 又要求用exists 则首先确定外表是 EMP 内表是DEPT 查询结果所示A表在B表上的映射 又因为关联是DEPTID即  结果只能初步筛选出映射的所有DEPTNO,接下来考虑的是进一步筛选 

2.进一步筛选条件 根据BLAKE 可以得到确定的DEPTID,从而得到整个部门的雇员,最后筛选去除ENAME='BLAKE'即可*/

 

/*

错误的写法

SELECT T.ENAME 雇员名称, T.DEPTNO 部门编号

  FROM (SELECT B.DEPTNO, B.ENAME

          FROM EMP B

         WHERE exists

         (SELECT A.DEPTNO FROM DEPT A WHERE A.DEPTNO = B.DEPTNO)) T

 WHERE T.ENAME <> 'BLAKE'

   AND T.DEPTNO = (SELECT DEPTNO FROM EMP WHERE ENAME = 'BLAKE')*/

 /*  

 错误的写法

 SELECT T.ENAME 雇员名称, T.DEPTNO 部门编号

   FROM (SELECT * FROM EMP) T

  WHERE T.ENAME <> 'BLAKE'

    AND T.DEPTNO = (SELECT DEPTNO FROM EMP WHERE ENAME = 'BLAKE')

*/

 

SELECT * FROM EMP

SELECT * FROM EMP A WHERE EXISTS (SELECT * FROM EMP B WHERE B.JOB LIKE '%CLERK%' AND A.EMPNO=B.EMPNO)

6.部门平均工资低于2000的提升20%

--思考 显然查询的是所有部门 使用 右连接

 SELECT C.DNAME 部门名称 ,

        C.DEPTNO 部门编号,

        ROUND(C.SUM_SAL / C.NUMS) 平均工资,

        CASE

          WHEN ROUND(C.SUM_SAL / C.NUMS) < 2000 THEN

           ROUND(C.SUM_SAL / C.NUMS) * (1 + 0.2)

          ELSE

           ROUND(C.SUM_SAL / C.NUMS)

        END "提升20%后的工资"

   FROM (SELECT B.DEPTNO DEPTNO,

                B.DNAME DNAME,

                SUM(SAL) SUM_SAL,

                COUNT(*) NUMS

           FROM EMP A

          RIGHT JOIN DEPT B

             ON B.DEPTNO = A.DEPTNO

          GROUP BY (B.DEPTNO, B.DNAME)) C

 

      /* SELECT C.DNAME,C.DEPTNO DEPRNO, ROUND(C.SUM_SAL / C.NUMS )AVERAGE_SAL

          FROM (SELECT A.DEPTNO DEPTNO,B.DNAME DNAME, SUM(SAL) SUM_SAL, COUNT(*) NUMS

                  FROM EMP A RIGHT  JOIN  DEPT B ON B.DEPTNO = A.DEPTNO

                 GROUP BY(A.DEPTNO,B.DNAME) ) C*/

 

 

 

/*SELECT B.GROUP_ID,  B.PARAM_NAME ,ROUND(B.SAL/B.NUM,2)  FROM (

SELECT GROUP_ID, PARAM_NAME ,SUM(VALUE) SAL,COUNT(*) NUM  FROM DD_TABLE1 A  GROUP BY(PARAM_NAME,GROUP_ID) 

)B */

 

 

7.显示超过部门平均工资的所有雇员信息

--,lpad(T.SAL,5)填充在左侧 使其左对齐 

SELECT T.*,

       ROUND(C.SUM_SAL / C.NUMS, 2) 平均工资,

       CASE

         WHEN T.SAL > ROUND(C.SUM_SAL / C.NUMS, 2) THEN

          '是'

         ELSE  '否'

       END 是否超过平均工资

  FROM EMP T

  LEFT JOIN (SELECT B.DEPTNO DEPTNO,

                    B.DNAME DNAME,

                    SUM(SAL) SUM_SAL,

                    COUNT(*) NUMS

               FROM EMP A

              RIGHT JOIN DEPT B

                 ON B.DEPTNO = A.DEPTNO

              GROUP BY (B.DEPTNO, B.DNAME)) C

    ON C.DEPTNO = T.DEPTNO

 

8.  显示所有雇员的年收入(工资+补助+奖金),奖金是部门的平均工资的2倍

SELECT T.*,

       C.SUM_SAL 部门成员薪资总和,

       C.NUMS 部门成员数量,

       ROUND(C.SUM_SAL / C.NUMS, 2) AS 部门平均工资,

       T.SAL + NVL(T.COMM, 0) + ROUND(C.SUM_SAL / C.NUMS, 2) * 2 AS 年收入

  FROM EMP T

  LEFT JOIN (SELECT B.DEPTNO DEPTNO,

                    B.DNAME DNAME,

                    SUM(SAL) SUM_SAL,

                    COUNT(*) NUMS

               FROM EMP A

              RIGHT JOIN DEPT B

                 ON B.DEPTNO = A.DEPTNO

              GROUP BY (B.DEPTNO, B.DNAME)) C

    ON C.DEPTNO = T.DEPTNO

 

9. 使用row_number()rank 不使用max() min(),筛选出所有雇员中最大年分、最小年分的雇员信息

SELECT ENAME 入职最小年份员工名称, TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) 入职最小年份

  FROM EMP

 WHERE TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) =

       (SELECT B.FLAG_YEAR

          FROM (SELECT ROWNUM FLAG, A.FLAG_YEAR FLAG_YEAR, A.ENAME ENAME

                  FROM (SELECT TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) FLAG_YEAR,

                               ENAME,

                               ROW_NUMBER() OVER(PARTITION BY TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) ORDER BY HIREDATE ASC) RN

                          FROM EMP 

                         ORDER BY HIREDATE ASC) A) B

         WHERE B.FLAG = 1

         );

 

 SELECT ENAME 入职最大年份员工名称,

        TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) 入职最大年份

   FROM EMP

  WHERE TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) =

        (SELECT B.FLAG_YEAR

           FROM (SELECT ROWNUM FLAG, A.FLAG_YEAR FLAG_YEAR, A.ENAME ENAME

                   FROM (SELECT TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) FLAG_YEAR,

                                ENAME,

                                ROW_NUMBER() OVER(PARTITION BY TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) ORDER BY HIREDATE ASC) RN

                           FROM EMP

                          ORDER BY HIREDATE DESC) A) B

          WHERE B.FLAG = 1);

       

                   

 

 

 /*SELECT ENAME 最小年份雇员名称,TO_NUMBER(TO_CHAR(HIREDATE,'YYYY')) 雇员入职最小年份

  FROM EMP 

 WHERE TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) =

       (SELECT C.FLAG_YEAR 最大年份

          FROM (SELECT ROWNUM, B.FLAG_YEAR FLAG_YEAR

                  FROM (SELECT A.HIREDATE ,TO_NUMBER(TO_CHAR(HIREDATE, 'YYYY')) FLAG_YEAR,

                               ROW_NUMBER() OVER(PARTITION BY HIREDATE ORDER BY HIREDATE ASC) RN

                          FROM EMP A ORDER BY HIREDATE ASC

                        ) B

                 WHERE  ROWNUM = 1) C);

           */

 

10. 使用row_number()rank 不使用max() min(),筛选出【部门】最大生日、最小生日的雇员信息

SELECT D.DEPTNO 部门编号, E.MAX_HIAREDATE 部门最大生日员工信息, E.MIN_HIAREDATE 部门最小生日员工信息

  FROM DEPT D

  LEFT JOIN (SELECT B.DEPTNO,

                    B.MIN_HIAREDATE MIN_HIAREDATE,

                    (SELECT C.MAX_YEAR

                       FROM (SELECT A.HIREDATE MAX_YEAR, A.DEPTNO DEPTNO

                               FROM (SELECT EMP.*,

                                            ROW_NUMBER() OVER(PARTITION BY DEPTNO ORDER BY HIREDATE DESC) RN

                                       FROM EMP) A

                              WHERE A.RN = 1) C

                      WHERE C.DEPTNO = B.DEPTNO) MAX_HIAREDATE

               FROM (SELECT A.DEPTNO   DEPTNO,

                            A.ENAME,

                            A.HIREDATE MIN_HIAREDATE

                       FROM (SELECT EMP.*,

                                    ROW_NUMBER() OVER(PARTITION BY DEPTNO ORDER BY HIREDATE ASC) RN

                               FROM EMP) A

                      WHERE A.RN = 1) B) E

    ON D.DEPTNO = E.DEPTNO

 

 

 

select * from EMP where rownum<=10

 

 

SELECT DEPTNO FROM EMP GROUP BY EMP.DEPTNO HAVING 

 

SELECT DEPTNO FROM EMP WHERE DEPTNO >10 GROUP BY EMP.DEPTNO

 

 

 

 

 

DDL: 1.建表CREATE TABLE  修改表结构,添加,删,除,修改列长度 ALERT TABLE   删除表DROP TABLE 建立索引 CREATE INDEX  删除索引DROP INDEX

DML: INSERT DELETE UPDATE SELECT

DCL: GRANT 授予访问权限  REVOKE撤销访问权限  COMMIT提交事务处理  ROLLBACK事务处理回退 SAVEPOINT 设置保存点  LOCK 对数据库的特定部分进行锁定

 

 

 

1.常用函数

a.查询时间。指定格式

to_char(creation_date,'yyyy--mm--dd')

to_date('2019/11/2') 

select to_char(sysdate),to_char(sysdate,'yyyy-MM-dd HH24:mm:ss'), to_date(sysdate),to_date(to_char(sysdate,'yyyy-MM-dd'),'yyyy-MM-dd')from dual
where to_char(sysdate,'yyyy-MM-dd')='2019-11-02'

 单行函数

 

 字符函数分为 

a.大小写控制函数  :小写 lower() 大写upper()  首字母大写 initcap()

b.字符控制函数: 连接concat  截取函数substr  取得长度length  获取位置instr  左对齐 不足的位置用*替代 lpad  右对齐 rpad   trim去掉首尾的指定的字符串  replace

 

 数值函数分为

 

 

 

 

多行函数

 赋值 :=

[范围包括边界]: between and 

like 'a%' 首位是a

like '%a'  末尾是a

like '_a%' 第二位是a

like '%a%'  含有a的任意

***********  like '%_%'含有空格的的名字 不是表示有下划线

应该这样写 like '%\_%' escape '\' 或者 应该这样写 like '%#_%' escape '#'  多种写法

 取别名 1.直接在查询字段后加名字 或者双引号 2。字段后加上as 再加别名或者双引号

|| 连接

distinct 去重

运算优先级

 

 

order by在结尾,在where后

oracle备份数据

1. 使用plsql

2.使用wndows 批处理脚本 + windows定时任务

 

 

--触发器测试
create or replace trigger update_hzd_table_trigger
after
update on hzd_table
for each row
begin dbms_output.put_line('触发器测试') ;
end;

update hzd_table ht set ht.age=19 where ht.age<55



posted @ 2019-11-02 20:14  琉璃青了谁的眸  阅读(355)  评论(0编辑  收藏  举报