SQL和PLSQL

本文通过实际案例展示了如何使用SQL进行数据查询与处理,包括纠正语法错误、查询特定信息、利用回收站恢复数据以及编写PL/SQL块进行复杂的数据分析与更新。


过滤和排序.txt

SQL>--where

SQL>--查询工资大于2500的员工信息

SQL>select *

  2  formemp

  3 where sal>2500;

form emp

*

2 行出现错误:

ORA-00923:未找到要求的 FROM 关键字

SQL>ed

已写入 file afiedt.buf

 

  1 select *

  2  formemp

  3* where sal>2500

SQL> /

form emp

*

2 行出现错误:

ORA-00923:未找到要求的 FROM 关键字

 

SQL> 2

  2* form emp

SQL> c/form/from

  2* from emp

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7566 JONES      MANAGER         7839 02-4 -81      2975                    20                                  

 

SQL>--查询KING的信息

SQL>select *

  2  fromemp

  3 where ename='king';

 

未选定行

 

SQL>ed

已写入 file afiedt.buf

 

  1 select *

  2  fromemp

  3* where ename='KING'

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                   

      7839 KING       PRESIDENT            17-11-81     5000                    10                                  

 

SQL>--日期:查询17-11-81入职的员工

SQL>select *

  2  fromemp

  3 where hiredate='17-11-81';

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7839 KING       PRESIDENT            17-11-81     5000                    10                                  

 

SQL>select *

  2  fromemp

  3 where hiredate='1987-11-17';

wherehiredate='1987-11-17'

               *

3 行出现错误:

ORA-01861:文字与格式字符串不匹配

 

SQL> --查看当前日期格式

SQL>select sysdate from dual;

 

SYSDATE                                                                                                                

--------------                                                                                                         

15-8 -11                                                                                                             

SQL>--查询系统设置

SQL>select * from v$nls_parameters;

 

SQL>col value for a30

SQL> /

PARAMETER                                                       VALUE                                                 

----------------------------------------------------------------------------------------------                        

NLS_LENGTH_SEMANTICS                                            BYTE                                                  

NLS_NCHAR_CONV_EXCP                                             FALSE                                                 

 

已选择19行。

 

SQL>--修改日期格式

SQL>alter session set nls_date_format='yyyy-mm-dd';

 

会话已更改。

 

SQL>select *

  2  fromemp

  3 where hiredate='1987-11-17';

 

SQL>where hiredate='1981-11-17';

SP2-0734:未知的命令开头 "where hire..." - 忽略了剩余的行。

SQL>select *

  2  fromemp

  3 where hiredate='1981-11-17';

 

     EMPNO ENAME      JOB              MGR HIREDATE     SAL      COMM     DEPTNO                                      

-------------------- --------- ---------- ---------- ----- ---------- ----------                                      

      7839 KING       PRESIDENT            1981-11-17  5000                    10                                      

 

SQL>alter session set nls_date_formate='DD-MON-RR';

altersession set nls_date_formate='DD-MON-RR'

*

1 行出现错误:

ORA-00922:选项缺失或无效

SQL> altersession set nls_date_format='DD-MON-RR';

会话已更改。

 

SQL>--日期:格式问题(隐式转换、显示转换)

SQL>host cls

SQL>--between..and

SQL>--查询工资位于1000~2500的员工

SQL>select * from emp where sal>=1000 and sal<=2500;

  

SQL>select * from emp where sal>=1600 and sal<=2500;

SQL>select * from emp where sal between 1600 and 2500;

SQL>select * from emp where sal between 2500 and 1600;

SQL>--注意:小值在前,大值在后

SQL>--in:在集合中

SQL>--查询部门号为10 20的员工

SQL>select * from emp where deptno=10 or deptno=20;

SQL>select * from emp where deptno in(10,20);

SQL>host cls

 

SQL>--模糊查询

SQL>--查询姓名以S打头的员工

SQL>select *

  2  fromemp

  3 where ename like 'S%';

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

      7788 SCOTT      ANALYST         7566 13-7 -87      3000                    20                                  

 

已选择2行。

SQL>--查询姓名为四个字符的员工信息

SQL>select *

  2  fromemp

  3 where ename like '____';

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7521 WARD       SALESMAN        7698 22-2 -81     1250        500         30                                  

      7839 KING       PRESIDENT            17-11-81     5000                    10                                  

      7902 FORD       ANALYST         7566 03-12-81      3000                    20                                   

已选择3行。

SQL>insert into emp(empno,ename) values(1234,'Tom_123');

已创建 1 行。

SQL>--查询姓名中含义下划线的员工

SQL>select *

  2  fromemp

  3 where ename like '%_%';

SQL>select *

  2  fromemp

  3 where ename like '%\_%' escape '\';

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      1234 Tom_123                                                                                                     

已选择 1 行。

SQL>select *

  2  fromemp

  3 where ename like '%a_%' escape 'a';

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      1234 Tom_123                                                                                                     

已选择 1 行。

SQL>host cls

 

SQL>--排序 order by

SQL>--按照月薪排序

SQL>select *

  2  fromemp

  3 order by sal;

SQL>--a命令: append

SQL> adesc;

  3* order by saldesc

SQL>select *

  2  fromemp

  3 order by sal;

SQL>a  desc;

  3* order by sal desc

SQL> /

SQL>--a:两个空格

SQL>host cls

SQL>--order by后面可以跟哪些:1. 列名 2. 别名  3.序号

SQL>--按照年薪排序

SQL>select ename,sal,sal*12 年薪

  2  fromemp

  3 order by 年薪;

 

ENAME        SAL       年薪                                                                                            

--------------- ----------                                                                                            

SMITH        800       9600                                                                                            

JAMES        950     11400                                                                                            

 

SQL>select ename,sal,sal*12 年薪

  2  fromemp

  3 order by 3;

 

ENAME        SAL       年薪                                                                                            

--------------- ----------                                                                                            

SMITH        800       9600                                                                                            

 

SQL>--查询员工的信息,要求按照奖金排序

SQL>select *

  2  fromemp

  3 order by comm;

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7844 TURNER     SALESMAN        7698 08-9 -81     1500          0         30                                  

      7499 ALLEN      SALESMAN        7698 20-2 -81     1600        300         30                                  

SQL>delete from emp where empno=1234;

已删除 1 行。

SQL>select *

  2  fromemp

  3 order by comm;

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                   

      7844 TURNER     SALESMAN        7698 08-9 -81     1500          0         30                                  

SQL>a  desc;

  3* order by comm desc

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

 

SQL>--将空值排到最后

SQL>select *

  2  fromemp

  3 order by comm desc

  4 nulls last;

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7654 MARTIN     SALESMAN        7698 28-9 -81     1250       1400         30                                  

   

SQL>select *

  2  fromemp

  3 order by deptno,sal;

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7934 MILLER     CLERK           7782 23-1 -82      1300                    10                                  

    

SQL>a  desc;

  3* order by deptno,sal desc

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                   

      7839 KING       PRESIDENT            17-11-81     5000                    10                                  

    

SQL>ed

已写入 file afiedt.buf

 

  1 select *

  2  fromemp

  3* order by deptno desc,sal desc

SQL> /

 

    EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7698 BLAKE      MANAGER         7839 01-5 -81      2850                    30                                  

     

SQL>--升序和降序只作用于最近的一列

SQL>--order by作用于多列:先按照第一列排序;然后按照第二列排序;以此类推;

SQL>spool off

 

SQL>--清屏

SQL>host cls

 

SQL>--linux清屏: host clear

SQL>--当前用户下的表

SQL>select * from tab;

 

TNAME                          TABTYPE  CLUSTERID                              

------------------------------------- ----------                              

DEPT                           TABLE                                            

EMP                            TABLE                                           

BONUS                          TABLE                                           

SALGRADE                       TABLE                                            

 

SQL>--emp表的结构

SQL>desc emp;

 名称                                      是否为空? 类型

 ------------------------------------------------- ----------------------------

 EMPNO                                     NOT NULLNUMBER(4)

 ENAME                                              VARCHAR2(10)

SQL>--查询员工所有信息

SQL>select * from emp;

 

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM

SQL>--设置行宽

SQL>set linesize 120

SQL>--设置列宽

SQL>col sal for 9999

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

    

SQL>--设置页大小

SQL>set pagesize 20

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                   

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                   

    

SQL>set feedback off

SQL> /

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                   

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>set feedback on

SQL>--通过列名

SQL>select empno,ename,job,mgr,hiredate,sal,comm,deptno

  2  fromemp;

 

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

-------------------- --------- ---------- -------------- ----- ---------- ----------                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

 

SQL>--问题:*和列名哪种性能好?

SQL>--Oracle9i之前,列名>*

SQL>host cls

 

SQL>--具体的列

SQL>--查询员工的编号,姓名,月薪

SQL>select empno,ename,sal form emp;

select empno,ename,salform emp

                            *

1 行出现错误:

ORA-00923:未找到要求的 FROM 关键字

 

 

SQL>--c命名修改

SQL> c/form/from

  1* select empno,ename,sal from emp

SQL> /

 

     EMPNO ENAME        SAL                                                                                            

-------------------- -----                                                                                            

      7369 SMITH        800                                                                                            

   

SQL>--通过ed命令

SQL>select empno,ename,sal form emp;

selectempno,ename,sal form emp

                            *

1 行出现错误:

ORA-00923:未找到要求的 FROM 关键字

 

 

SQL>ed

已写入 file afiedt.buf

 

  1* select empno,ename,sal from emp

SQL> /

 

     EMPNO ENAME        SAL                                                                                                                                                                                  

      7369 SMITH        800                                                                                             

  

SQL>--别名: 1. as 2.  as可以省略 3. 跟双引号

SQL>select empno as 员工编号, ename 姓名, sal "姓名"

  2  fromemp;

 

  员工编号 姓名             姓名                                                                                       

-------------------- ----------                                                                                       

      7369 SMITH             800                                                                                       

 

SQL>--问题: 有无双引号的区别?

SQL>host cls

 

SQL>--select含义算术表达式

SQL>--查询员工,编号,姓名,月薪,年薪

SQL>select empno,ename,sal 月薪, sal*12 年薪

  2  fromemp;

 

     EMPNO ENAME            月薪       年薪                                                                                                                                                      

      7369 SMITH             800       9600                                                                             

SQL>--查询员工信息,编号,姓名,月薪,年薪,奖金,年收入

SQL>select empno,ename,sal 月薪, sal*12 年薪, comm 奖金, sal*12+comm 年收入

  2  fromemp;

 

     EMPNO ENAME            月薪       年薪       奖金     年收入                                                                                                        

      7369 SMITH             800       9600                                                                            

    

SQL>/*

SQL>sql里面,关于空值的使用:

SQL>1. 如果一个表达式中含空值,则整个表达式为空

SQL>2. null != null

SQL>*/

SQL>--查询奖金为空的员工信息

SQL>select *

  2  fromemp

  3 where comm =null;

未选定行

SQL>--1. 使用滤空函数 null-->0

SQL>select empno,ename,sal 月薪, sal*12 年薪, comm 奖金, sal*12+nvl(comm,0) 年收入

  2  fromemp;

     EMPNO ENAME            月薪       年薪       奖金     年收入                                                                                                            

      7369 SMITH             800       9600                  9600                                                      

  

SQL>2. is或者is not

SP2-0734:未知的命令开头 "2. is或者i..." - 忽略了剩余的行。

SQL>-- 2. is或者is not

SQL> select*

  2  fromemp

  3 where comm is null;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                               

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                   

SQL>--查询员工的部门号

SQL>select depnto from emp;

selectdepnto from emp *

1 行出现错误:

ORA-00904:"DEPNTO": 标识符无效

SQL>select deptno from emp;

    DEPTNO                                                                                                             

                                                                                                             

        20                                                                                                              

     

SQL>select distince deptno from emp;

selectdistince deptno from emp

       *

1 行出现错误:

ORA-00904:"DISTINCE": 标识符无效

 

SQL> selectdistinct deptno from emp;

    DEPTNO                                                                                                                                                                                                                           

        30                                                                                                             SQL>--distinct如果作用于多列?

SQL>select distinct job,deptno from emp;

 

JOB           DEPTNO                                                                                                                                                                                                   

MANAGER           20                                                                                                   

SQL>--只有多列全部相同,才会认为是相同

SQL>host cls

 

SQL>--连接符: ||

SQL>--显示 Hello World

SQL>select 'hello' || ' world' from dual;

'HELLO'||'W                                                                                                                                                                                                                     

helloworld                                                                                                            

已选择 1 行。

SQL>--oracle一个伪表dual:1.满足语法 2. 方便做测试

SQL>select 3+2 from dual;

       3+2                                                                                                                                                                                                                        

         5                                                                                                             

已选择 1 行。

SQL>--查询员工的信息:*** 的工资是***

SQL>select ename||'的工资是'||sal

  2  fromemp;

 

ENAME||'的工资是'||SAL                                                                                                  

----------------------------------------------------------                                                             

SMITH的工资是800                                                                                                        

SQL>spool off

如何手动解锁帐号和设置密码:

1. 管理员登录

   *. 密码认证:sqlplus sys/password as sysdba

   *. 主机认证:sqlplus / as sysdba (前提:操作系统的用户即为数据库管理员)

2. 解锁:

   alter user scott account unlock;

3. 改密码:

   alter user scott identified by paas123;

SQL>--大小写函数

SQL>select lower('HELLO WORLD')  转小写, upper('hEhllo WorLD') 转大写 from dual;

转小写      转大写                                                                                                     

-----------------------                                                                                               

helloworld HEHLLO WORLD                                                                                               

 

已选择 1 行。

SQL>--首字母大写

SQL>select initcap('hello world') 首字母大写  fromdual

  2  ;

首字母大写                                                                                                                                                                                                                         

HelloWorld                                                                                                            

已选择 1 行。

SQL>--显示hello word

SQL>select concat('hello',' world') from dual;

CONCAT('HEL                                                                                                                                                                                                                     

helloworld                                                                                                            

已选择 1 行。

SQL>--substr: 求子串

SQL>select substr('Hello World',3) from dual;

SUBSTR('H                                                                                                                                                                                                                          

lloWorld                                                                                                              

已选择 1 行。

SQL>select substr('Hello World',3,5) from dual;

SUBST                                                                                                                                                                                                                                    

lloW                                                                                                                  

已选择 1 行。

SQL>host cls

SQL>--length:字符数; lengthb:字节数

SQL>select length('hello world') 字符数, lengthb('hello world') 字节数 from dual;

    字符数     字节数                                                                                                                                                                                              

        11         11                                                                                                  

已选择 1 行。

SQL>select lenght('中国') 字符数, lengthb('中国') 字节数 from dual;

selectlenght('中国') 字符数, lengthb('中国') 字节数 from dual   

1 行出现错误:

ORA-00904:"LENGHT": 标识符无效

SQL>select length('中国') 字符数, lengthb('中国') 字节数 from dual;

    字符数     字节数                                                                                                                                                                                              

         2          4                                                                                                  

已选择 1 行。

SQL>host cls

SQL>--instr: 求子串的位置

SQL>select instr('hello world','ll') from dual;

INSTR('HELLOWORLD','LL')                                                                                                                                                                                          

                       3                                                                                               

已选择 1 行。

SQL>select instr('hello world','abc') from dual;

INSTR('HELLOWORLD','ABC')                                                                                                                                                                                            

                        0                                                                                              

已选择 1 行。

SQL>--左右填充: abcd --> 10, 并且用*填充

SQL>select lpad('abcd',10,'*') 左填充,rpad('abcd',10,'*') 右填充 from dual;

左填充     右填充                                                                                                                                                                                                        

******abcdabcd******                                                                                                  

已选择 1 行。

SQL>--trim:去掉字符串前后的指定的字符

SQL>select trim('H' from 'Hello WorldH') from dual;

TRIM('H'FR                                                                                                                                                                                                                         

elloWorld                                                                                                             

已选择 1 行。

SQL>--替换:

SQL>select replace('Hello World','l','*') from dual;

REPLACE('HE                                                                                                                                                                                                                   

He**oWor*d                                                                                                            

已选择 1 行。

SQL>select ename from emp;

ENAME                                                                                                                                                                                                                          

SMITH   

                                                                                                              

SQL>host cls

SQL>--数字函数

SQL>select round(45.926,2) 四舍五入, trunc(45.926,2) 截断, mod(1600,300) 求于 from dual;

  四舍五入       截断       求于                                                                                                                                                                             

     45.93     45.92        100                                                                                        

已选择 1 行。

SQL>--日期函数

SQL>select sysdate from dual;

SYSDATE                                                                                                                                                                                                                       

15-8 -11                                                                                                             

已选择 1 行。

SQL>host cls

SQL>--昨天,今天,明天

SQL> selectsysdate-1 昨天, sysdate 今天, sysdate+1 明天 from dual;

昨天           今天           明天                                                                                                                                                            

14-8 -11     15-8 -11    16-8 -11                                                                               

已选择 1 行。

SQL>--计算员工的工龄

SQL>select ename, sysdate-hiredate from emp;

ENAME                                                                                                                                                                                                               

SMITH      11198.6066                                                                                                   

SQL>--日期能相加吗?

SQL>select ename, sysdate+hiredate  from emp;

selectename, sysdate+hiredate  from emp

                     *

1 行出现错误:

ORA-00975:不允许日期 + 日期

SQL>host cls

SQL>--计算员工的工龄,分别以天,月,年方式显示

SQL>select ename, sysdate-hiredate , (sysdate-hiredate)/7 星期, (sysdate-hiredate)/30

  2  fromemp;

ENAME                     星期                                                                                                                                                              

SMITH      11198.6088 1599.80126  373.28696                                                                            

SQL>select ename,(sysdate-hiredate)/30 , months_between(sysdate,hiredate) 方式二 from emp;

ENAME                   方式二                                                                                                                                                                            

SMITH      373.287032 367.955193                                                                                        

SQL>--add_months: 在指定的时间上加上月数

SQL>--123月后

SQL>select add_months(sysdate,123) from dual;

ADD_MONTHS(SYS                                                                                                                                                                                                               

15-11-21                                                                                                             

已选择 1 行。

SQL>--本月的最后一天

SQL>select last_day(sysdate) from dual;

LAST_DAY(SYSDA                                                                                                                                                                                                                  

31-8 -11                                                                                                             

已选择 1 行。

SQL>host cls

SQL>--next_day:从某个时间算起,下一个出现该星期几的日期

SQL>select next_day(sysdate,'星期一') from dual;

NEXT_DAY(SYSDA                                                                                                                                                                                                                

22-8 -11                                                                                                             

已选择 1 行。

SQL>host cls

SQL>--对日期进行四舍五入

SQL>select round(sysdate,'month'), round(sysdate,'year') from dual;

ROUND(SYSDATE,ROUND(SYSDATE,                                                                                                                                                                                  

01-8 -11     01-1 -12                                                                                              

已选择 1 行。

SQL>--对日期进行截断

SQL>select trunc(sysdate,'month'),trunc(sysdate,'year') from dual;

TRUNC(SYSDATE,TRUNC(SYSDATE,                                                                                                                                                                                  

01-8 -11     01-1 -11                                                                                              

已选择 1 行。

SQL>select sysdate from dual;

SYSDATE                                                                                                                                                                                                                  

15-8 -11                                                                                                             

已选择 1 行。

SQL>--RR:表示年,有问题吗?

SQL>--千年虫问题

SQL>host cls

SQL>--显示当前系统时间

SQL>select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY                                                                                                                                                                                                     

2011-08-1514:58:35                                                                                                     

已选择 1 行。

SQL>--今天星期几

SQL>select to_char(sysdate,'day') from dual;

TO_CHAR(S                                                                                                                                                                                                                            

星期一                                                                                                                 

已选择 1 行。

SQL>--格式化显示日期: 今天是2011-08-15,现在时间14:58:35

SQL>select to_char(sysdate,'"今天是"yyyy-mm-dd "现在时间"hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'"今天是"YYYY-MM-                                                                                                                                                                       

今天是2011-08-15 现在时间15:01:03                                                                                      

已选择 1 行。

SQL>host cls

SQL> select* from v$nls_parameters;

PARAMETER                                                        VALUE                                                             

NLS_LANGUAGE                                                    SIMPLIFIED CHINESE                                    

SQL>host cs

SQL>--查询员工的工资,要求有千位符,货币代码,两位小数

SQL>select ename,to_char(sal,'L9,999.99') from emp;

ENAME      TO_CHAR(SAL,'L9,999                                                                                                                                                                              

SMITH                 800.00                                                                                         

SQL>select to_number('123') from dual;

 

TO_NUMBER('123')                                                                                                                                                                                                      

             123                                                                                                       

已选择 1 行。

SQL>host cls

SQL>select *

  2  fromemp

  3 where hiredate=to_date('1981-12-17','yyyy-mm-dd');

未选定行

SQL>select *

  2  fromemp

  3 where hiredate=to_date('1981-11-17','yyyy-mm-dd');

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                   

      7839 KING       PRESIDENT            17-11-81     5000                    10                                   

已选择 1 行。

SQL>--通用函数

SQL>--滤空函数: nvl(a,b):a为空时,返回b,反则返回a

SQL>--          nvl2(a,b,c):a为空时,返回c;否则返回b;

SQL>select ename,sal,sal*12 年薪, comm 奖金, sal*12+nvl2(comm,comm,0) 年收入 from emp;

ENAME        SAL       年薪       奖金     年收入                                                                                                                                         

SMITH        800       9600                  9600                                                                      

SQL>host cls

SQL>--nullif(a,b):a=b时,返回null;不等时,返回a

SQL>select nullif('abc','abc') from dual;

NUL                                                                                                                                                                                                                                                                                                                                                            

已选择 1 行。

SQL>select nullif('abc','abcd') from dual;

NUL                                                                                                                     

---                                                                                                                    

abc                                                                                                                     

已选择 1 行。

SQL>host cls

SQL>--COALESCE: 找到蚕食;列表中,第一个不为空的值

SQL>select ename,sal,comm,COALESCE(comm,sal) 第一个不为空 from emp;

ENAME        SAL       COMM 第一个不为空                                                                                                                                                         

SMITH        800                     800                                                                               

SQL>host cls

SQL>--背景:根据不同的工种涨工资

SQL>select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                      

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>--总裁涨1000,经理800,其他员工600

SQL>--使用case表达式

SQL>select ename,job,sal 涨前工资, case job when 'PRESIDENT' then sal+100

  2                                          when'MANAGER'   then sal+800

  3                                          elsesal+400

  4                                 end 涨后工资

  5  fromemp;

 

ENAME      JOB        涨前工资  涨后工资                                                                                                                                                        

SMITH      CLERK            800       1200                                                                              

SQL>select ename,job,sal 涨前工资, decode(job,'PRESIDENT',sal+1000,

  2                                           'MANAGER',  sal+800,

  3                                                       sal+400) 涨后工资

  4  fromemp;

ENAME      JOB         涨前工资   涨后工资                                                                                                                                                         

SMITH      CLERK            800       1200                                                                              

SQL>spool off

SQL>/*

SQL>Oracle中支持的连接类型:

SQL>1. 等值连接

SQL>2. 不等值连接

SQL>3. 外连接

SQL>4. 自连接

SQL>*/

SQL>--等值连接

SQL>--查询员工的信息,要求显示员工编号,姓名,月薪和部门名称

SQL>select e.empno,e.ename,e.sal,d.dname

  2  fromemp e,dept d

  3 where e.deptno=d.deptno;

     EMPNO ENAME        SAL DNAME                                                                                                                                                                   

      7369 SMITH        800 RESEARCH                                                                                   

SQL>--不等值连接

SQL>--查询员工信息,要求显示工资级别

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                                                                                                    

DEPT                           TABLE                                                                                   

SQL>select * from salgrade;

     GRADE     LOSAL      HISAL                                                                                                                                                                             

         1        700       1200                                                                                        

SQL>select e.ename,e.sal,s.grade

  2  fromemp e,salgrade s

  3 where e.sal between s.losal and s.hisal

  4  ;

ENAME        SAL     GRADE                                                                                                                                                                             

SMITH        800          1                                                                                            

SQL>--按部门查询员工人数

SQL>--要求,显示部门编号,部门名称,人数

SQL>select d.deptno,d.dname,count(e.empno)

  2  fromemp e, dept d

  3 where e.deptno=d.deptno;

selectd.deptno,d.dname,count(e.empno)

       *

1 行出现错误:

ORA-00937:不是单组分组函数

SQL>select d.deptno,d.dname,count(e.empno)

  2  fromemp e, dept d

  3 where e.deptno=d.deptno

  4 group by d.deptno,d.dname;

    DEPTNO DNAME          COUNT(E.EMPNO)                                                                                                                                                         

        10 ACCOUNTING                  3                                                                               

       

SQL>--这个结果对吗?

SQL>select * from dept;

 

    DEPTNO DNAME          LOC                                                                                                                                                                    

        10 ACCOUNTING     NEW YORK                                                                                     

SQL>--外连接:当等值连接条件不成立时,任然希望某些记录出现的结果中

SQL>-- 左外连接,和右外连接

SQL>--右外连接:条件不成立时,等号右边的任然显示,写法:where e.deptno(+)=d.deptno

SQL>--左外连接:条件不成立时,,等号左边的任然显示,写法:where e.deptno =d.deptno(+)

SQL>select d.deptno,d.dname,count(e.empno)

  2  fromemp e, dept d

  3 where e.deptno(+)=d.deptno

  4 group by d.deptno,d.dname;

    DEPTNO DNAME          COUNT(E.EMPNO)                                                                                                                                                          

        10 ACCOUNTING                  3                                                                               

SQL>host cls

SQL>--查询员工信息,要求显示:***的老板是***

SQL>select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                   

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                   

 

SQL>--自连接:通过表的别名,将同一张表视为不同表,然后再利用等值、不等值、外连接进行操作

SQL>select e.ename||'的老板是'||b.ename

  2  fromemp e,emp b

  3 where e.mgr=b.empno;

E.ENAME||'的老板是'||B.ENAME                                                                                                                                                                                       

FORD的老板是JONES                                                                                                      

 

SQL>--问题:自连接存在什么问题?

SQL>--性能问题

SQL>--自连接只适用于小表

SQL>--为了解决自连接的性能问题,Oracle提出了层次查询

SQL>--伪列:level

SQL>--层次查询:同一张表的前后两次查询,进行连接操作

SQL>select level,empno,ename,mgr

  2  fromemp

  3 connect by prior empno=mgr

  4 start with empno=7839

  5 order by level;

     LEVEL     EMPNO ENAME             MGR                                                                                                                                                      

         1      7839 KING                                                                                             

      

SQL>--打开sql执行的时间开关

SQL>

SQL>set timing on

SQL>  select e.ename||'的老板是'||b.ename

  2  from emp e,emp b

  3  where e.mgr=b.empno;

 

E.ENAME||'的老板是'||B.ENAME                                                                                           

FORD的老板是JONES                                                                                                      

已用时间:  00: 00: 00.01

SQL>select level,empno,ename,mgr

  2  fromemp

  3 connect by prior empno=mgr

  4 start with empno=7839

  5 order by level;

     LEVEL     EMPNO ENAME             MGR                                                                            

         1      7839 KING                                                                                             

 

已用时间:  00: 00: 00.39

SQL>set timing off

SQL>spool off

SQL>--sum函数

SQL>--求员工工资的总和

SQL>select sum(sal) from emp;

  SUM(SAL)                                                                                                                                                                                                                          

     29025                                                                                                             

已选择 1 行。

SQL>--count函数:求个数

SQL>--求员工的人数

SQL>select count(*) from emp;

  COUNT(*)                                                                                                                                                                                                                         

        14                                                                                                             

已选择 1 行。

SQL>--求平均工资

SQL>select sum(sal)/count(*) from emp;

SUM(SAL)/COUNT(*)                                                                                                                                                                                                        

       2073.21429                                                                                                      

已选择 1 行。

SQL>select avg(sal) from emp;

  AVG(SAL)                                                                                                                                                                                                                          

2073.21429                                                                                                             

已选择 1 行。

SQL>host cls

SQL>--求奖金的总额

SQL>select sum(comm) from emp;

 SUM(COMM)                                                                                                                                                                                                                       

      2200                                                                                                             

已选择 1 行。

SQL>--求平均奖金

SQL>select sum(comm)/count(*) from emp;

SUM(COMM)/COUNT(*)                                                                                                                                                                                                            

        157.142857                                                                                                     

已选择 1 行。

SQL>select avg(comm) from emp;

 AVG(COMM)                                                                                                                                                                                                                     

       550                                                                                                             

已选择 1 行。

SQL>--组函数会自动滤空

SQL>select sum(comm)/count(comm) from emp;

SUM(COMM)/COUNT(COMM)                                                                                                                                                                                                 

                  550                                                                                                  

已选择 1 行。

SQL>select count(comm) from emp;

COUNT(COMM)                                                                                                                                                                                                                     

          4                                                                                                            

已选择 1 行。

SQL>  select sum(comm)/count(nvl(comm,0)) from emp;

SUM(COMM)/COUNT(NVL(COMM,0))                                                                                                                                                                                    

                  157.142857                                                                                           

已选择 1 行。

SQL>select count(nvl(comm,0)) from emp;

COUNT(NVL(COMM,0))                                                                                                                                                                                                         

                14                                                                                                     

已选择 1 行。

SQL>--屏蔽组函数的滤空功能:嵌套滤空函数

SQL>host cls

SQL>--求最高工资和最低公司

SQL>select max(sal) 最高工资, min(sal) 最低工资 from emp;

  最高工资   最低工资                                                                                                                                                                                                   

      5000        800                                                                                                  

已选择 1 行。

SQL>host cls

SQL>--求各个部门的平均工资

SQL>select deptno,avg(sal)

  2  fromemp

  3 group by deptno;

    DEPTNO  AVG(SAL)                                                                                                                                                                                                 

        30 1566.66667                                                                                                  

        20      2175                                                                                                  

        10 2916.66667                                                                                                  

已选择3行。

SQL>host cls

SQL>--按部门,不同的工种求平均工资

SQL>select deptno,job,avg(sal)

  2  fromemp

  3 group by deptno,job;

    DEPTNO JOB         AVG(SAL)                                                                                                                                                                             

        20 CLERK            950                                                                                         

SQL>select deptno,job,avg(sal)

  2  fromemp

  3 group by deptno,job

  4 order by 1;

 

    DEPTNO JOB         AVG(SAL)                                                                                                                                                                   

        30 SALESMAN        1400                                                                                        

SQL>select deptno,job,avg(sal)

  2  fromemp

  3 group by deptno

  4 order by 1;

selectdeptno,job,avg(sal)

1 行出现错误:

ORA-00979:不是 GROUP BY 表达式

SQL>host cls

SQL>--having:对分组后的数据,再进行过滤

SQL>select deptno,max(sal)

  2  fromemp

  3 group by deptno

  4 having max(sal)>2000;

    DEPTNO  MAX(SAL)                                                                                                                                                                                                 

        10      5000                                                                                                   

已选择3行。

SQL>select deptno,max(sal)

  2  fromemp

  3 group by deptno

  4 having max(sal)>3000;

    DEPTNO  MAX(SAL)                                                                                                                                                                                                

        10      5000                                                                                                  

已选择 1 行。

SQL>host cls

SQL>--group by 的增强

SQL>/*

SQL>select deptno,job,sum(sal) from emp group by deptno,job

SQL> +

SQL>select deptno,sum(sal) from emp group by deptno

SQL> +

SQL>select sum(sal) from emp

SQL>

SQL>group by的增强:

SQL>group by rollup(a,b)

SQL> =

SQL>group by a,b

SQL> +

SQL>group by a

SQL> +

SQL>group by null

SQL>

SQL>select deptno,job,sum(sal)

SQL>from emp

SQL>group by rollup(depnto,job);

SQL>*/

SQL>select deptno,job,sum(sal)

  2  fromemp

  3 group by rollup(depnto,job);

group byrollup(depnto,job)

3 行出现错误:

ORA-00904:"DEPNTO": 标识符无效

SQL>host cls

SQL>select deptno,job,sum(sal)

  2  fromemp

  3 group by rollup(deptno,job);

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                               

        10 CLERK           1300                                                                                       

SQL>break on deptno skip 2

SQL> /

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                        

        10 CLERK           1300                                                                                         

           MANAGER         2450                                                                                        

           PRESIDENT       5000                                                                                         

                           8750                                                                                        

                                                                                                             

        20 CLERK           1900                                                                                        

           ANALYST         6000                                                                                        

           MANAGER         2975                                                                                        

                          10875                                                                                        

                                                                                                            

        30 CLERK            950                                                                                        

           MANAGER         2850                                                                                        

           SALESMAN        5600                                                                                        

                           9400                                                                                        

                                                                                                                       

    DEPTNO JOB         SUM(SAL)                                                                                        

------------------- ----------                                                                                        

                                                                                                                        

                          29025                                                                                        

已选择13行。

SQL>break on null

SQL> /

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                          

        10 CLERK           1300                                                                                         

已选择13行。

SQL>spool off

SQL>--查询1020部门的员工信息

SQL>--第一种

SQL>select *

  2  fromemp

  3 where deptno=10 or deptno=20;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                   

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>--第二种

SQL>select*

  2  ;

2 行出现错误:

ORA-00923:未找到要求的 FROM 关键字

SQL>select *

  2  fromemp

  3 where deptno in(10,20);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                             

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

已选择8行。

SQL>host cls

SQL>--第三种,集合运算

SQL>select * from emp where deptno=10;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

      7782 CLARK      MANAGER         7839 09-6 -81      2450                    10                                  

SQL>select * from emp where deptno=20;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                      

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>select * from emp where depnto=10

  2 union

  3 select * from emp where deptno=20;

select *from emp where depnto=10

1 行出现错误:

ORA-00904:"DEPNTO": 标识符无效

SQL>ed

已写入 file afiedt.buf

  1 select * from emp where deptno=10

  2 union

  3* select * from emp where deptno=20

SQL> /

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                             

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>host cls

SQL>--使用union完成group by rollup

SQL>select deptno,job,sum(sal) from emp group by deptno,job

  2 union

  3 select deptno,sum(sal) from emp group by deptno

  4 union

  5 select sum(sal) from emp;

selectdeptno,sum(sal) from emp group by deptno

3 行出现错误:

ORA-01789:查询块具有不正确的结果列数

SQL> /*

SQL> 注意事项:

SQL>1. 参与运算的各个集合必须列数相同,并且类型一致

SQL>2. 最终结果的表头采用第一个select的表头

SQL>*/

SQL>select deptno,job,sum(sal) from emp group by deptno,job

  2 union

  3 select deptno,to_char(null),sum(sal) from emp group by deptno

  4 union

  5 select to_number(null),to_char(null),sum(sal) from emp;

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                            

        10 CLERK           1300                                                                                        

SQL>break on deptno skip 2

SQL> /

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                            

        10 CLERK           1300                                                                                        

           MANAGER         2450                                                                                         

           PRESIDENT       5000                                                                                        

                           8750                                                                                                                                                                                              

                                                                                                                       

        20 ANALYST         6000                                                                                        

           CLERK           1900                                                                                        

           MANAGER         2975                                                                                        

                          10875                                                                                                                                                                                                           

 

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                                                                                                                                                

        30 CLERK            950                                                                                        

           MANAGER         2850                                                                                        

           SALESMAN        5600                                                                                        

                           9400                                                                                        

                                                                                                                        

                                                                                                                       

                          29025                                                                                        

                                                                                                                       

                                                                                                                        

 

已选择13行。

SQL>--rollup和集合运算,哪个好?

SQL>set timing on

SQL>select deptno,job,sum(sal)

  2  fromemp

  3 group by rollup(deptno,job);

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                            

        10 CLERK           1300                                                                                        

           MANAGER         2450                                                                                        

           PRESIDENT       5000                                                                                        

                           8750                                                                                        

 

        20 CLERK           1900                                                                                        

           ANALYST         6000                                                                                        

           MANAGER         2975                                                                                        

                          10875                                                                                        

 

    DEPTNO JOB         SUM(SAL)                                                                                        

------------------- ----------                                                                                                                                                                                                      

        30 CLERK            950                                                                                         

           MANAGER         2850                                                                                        

           SALESMAN        5600                                                                                         

                           9400                                                                                        

                                                                                     

                          29025                                                                                                                                                                                             

 

已选择13行。

已用时间:  00: 00: 00.18

SQL>select deptno,job,sum(sal) from emp group by deptno,job

  2 union

  3 select deptno,to_char(null),sum(sal) from emp group by deptno

  4 union

  5 select to_number(null),to_char(null),sum(sal) from emp;

    DEPTNO JOB         SUM(SAL)                                                                                                                                                                            

        10 CLERK           1300                                                                                                                                                                                                       

        20 ANALYST         6000                                                                                        

           CLERK           1900                                                                                        

           MANAGER         2975                                                                                        

                          10875                                                                                        

 

    DEPTNO JOB         SUM(SAL)                                                                                        

------------------- ----------                                                                                                                                                                                                              

        30 CLERK            950                                                                                        

           MANAGER         2850                                                                                        

           SALESMAN        5600                                                                                        

                           9400                                                                                                                                                                                                   

                          29025                                                                                        

已选择13行。

已用时间:  00: 00: 00.50

SQL>--集合运算只适用于小表

SQL>set timing off

SQL> breakon null

SQL>host cls

SQL>--交集:

SQL>--举例:查询员工信息,工资位于1000~20001500~2500的范围上

SQL>select * from emp where sal between 1000 and 2000

  2 intersect

  3 select * from emp where sal between 1500 and 2500;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                 

      7499 ALLEN      SALESMAN        7698 20-2 -81     1600        300         30                                  

SQL>--差集:

SQL>--举例:查询员工信息,工资位于1000~2000上,但不属于1500~2500的范围上

SQL>select * from emp where sal between 1000 and 2000

  2 minus

  3 select * from emp where sal between 1500 and 2500;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                    

      7521 WARD       SALESMAN        7698 22-2 -81     1250        500         30                                  

    

SQL>--第一题: rownum伪列,行号

SQL>select rownum,ename,sal from emp;

    ROWNUM ENAME        SAL                                                                                                                                                                                     

         1 SMITH        800                                                                                             

     

SQL>--rownum的注意事项:

SQL>/*

SQL>1. 行号一旦生成,就不变

SQL>2. 行号只能使用小于号,不能使用大于号

SQL>*/

SQL>select rownum,ename,sal from emp order by sal desc;

 

    ROWNUM ENAME        SAL                                                                                                                                                                 

         9 KING        5000                                                                                            

SQL>select *

  2  fromemp

  3 where rownum<=3

  4 order by sal desc;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                              

      7499 ALLEN      SALESMAN        7698 20-2 -81     1600        300         30                                  

SQL>select *

  2  fromemp

  3 where rownum>=5 and rownum<=8;

未选定行

SQL>host cls

SQL>select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>host cls

SQL>--第一题

SQL>select rownum,e.empno,e.ename,e.sal

  2  from(select * from emp order by sal desc) e

  3 where rownum<=3;

    ROWNUM     EMPNO ENAME        SAL                                                                                                                                                            

         1      7839 KING        5000                                                                                 

SQL>--from后的子查询视为新表

SQL>select *

  2  from     (select rownum r,e1.*

  3          from (select * from emp order by sal) e1

  4          where rownum <=8

  5         )

  6 where r >=5;

         R     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                           

         5      7654 MARTIN     SALESMAN        7698 28-9 -81     1250       1400         30                       

SQL>host cls

SQL>--第二题:

SQL>select empno,ename,sal,avgsal

  2  fromemp e,(select deptno,avg(sal) avgsal from emp group by deptno) d

  3 where e.sal>d.avgsal and e.deptno=d.deptno

  4  ;

     EMPNO ENAME        SAL    AVGSAL                                                                                                                                                          

      7698 BLAKE       2850 1566.66667                                                                                 

SQL>spool off

SQL>select hiredate from emp;

HIREDATE                                                                                                                                                                                                                   

17-12-80                                                                                                             

SQL>select to_char(hiredate,'yyyy') from emp;

TO_C                                                                                                                                                                                                                                       

1980                                                                                                                   

SQL>select count(*)"Total",sum(decode(to_char(hiredate,'yyyy'),'1980',1,0))"1980",

  2                          sum(decode(to_char(hiredate,'yyyy'),'1981',1,0))"1981",

  3                         sum(decode(to_char(hiredate,'yyyy'),'1982',1,0)) "1982",

  4                         sum(decode(to_char(hiredate,'yyyy'),'1987',1,0)) "1987"

  5  fromemp;

     Total      1980       1981       1982      1987                                                                                                                             

        14          1         10          1          2                                                                 

SQL>spool off

SQL>--背景:查询工资比SCOTT高的员工信息

SQL>--1.求出SCOTT的工资

SQL>select sal

  2  fromemp

  3 where ename='SCOTT';

       SAL                                                                                                                                         

      3000                                                                     

SQL>--2.求出比3000高的员工

SQL>select *

  2  fromemp

  3 where sal>3000;

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM    DEPTNO                                                                                                                                        

      7839 KING       PRESIDENT            17-11-81          5000           

        10                                                                      

SQL>set linesize 120

SQL>col sal for 9999

SQL> /

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                  

      7839 KING       PRESIDENT            17-11-81     5000                    10                                  

SQL>--子查询适用的场景:不能一次求解

SQL>--使用子查询求解

SQL>select *

  2  fromemp

  3 where sal > (select sal

  4               from emp

  5               where ename='SCOTT');

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                   

      7839 KING       PRESIDENT            17-11-81     5000                    10                                  

SQL>/*

SQL> 子查询的注意事项:

SQL>1. 将子查询放入括号中

SQL>2. 尽量将子查询往右放

SQL>3. 在主查询的select, from, where后面均可使用子查询

SQL>4. 在主查询中的group by后面不能使用子查询

SQL>5. 主查询和子查询可以不是一张表,只要子查询返回的结果,主查询可以使用,即可

SQL>6.  from使用子查询,最常使用的.

SQL>7. 一般,在子查询中不使用order by;但在top-n分析中,除外

SQL>*/

SQL>--3.在主查询的select, from, where后面均可使用子查询

SQL>select (select ename from emp where empno=7839),job

  2  fromemp;

(SELECTENAJOB                                                                                                                                                                                                          

KING       CLERK                                                                                                       

 (SELECTENA JOB                                                                                                                                                                                                         

KING       CLERK                                                                                                        

SQL>--查询部门号为10的员工信息 select * from emp where deptno=10;

SQL>--姓名和薪水

SQL>

SQL>select *

  2  from(select ename,sal from emp where deptno=10);

ENAME        SAL                                                                                                                                                                                                           

CLARK       2450                                                                                                        

SQL>select e.ename,e.sal

  2  from(select ename,sal from emp where deptno=10) e

  3  ;

ENAME        SAL                                                                                                                                                                                                

CLARK       2450                                                                                                       

SQL> --5.主查询和子查询可以不是一张表,只要子查询返回的结果,主查询可以使用,即可

SQL>--查询部门名称为ACCOUTING的员工

SQL>select *

  2  fromemp

  3 where deptno=( select deptno from dept where dname='ACCOUNTING');

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                

      7782 CLARK      MANAGER         7839 09-6 -81      2450                    10                                   

SQL>host cls

SQL>--在子查询中使用组函数

SQL>--查询工资最低的员工

SQL>select *

  2  fromemp

  3 where sal=(select min(sal) from emp);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

 

SQL>select *

  2  fromemp

  3 where sal= (select min(sal)  fromemp  group by deptno);

wheresal= (select min(sal)  from emp  group by deptno)            *

3 行出现错误:

ORA-01427:单行子查询返回多个行

SQL>host cls

SQL>--子查询中空值

SQL>--查询不是经理的员工

SQL>select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                         

      7934 MILLER     CLERK           7782 23-1 -82      1300                    10                                  

已选择14行。

SQL>select *

  2  fromemp

  3 where empno not in (select mgr from emp);

未选定行

SQL>--如果子查询中含义空值,则整个子查询为空

SQL>--对子查询实现滤空,通过where条件

SQL>select *

  2  fromemp

  3 where empno not in (select mgr from emp where mgr is not null);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                          

      7900 JAMES      CLERK           7698 03-12-81       950                    30                                  

已选择8行。

SQL>host cls

SQL>--多行子查询

SQL>--in: 查询部门名称为ACCOUNTINGSALES的员工信息

SQL>select * from dept;

    DEPTNO DNAME          LOC                                                                                                                                                                     

        10 ACCOUNTING     NEW YORK                                                                                      

SQL>select *

  2  fromemp

  3 where deptno in (select deptno from dept where dname='ACCOUNTING' ordname='SALES');

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                             

      7499 ALLEN      SALESMAN        7698 20-2 -81     1600        300         30                                   

SQL>--any:和子查询返回的任意一个值比较

SQL>--查询工资比10号部门任意一个低的员工信息

SQL>select *

  2  fromemp

  3 where sal < any (select sal from emp where deptno=10);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                    

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

  

SQL>select *

  2  fromemp

  3 where sal < (select min(sal) from emp where deptno=10);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                               

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                   

SQL>select *

  2  fromemp

  3 where sal < (select max(sal) from emp where deptno=10);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                         

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

    

SQL>--查询工资比10号部门任意一个低的员工信息:即小于最大值

SQL>host cls

SQL>--all:和子查询返回的所有值比较

SQL>--查询工资比10号部门都低员工

SQL>select *

  2  fromemp

  3 where sal < all (select sal from emp where deptno=10);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>select *

  2  fromemp

  3 where sal < (select min(sal) from emp where deptno=10);

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                    

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>--查询工资比10号部门都低员工:即小于子查询的最小值

SQL>spool off

SQL>--Oracle中的事务

SQL>host cls

SQL>/*

SQL>Oracle中,事务的起始标志:

SQL>           DML语句为起始标志

SQL>           事务自动开启

SQL> 结束标志: 提交: 1. 显式提交: commit

SQL>                 2. 隐式提交: DDL自动提交前面的DML语句

SQL>           回滚:1. 显式回滚: rollback

SQL>                 2. 隐式回滚: 系统掉电,宕机,非正常退出

SQL>*/

SQL>host cls

SQL>--存储点

SQL>select * from emp10;

SQL>select * from emp20;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                 

SQL>rollbck;

SP2-0042:未知命令 "rollbck" - 其余行忽略。

SQL>rollback;

SQL>--插入数据

SQL>insert into emp20(empno,ename) values(1234,'Tom_123');

SQL>set feedback on

SQL>--定义一个存储点

SQL>select * from emp20;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                   

SQL>savepoint a;

保存点已创建。

SQL>--更新操作

SQL>update emp20 set sal=2000;

已更新6行。

SQL>select * from emp20;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                  

      7369 SMITH      CLERK           7902 17-12-80      2000                    20                                  

已选择6行。

SQL>--回退到a

SQL>rollback to a;

回退已完成。

SQL>select * from emp20;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM    DEPTNO                                                                  

      7369 SMITH      CLERK           7902 17-12-80       800                    20                                  

SQL>--提交

SQL>commit;

提交完成。

SQL>host cls

SQL>--JDBC中如何使用存储点?

SQL>/*

SQL>Connection conn = ......

SQL>conn.setAutoCommit(false);

SQL>Statement st = conn.createStatement();

SQL>st.excute(sql1);

SQL>st(sql2);

SQL>Savepoint sp = conn.setSavePoint();

SQL>sql3

SQL>sql4

SQL>conn.rollback(sp);

SQL>conn.commit;

SQL>*/

SQL>spool off

 

SQL>/*

SQL> 表的操作:

SQL>1. create table

SQL>2. alter table(添加新列,修改列,删除列)

SQL>3. drop table

SQL>*/

SQL>--4. 约束

SQL>show user;

USER "SCOTT"

SQL>host cls

SQL>/*

SQL> 创建表:

SQL>1. create table权限

SQL>2. users表空间上,必须有相应的配额

SQL>*/

SQL>create table testtable

  2  (tidnumber,

  3  tname varchar2(20),

  4  birthday date default sysdate);

表已创建。

SQL>insert into testtable(tid,tname) values(1,'aa);

ERROR:

ORA-01756:引号内的字符串没有正确结束

SQL>insert into testtable(tid,tname) values(1,'aa');

已创建 1 行。

SQL>select * from testtable;

       TID TNAME                BIRTHDAY                                                                                                                                                  

         1 aa                   16-8 -11                                                                             

已选择 1 行。

SQL>host cls

SQL>show user

USER "SCOTT"

SQL>select * from hr.employees;

EMPLOYEE_IDFIRST_NAME           LAST_NAME                 EMAIL                     PHONE_NUMBER         HIRE_DATE    

JOB_ID         SALARY COMMISSION_PCT MANAGER_IDDEPARTMENT_ID                                                                                                                

        198 Donald               OConnell                  DOCONNEL                  650.507.9833         21-6 -99   

SH_CLERK         2600                       124            50                                                          

已选择107行。

SQL>host cls

SQL>select * from hr.employees;

select *from hr.employees

                 *

1 行出现错误:

ORA-00942:表或视图不存在

SQL>host cls

SQL>--rowid:行地址, Oracle维护的,代表硬盘上的一个位置,在该位置上,存了该条记录

SQL>select rowid,empno,ename, sal from emp;

ROWID                   EMPNO ENAME        SAL                                                                                                                                               

AAANW0AAEAAAAAfAAA       7369 SMITH        800                                                                          SQL>host cls

SQL>--使用子查询创建表

SQL>--建立一个新表,包含员工的编号,姓名,月薪,年薪,年收入

SQL>create table empincome

  2  as

  3 select empno,ename,sal,sal*12 annlsal,sal*12+nvl(comm,0) totalIncome

  4  fromemp;

表已创建。

SQL> select* from empincome;

     EMPNO ENAME        SAL   ANNLSAL TOTALINCOME                                                                                                                                        

      7369 SMITH        800       9600       9600                                                                     

SQL>--修改表

SQL>desc empincome;

 名称                                                             是否为空? 类型

EMPNO                                                                     NUMBER(4)

 ENAME                                                                     VARCHAR2(10)

 SAL                                                                       NUMBER(7,2)

 ANNLSAL                                                                   NUMBER

 TOTALINCOME                                                               NUMBER

SQL>--添加照片列

SQL>alter table empincome add column image blob;

altertable empincome add column image blob

1 行出现错误:

ORA-00904:: 标识符无效

SQL>alter table empincome addimage blob;

altertable empincome addimage blob

1 行出现错误:

ORA-01735:无效的 ALTER TABLE 选项

SQL>alter table empincome add image blob;

表已更改。

SQL>desc  empincome;

 名称                                                             是否为空? 类型

EMPNO                                                                      NUMBER(4)

SQL>--修改列

SQL>alter table  empincome modify enamevarchar(20);

 

表已更改。

SQL>desc  empincome;

 名称                                                             是否为空? 类型

EMPNO                                                                      NUMBER(4)

SQL>--删除列

SQL>alter table empincome drop  column image;

表已更改。

SQL>desc empincome;

 名称                                                             是否为空? 类型

EMPNO                                                                      NUMBER(4)

 ENAME                                                                     VARCHAR2(20)

 SAL                                                                       NUMBER(7,2)

 ANNLSAL                                                                   NUMBER

 TOTALINCOME                                                               NUMBER

SQL>host cls

SQL>--删除表

SQL>--Oracle的回收站

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                                                                                                        

DEPT                           TABLE                                                                                    

SQL>drop table EMPINCOME;

 

表已删除。

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                                      

DEPT                           TABLE                                                                                   

已选择9行。

SQL>--查看回收站

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME                                                                          

EMPINCOME        BIN$Tp9LGYxbTpeSeiaZCUl5uA==$0TABLE        2011-08-16:15:41:31                                       

SQL>--闪回(flashback)

SQL>--彻底删除

SQL>drop table testdelete purge;

表已删除。

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME                                                                            

EMPINCOME        BIN$Tp9LGYxbTpeSeiaZCUl5uA==$0TABLE        2011-08-16:15:41:31                                       

SQL>--清空回收站

SQL>purge recyclebin;

回收站已清空。

SQL>  show recyclebin;

SQL>host cls

SQL>create table myperson

  2  (pid varchar2(18) constraint myperson_PK primary key,

  3   pname varchar(10) constraint mypserson_name not null,

  4   email  varchar(20) constraintmyperson_eamil unique,

  5   gender varchar(4) constraint myperson_gender check(gender in('','')),

  6   deptno number(4) constraint myperson_fk refereneces dept(deptno));

  deptno number(4) constraint myperson_fk referenecesdept(deptno))

                   *

6 行出现错误:

ORA-02253:此处不允许约束条件说明

SQL>create table myperson

  2  (pid varchar2(18) constraint myperson_PK primary key,

  3   pname varchar(10) constraint mypserson_name not null,

  4   email  varchar(20) constraintmyperson_eamil unique,

  5   gender varchar(4) constraint myperson_gender check(gender in('','')),

  6   deptno number(4) constraint myperson_fk references dept(deptno));

表已创建。

SQL>insert into myperson values('a1234','Tom','tom@126.com','',10);

已创建 1 行。

SQL>insert into myperson values('a1234','Tom','tom@126.com','',10);

insertinto myperson values('a1234','Tom','tom@126.com','',10)

1 行出现错误:

ORA-02290:违反检查约束条件 (SCOTT.MYPERSON_GENDER)

SQL>spool off

PL/SQL

setserveroutput on

declare

   --变量申明

begin

    --程序体

    dbms_output.put_line('Hello World');

end;

/

 

/*

if语句: 判断用户键盘输入的数字

*/

setserveroutput on

--接收键盘输入

acceptnum prompt '请输入一个数字:';

declare

   --通过&取输入的值

   pnum number := &num;

begin

  if pnum = 0 then  dbms_output.put_line('您输入的是0');

  end if;

  if pnum = 1 then  dbms_output.put_line('您输入的是1');

  end if;

end;

/

 

/*

0

catch(***Exceptionex){

    ...

}

*/

setserveroutput on

declare

   --定义数值变量,用于保存1/0结果

   pnum number;

begin

  --赋值

  pnum := 1/0;

exception

  when zero_divide then dbms_output.put_line('0');

end;

/

 

/*

带参数的光标: 查询并打印10号部门的员工的姓名和薪水

selectename,sal from emp where deptno=?

*/

setserveroutput on

declare

  cursor cemp10(pdno number) is selectename,sal from emp where deptno=pdno;

  pename emp.ename%type;

  psal  emp.sal%type;

begin

  open cemp10(20);

  loop

    fetch cemp10 into pename,psal;

    exit when cemp10%notfound;

    dbms_output.put_line(pename||'的工资是'||psal);

  end loop;

  close cemp10;

end;

/

 

/*

给员工涨工资,按照工种涨:总裁涨1000 经理800 其他人员400

可能的sql:

selectempjob,empno from emp;

updateemp set sal=sal+? where empno=?

*/

setserveroutput on

declare

  --光标保存员工的编号和工作

  cursor cemp is select empno,empjob from emp;

  --对应的变量

  pempno emp.empno%type;

  pempjob emp.empjob%type;

begin

  open cemp;

  LOOP

    --取出一个员工

    fetch cemp into pempno,pempjob;

    --退出条件

    exit when cemp%notfound;

    --判断

    if pempjob = 'PRESIDENT' then update empset sal=sal+1000  where empno=pempno;

      elsif pempjob= 'MANAGER' then update empset sal=sal+800 where empno=pempno;

      else update emp set sal=sal+400 whereempno=pempno;

    end if;     

  END LOOP ;

  close cemp;

  --提交

  commit;

  dbms_output.put_line('完成');

end;

/

 

/*

使用游标查询员工姓名和工资,并打印

可能的sql

selectename,sal from emp

*/

setserveroutput on

declare

  --定义光标

  cursor cemp is select ename,sal from emp;

  --定义光标对应的变量

  pename emp.ename%type;

  psal emp.sal%type;

begin

  --打开光标

  open cemp;

  --通过循环取出光标中的值

  loop

    --取值

    fetch cemp into pename,psal;

    --退出条件

    exit when cemp%notfound;

    --取到值

    dbms_output.put_line(pename||'的薪水是'||psal);

  end loop;

  --关闭光标

  close cemp;

end;

/

 

/*

实例1:统计每年入职的员工个数。

selectcount(*) "Total", sum(decode(to_char(hiredate,'yyyy'),'1980',1,0))"1980"

from emp;

可能的sql:

selectto_char(hiredate,'yyyy') from emp;

*/

setserveroutput on

declare

  --定义光标保存员工的入职年份

  cursor cemp is selectto_char(hiredate,'yyyy') from emp;

  phiredate varchar2(4);

  --计数器

  count80 number := 0;

  count81 number := 0;

  count82 number := 0;

  count87 number := 0;

begin

  --打开光标

  open cemp;

  loop

    --取值

    fetch cemp into phiredate;

    --退出条件

    exit when cemp%notfound;

    if phiredate = '1980' then count80 :=count80 +1;

      elsif phiredate = '1981' thencount81:=count81+1;

      elsif phiredate = '1982' then count82:=count82+1;

     else  count87 := count87 + 1;

    end if;

  end loop; 

  --关闭

  close cemp;

  --输出

  dbms_output.put_line('总数' ||(count80+count81+count82+count87));

  dbms_output.put_line('80'|| count80);

  dbms_output.put_line('81'|| count81);

  dbms_output.put_line('82'|| count82);

  dbms_output.put_line('87'|| count87);

end;

/

 

/*

实例2

为员工长工资。从最低工资调起每人长10%,但工资总额不能超过6万元,

请计算长工资的人数和长工资后的工资总额,并输出输出长工资人数及工资总额。

可能用到的sql:

selectempno from emp order by sal;

涨工资:update emp set sal=sal*1.1 where empno=?

工资总额: select sum(sal) from emp;

*/

setserveroutput on

declare

  --查询员工,按照工资升序排列

  cursor cemp is select empno from emp order bysal;

  pempno emp.empno%type;--记录员工的编号

  --变量保存工资的总额

  psalTotal number;

  --计数器保存涨工资的人数

  empcount number :=0;

begin

  --初始化工资的总额

  select sum(sal) into psalTotal from emp;

  --涨工资

  open cemp;

  loop

    --第一个退出条件

    exit when psalTotal > 60000;

    --取出一个员工涨工资

    fetch cemp into pempno;

    --第二个退出条件

    exit when cemp%notfound;

    --涨工资

    update emp set sal=sal*1.1 where empno=pempno;

    --人数加一

    empcount := empcount + 1;

    --重新计算工资总额

     select sum(sal) into psalTotal fromemp;   

  end loop;

  close cemp;

  --提交

  commit;

  --输出结果

  dbms_output.put_line('工资总额:' || psaltotal);

  dbms_output.put_line('涨工资的人数:' || empcount);

  dbms_output.put_line('-----------------------');

end;

/

 

/*

实例3:

PL/SQL语言编写一程序,实现按部门分段(6000以上、(60003000)3000元以下)

统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)

可能的sql

查询部门: select distinct deptno from dept;

取出该部门的员工: select sal from emp where deptno=?

计算该部门的工资总额: select sum(sal) from emp where deptno=?

*/

setserveroutput on

declare

  --查询部门

  cursor cdept is select distinct deptno fromdept;

  pdeptno dept.deptno%type;

  --查询该部门中的员工

  cursor cemp(pdno number) is select sal fromemp where deptno=pdno;

  psal emp.sal%type;

  --计数器

  count1 number;-->6000

  count2 number;--3000~6000

  count3 number;--<3000

  --工资总额

  psalTotal number;

begin

  --获取部门

  open cdept;

  loop

    --取一个部门

    fetch cdept into pdeptno;

    --退出

    exit when cdept%notfound;

    --初始化计数器

    count1 := 0;count2 := 0;count3 := 0;

    --得到该部门的工资总额

    select sum(sal) into psalTotal from empwhere deptno=pdeptno;

    --得到该部门的员工的工资

    open cemp(pdeptno);

    loop

      --取一个员工的工资

      fetch cemp into psal;

      exit when cemp%notfound;

      --判断

      if psal >= 6000 then count1 := count1+1;

        elsif psal < 6000 and psal >=3000then count2:=count2+1;

        else count3:=count3+1;

      end if;

    end loop;

    close cemp; 

    --保存结果

    insert into msg1values(pdeptno,count3,count2,count1,psalTotal);

    commit;

  end loop; 

  close cdept;

  dbms_output.put_line('完成');

end;

/

 

/*

打印1~10

*/

setserveroutput on

declare

  pnum number :=1;

begin

  loop

    --退出条件

    exit when pnum > 10;

    --打印

    dbms_output.put_line(pnum);

    pnum := pnum  + 1;

  end loop;

end;

/

 

/*

引用型变量和记录型变量

1. 引用型变量: 查询7839员工姓名和薪水 select ename, sal from emp where empno=7839;

2. 记录型变量: 查询7839员工所有信息 select * from emp where empno=7839;

*/

setserveroutput on

declare

  --申明引用型变量

  pename emp.ename%type; --记录姓名

  psal  emp.sal%type;--记录薪水

  --记录型变量

  emprec emp%rowtype;

begin

  --执行查询

  --select ename, sal into pename,psal from empwhere empno=7839;

  select * into emprec from emp whereempno=7839;

  --打印

  --dbms_output.put_line(pename||'的薪水是'||psal);

  dbms_output.put_line(emprec.ename||'的薪水是'||emprec.sal);

end;

/

 

/*

自定义例外

*/

setserveroutput on

declare

  cursor cemp(pdno number) is select ename fromemp where deptno=pdno;

  --变量

  pename emp.ename%type;

  --例外

  no_emp_data exception;

begin

  open cemp(70);

  --取值

  fetch cemp into pename;

  if cemp%notfound then raise no_emp_data;

  end if;

 

  close cemp;

exception

  when no_emp_data then dbms_output.put_line('没有70号部门的员工');

end;

/

 

/*

示例1:限制非工作时间向数据库emp插入数据(before insert)

非工作时间: 星期四,星期六,星期日, x 900 1800

 x not between 9 and 18; x<9 or x>18

*/

create orreplace trigger securityEmp

beforeinsert

on emp

declare

begin

  if to_char(sysdate,'day') in ('星期四','星期六''星期日') or

      to_number(to_char(sysdate,'hh')) notbetween 9 and 18 then

      raise_application_error(-20001,'不能在非工作时间插入员工数据');

  end if;

end;

/

 

/*

场景二: 涨工资(涨后工资不能比涨前的少)

示例2:确认数据(检查emp表中sal 的修改值不低于原值)

*/

create orreplace trigger checksal

beforeupdate

on emp

for eachrow

declare

begin

  if :old.sal > :new.sal then

    raise_application_error(-20002,'涨工资后的值不能小于涨前的值,涨前为:'||:old.sal||' 涨后为:'||:new.sal);

  end if;

end;

/

 

/*

存储过程示例:为指定的职工在原工资的基础上长10%的工资,并打印涨工资前和涨工资后的工资

*/

 

create orreplace procedure raiseSalary(eno in number)

as

    --变量说明:记录该员工的工资

    psal emp.sal%type;

begin

  --得到该员工的工资

  select sal into psal from emp whereempno=eno;

 

  --给涨工资

  update emp set sal=sal*1.1 where empno=eno;

  --打印

  dbms_output.put_line(eno||'涨前的工资是'||psal||' 涨后的工资是' || (psal*1.1));

end;

/

 

/*

存储函数: 查询某员工的年收入

*/

create orreplace function queryEmpIncome(eno in number)

returnnumber

as

  --变量说明

  psal emp.sal%type;

  pcomm emp.comm%type;

begin

  --查询该员工的月薪和奖金

  select sal,comm into psal,pcomm from empwhere empno=eno;

  --返回年收入

  return psal*12+nvl(pcomm,0);

end;

/

 

/*

out参数的存储过程: 查询某员工的月薪,年薪和年收入

 

问题:返回10号部门员工的所有信息

*/

create orreplace procedure queryempincomeinfo(eno in number,psal out number,

                                              pannlsal out number,

                                              ptotalIncome out number)

as             

begin

  --通过查询得到这些值

  select sal,sal*12,sal*12+nvl(comm,0) intopsal,pannlsal,ptotalincome from emp where empno=eno;

 

end;

/

 

/*

最简单的存储过程:打印hello world

*/

create orreplace procedure printHello

as

  --变量说明

begin

  dbms_output.put_line('Hello World');

 

end;

/

 

/*

PLSQL语言编写一个程序。按系(系名)分段统计(成绩小于60分,60-85, 85分以上)

“大学物理”课程各分数段的学生人数,及各系学生的平均成绩。

可能的sql:

得到系的信息: select dno,dname from dep;

得到该系选修了某门课的学生成绩:

selectgrade from sc where sno in (select sno from student where dno=?)

                     and   cno = (select cno from course where cname=?)

得到该系选修了某门课的学生平均成绩

selectavg(grade) from sc where sno in (select sno from student where dno=?)

                            and   cno = (select cno from course where cname=?)

*/

setserveroutput on

declare

 --得到系

 cursor cdep is select dno,dname from dep;

 pdno dep.dno%type;

 pdname dep.dname%type;

 

 --得到该系选修了某门课的学生成绩

 cursor cgrade(pdepno number,pcoursenamevarchar2) is

          select grade from sc where sno in(select sno from student where dno=pdepno)

                                and   cno = (select cno from course wherecname=pcoursename);

 pgrade sc.grade%type;

 --三个计数器

 count1 number;-- <60

 count2 number;--60~85

 count3 number;-->85

 --每个系的平均成绩

 pavggrade number;

 --课程 名称

 pcname varchar2(10);

begin

  --大学物理

  pcname := '大学物理';

  --打开系

  open cdep;

  loop

    fetch cdep into pdno,pdname;

    --退出条件

    exit when cdep%notfound;

    --计数器清零

    count1:=0;count2:=0;count3:=0;

    --得到该系大学物理的学生成绩

    open cgrade(pdno,pcname);

    loop

      fetch cgrade into pgrade;

      exit when cgrade%notfound;

      --判断

      if pgrade < 60 then count1:=count1+1;

        elsif pgrade>=60 and pgrade<85then count2:=count2+1;

        else count3:=count3+1;

      end if;

    end loop;

    close cgrade;

    --统计平均成绩

    select avg(grade) into pavggrade from scwhere sno in (select sno from student where dno=pdno)

                                             and   cno = (select cno fromcourse where cname=pcname);

   

    --保存结果

    insert into msgvalues(pcname,pdname,count1,count2,count3,pavggrade);

    commit;

  end loop;

  close cdep; 

 

  dbms_output.put_line('完成');

end;

/

SQL>/*

SQL>1. 错误删除数据,并且提交

SQL>2. 错误删除了一张表drop table

SQL>3. 如何获取表的历史记录

SQL>4. 错误地执行了一个事务,并且提交

SQL>*/

SQL>--切换到管理员

SQL>conn / as sysdba

已连接。

SQL>show parameters undo;

NAME                                 TYPE        VALUE                         

undo_management                      string      AUTO                           

undo_retention                       integer     900                           

undo_tablespace                      string      UNDOTBS1                      

SQL>--900秒改为1200

SQL>alter system set undo_retention=1200 scope=both;

系统已更改。

SQL>show parameters undo;

NAME                                 TYPE        VALUE                         

undo_management                      string      AUTO                          

undo_retention                       integer     1200                           

undo_tablespace                      string      UNDOTBS1                      

SQL>/*

SQL>scope的取值:1. memory 2. spfile 3. both

SQL>*/

SQL>--授予scott用闪回表的权限

SQL>grant flashback any table to scott;

授权成功。

SQL>conn scott/tiger

已连接。

SQL>host cls

SQL>--scn:系统改变号 system change number

SQL>--通过时间获取SCN

SQL>select timestamp_to_scn(sysdate) from dual;

TIMESTAMP_TO_SCN(SYSDATE)                                                                                                         

                  3995473                                                      

SQL>--闪回表

SQL>create table flashback_table

  2  (fidnumber,

  3  fname varchar(20));

表已创建。

SQL>insert into flashback_table values(1,'Tom');

已创建 1 行。

SQL>commit;

 

提交完成。

SQL>insert into flashback_table values(2,'Mary');

已创建 1 行。

SQL>commit;

提交完成。

SQL>insert into flashback_table values(3,'Mike');

已创建 1 行。

SQL>commit;

提交完成。

SQL>host cls

SQL>select * from flashback_table;

       FID FNAME                                                                                                            

         1 Tom                                                                 

         2 Mary                                                                 

         3 Mike                                                                

SQL>--记录当前的SCN

SQL>select timestamp_to_scn(sysdate) from dual;

TIMESTAMP_TO_SCN(SYSDATE)                                                                                                    

                  3995555                                                      

SQL>delete from flashback_table where fid=2;

已删除 1 行。

SQL>commit;

提交完成。

SQL>select * from flashback_table;

       FID FNAME                                                                                                       

         1 Tom                                                                 

         3 Mike                                                                

SQL>--执行闪回

SQL>flashback table flashback_table to scn 3995555;

flashbacktable flashback_table to scn 3995555

1 行出现错误:

ORA-08189:因为未启用行移动功能, 不能闪回表

SQL>select rowid, fid,fname from flashback_table;

ROWID                     FID FNAME                                                                     

AAANY0AAEAAAAI0AAA          1 Tom                                              

SQL>--开启表的行移动功能

SQL>alter table flashback_table enable row movement;

表已更改。

SQL>flashback table flashback_table to scn 3995555;

闪回完成。

SQL>select * from  flashback_table;

       FID FNAME                                                                                                              

         1 Tom                                                                  

         2 Mary                                                                

         3 Mike                                                                

SQL>/*

SQL> 注意:

SQL>1. 需要flashback any table的权限

SQL>2. 开启行移动功能

SQL>3. 如何获取回退的scn/时间?

SQL>*/

SQL>host cls

SQL>--oracle回收站

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                     

MSG1                           TABLE                                            

SYS_TEMP_FBT                   TABLE                                           

已选择9行。

SQL>drop table msg1;

表已删除。

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

MSG1             BIN$VzIQRj4rSnC/kXNQ3p9rGg==$0TABLE        2011-08-19:10:34:00

SQL>show user;

USER "SCOTT"

SQL>conn / as sysdba

已连接。

SQL>--管理员没有回收站

SQL>show user;

USER "SYS"

SQL>create table mytable

  2  (midnumber, mname varchar(20));

表已创建。

SQL>drop table mytable;

表已删除。

SQL>show recyclebin;

SQL>--回收站只对普通用户有效

SQL>conn scott/tiger

已连接。

SQL>host cls

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

MSG1             BIN$VzIQRj4rSnC/kXNQ3p9rGg==$0TABLE        2011-08-19:10:34:00

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                         

SYS_TEMP_FBT                   TABLE                                           

FLASHBACK_TABLE                TABLE                                           

BIN$VzIQRj4rSnC/kXNQ3p9rGg==$0TABLE                                           

DEPT                           TABLE                                           

SQL>drop table TESTSEQ purge;

表已删除。

SQL>--purge参数:彻底删除

SQL>  show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

MSG1             BIN$VzIQRj4rSnC/kXNQ3p9rGg==$0TABLE        2011-08-19:10:34:00

SQL>--清空回收站:purge recyclebin;

SQL>host cls

SQL>  show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

MSG1             BIN$VzIQRj4rSnC/kXNQ3p9rGg==$0TABLE        2011-08-19:10:34:00

SQL>--执行闪回删除

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                        

SYS_TEMP_FBT                   TABLE                                           

FLASHBACK_TABLE                TABLE                                           

BIN$VzIQRj4rSnC/kXNQ3p9rGg==$0TABLE                                           

SQL>flashback table msg1 to before drop;

闪回完成。

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                        

MSG1                           TABLE                                           

SYS_TEMP_FBT                   TABLE                                           

已选择8行。

SQL>select * from msg1;

    DEPTNO  EMP_NUM1   EMP_NUM2   EMP_NUM3   SUM_SAL                                           

        30          3          2          1     21538                         

SQL>drop table msg1;

表已删除。

SQL>host cls

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

MSG1             BIN$L7lJstduQeS4nblsvF+8tw==$0TABLE        2011-08-19:10:39:09

SQL>--通过回收站中的名字闪回删除

SQL>flashback table BIN$L7lJstduQeS4nblsvF+8tw==$0 to before drop;

flashbacktable BIN$L7lJstduQeS4nblsvF+8tw==$0 to before drop

1 行出现错误:

ORA-00905:缺失关键字

SQL>flashback table "BIN$L7lJstduQeS4nblsvF+8tw==$0" to before drop;

闪回完成。

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                          

MSG1                           TABLE                                            

SYS_TEMP_FBT                   TABLE                                           

SQL>host cls

SQL>--闪回重名的对象

SQL>create table test

  2  (tidnumber,

  3  tname varchar(20));

表已创建。

SQL>drop table test;

表已删除。

SQL>  create table test

  2  (tid number,

  3   tname varchar(20));

表已创建。

SQL>drop table test;

表已删除。

SQL>host cls

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

TEST             BIN$1wr66/qVT1eU/+mppG1Row==$0 TABLE        2011-08-19:10:42:38

TEST             BIN$pEMjzBhlQV+Qw5sG0JfSBA==$0TABLE        2011-08-19:10:42:24

SQL>--执行闪回删除

SQL>flashback table test to before drop;

闪回完成。

SQL>show recyclebin;

ORIGINALNAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME         

TEST             BIN$pEMjzBhlQV+Qw5sG0JfSBA==$0TABLE        2011-08-19:10:42:24

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                        

SQL>flashback table test to before drop;

flashbacktable test to before drop

1 行出现错误:

ORA-38312:原始名称已被现有对象使用

SQL>flashback table test to before drop rename to test123;

闪回完成。

SQL>select * from tab;

TNAME                          TABTYPE  CLUSTERID                                                      

MSG1                           TABLE                                           

SQL>host cls

SQL>--闪回版本查询

SQL>create table versions_table

  2  (vidnumber,

  3   vnamevarchar(20));

 

表已创建。

SQL>insert into versions_table values(1,'Tom');

已创建 1 行。

SQL>commit;

提交完成。

SQL>insert into versions_table values(2,'Mary');

已创建 1 行。

SQL>commit;

提交完成。

SQL>insert into versions_table values(3,'Mike');

已创建 1 行。

SQL>commit;

提交完成。

SQL>update versions_table set vname='Mary123' where vid=2;

已更新 1 行。

SQL>commit;

提交完成。

SQL>select * from versions_table;

       VID VNAME                                                                                                               

         1 Tom                                                                 

         2 Mary123                                                             

         3 Mike                                                                

 

SQL>--问题:如何获取表的历史记录?

SQL>host cls

SQL>/*

SQL>versions 伪表:

SQL>1. versions_operation: DML操作

SQL>2. versions_starttime: DML的起始时间

SQL>3. versions_endtime:DML的结束时间

SQL>4. versions_xid: DML的事务编号

SQL>*/

SQL>select vid,vname,versions_operation,versions_starttime,versions_endtime

  2  fromversions_tables

  3 versions between timestamp minvalue and maxvalue

  4 order by vid,versions_starttime;

fromversions_tables*

2 行出现错误:

ORA-00942:表或视图不存在

SQL>ed

已写入 file afiedt.buf

  1 select vid,vname,versions_operation,versions_starttime,versions_endtime

  2  fromversions_table

  3 versions between timestamp minvalue and maxvalue

  4* order by vid,versions_starttime

SQL> /

       VID VNAME                V                                                                                

VERSIONS_STARTTIME                                                             

VERSIONS_ENDTIME                                                               

         1 Tom                  I                                              

19-8 -11 10.47.58 上午                                                       

                                                                               

                                                                                

         2 Mary                 I                                              

19-8 -11 10.48.13 上午                                                       

19-8 -11 10.48.55 上午                                                        

SQL>set linesize 150

SQL>col VERSIONS_STARTTIME for a30

SQL>col VERSIONS_ENDTIME for a30

SQL> /

       VID VNAME                V VERSIONS_STARTTIME             VERSIONS_ENDTIME                                                                                                                        

         1 Tom                  I 19-8 -11 10.47.58 上午                                                                                           

SQL>/*

SQL> 通过闪回版本查询:

SQL>1. 获取所有历史记录

SQL>2.如何过去闪回表的时间或者SCN

SQL>*/

SQL>host cls

SQL>--闪回事务查询

SQL>desc flashback_transaction_query

 名称                                                                               是否为空? 类型

XID                                                                                         RAW(8)

SQL>conn / as sysdba

已连接。

SQL>grant select any transaction to scott;

授权成功。

SQL>conn scott/tiger

已连接。

SQL>host cls

SQL>--举例

SQL>create table transaction_table

  2  (tidnumber,

  3  tname varchar(20));

表已创建。

SQL>--第一个事务

SQL>insert into transaction_table values(1,'Tom');

已创建 1 行。

 

SQL>insert into transaction_table values(2,'Mary');

已创建 1 行。

SQL>insert into transaction_table values(3,'Mike');

已创建 1 行。

SQL>commit;

提交完成。

SQL>--第二个事务

SQL>select * from transaction_table;

       TID TNAME                                                                                                                                                                                                                                                    

         1 Tom                                                                                                                                       

         2 Mary                                                                                                                                      

         3 Mike                                                                                                                                      

SQL>delete from transaction_table where tid=2;

已删除 1 行。

SQL>update transaction_table set tname='Mike123' where tid=3;

已更新 1 行。

SQL>commit;

提交完成。

SQL>--通过闪回版本查询获取事务id

SQL>selecttid,tname,versions_operation,versions_starttime,versions_endtime,versions_xid

  2  fromtransaction_table

  3 versions between timestamp minvalue and maxvalue

  4 order by versions_xid;

       TID TNAME                V VERSIONS_STARTTIME             VERSIONS_ENDTIME               VERSIONS_XID                                                                      

         2 Mary                 D 19-8 -11 11.17.12 上午                                     03000C0055040000                                     

      

SQL>--通过闪回事务查询获取undo_sql

SQL>select operation,row_id,undo_sql

  2  fromflashback_transaction_query

  3 where xid='03000C0055040000';

 

OPERATION                        ROW_ID                                                                                                              

---------------------------------------------------                                                                                                 

UNDO_SQL                                                                                                                                             

------------------------------------------------------------------------------------------------------------------------------------------------------

UPDATE                          AAANY6AAEAAAAJNAAC                                                                                                   

update"SCOTT"."TRANSACTION_TABLE" set "TNAME" = 'Mike'where ROWID = 'AAANY6AAEAAAAJNAAC';                                                          

                                                                                                                                                      

DELETE                          AAANY6AAEAAAAJNAAB                                                                                                  

insertinto"SCOTT"."TRANSACTION_TABLE"("TID","TNAME")values ('2','Mary');                                                                          

                                                                                                                                                     

BEGIN                                                                                                                                                

   

SQL>update "SCOTT"."TRANSACTION_TABLE" set "TNAME" ='Mike' where ROWID = 'AAANY6AAEAAAAJNAAC';

已更新 1 行。

SQL>insert into"SCOTT"."TRANSACTION_TABLE"("TID","TNAME")values ('2','Mary');

已创建 1 行。

SQL>commit;

提交完成。

SQL>select * from TRANSACTION_TABLE;

       TID TNAME                                                                                                                                                                                                                                                         

         1 Tom                                                                                                                                       

         2 Mary                                                                                                                                      

         3 Mike                                                                                                                                      

SQL>spool off

SQL>--授权

SQL>conn / as sysdba

已连接。

SQL>grant create database link to scott;

授权成功。

SQL>conn scott/tiger

已连接。

SQL>--创建数据库链路

SQL>create database link l2 connect to scott identified by tiger using'remoteorcl';

数据库链接已创建。

SQL>--查询员工信息,要求显示员工的姓名,工资和部门号

SQL>--假设:dept在北京,emp在上海

SQL>select ename,sal,dname

  2  fromdept, emp@l2

  3 where dept.deptno=emp.deptno;

ENAME                                           SALDNAME                         

SMITH                                           800RESEARCH                   

SQL>conn / as sysdba

已连接。

SQL> grantcreate synonym to scott;

授权成功。

SQL>conn scott/tiger

已连接。

SQL>--使用同义词简化远端表

SQL>create synonym remoteemp for emp@l2;

同义词已创建。

SQL>select ename,sal,dname

  2  fromdept,remoteemp

  3 where dept.deptno=remoteemp.deptno;

 

ENAME                                           SAL DNAME                             

SMITH                                           800RESEARCH                   

SQL>host cls

SQL>--应用场景3:使用触发器实现数据的同步

SQL>create or replace trigger syncemp

  2 after update

  3  onemp

  4  foreach row

  5 declare

  6 begin

  7 

  8     update remoteemp set sal=:new.sal where empno=:new.empno;

  9 

 10  end;

 11  /

触发器已创建

SQL>select sal from emp where empno=7839;

       SAL                                                                                                                                       

     10648                                                                     

SQL>update emp set sal=4321 where empno=7839;

updateemp set sal=4321 where empno=7839*

1 行出现错误:

ORA-20002:涨工资后的值不能小于涨前的值,涨前为:10648 涨后为:4321

ORA-06512: "SCOTT.CHECKSAL", line4

ORA-04088:触发器 'SCOTT.CHECKSAL' 执行过程中出错

SQL>update emp set sal=sal+1 where empno=7839;

已更新 1 行。

SQL>commit;

提交完成。

SQL>spool off

SQL>host cls

SQL>conn / as sysdba

已连接。

SQL>--创建一个用户

SQL>create user myit1122 identified by password;

用户已创建。

SQL>--解锁

SQL>alter user myit1122 account unlock;

用户已更改。

SQL>--改密码

SQL>alter user myit1122 identified by abcd;

用户已更改。

SQL>host cls

SQL>--权限

SQL>conn hr/hr

已连接。

SQL>conn / as sysdba

已连接。

SQL>drop user jeff cascade;

用户已删除。

SQL>drop user emi cascade;

用户已删除。

SQL>host cls

SQL>--权限的级联

SQL>show user;

USER "SYS"

SQL>--创建jeff emi

SQL>create user jeff identified by password;

用户已创建。

SQL>--授予登录

SQL>grant create session to jeff;

授权成功。

SQL>create user emi identified by password;

用户已创建。

SQL>grant create session to emi;

授权成功。

SQL>--授予jeff创建表的权限

SQL>grant create table to jeff with admin option;

授权成功。

SQL>--分配空间users

SQL>alter user jeff quota unlimited on users;

用户已更改。

SQL>--切换到jeff

SQL>

SQL>conn jeff/password

已连接。

SQL>--授予emi创建表的权限

SQL>grant create table to emi;

授权成功。

SQL>conn / as sysdba

已连接。

SQL>alter user emi quota unlimited on users;

用户已更改。

SQL>conn emi/password

已连接。

SQL>show user

USER "EMI"

SQL>create table bb(bb number);

表已创建。

SQL>--切换到管理员上,撤销create table

SQL>conn / as sysdba

已连接。

SQL>revoke create table from jeff;

撤销成功。

SQL>conn jeff/password

已连接。

SQL>create table ccc(cc number);

createtable ccc(cc number)

1 行出现错误:

ORA-01031:权限不足

SQL>conn emi/password

已连接。

SQL>  create table ccc(cc number);

表已创建。

SQL>host cls

SQL>-- 演示grant option

SQL>conn scott/tiger

已连接。

SQL>--select on emp-->jeff

SQL>grant select on emp to jeff with grant option;

授权成功。

SQL>conn jeff/password

已连接。

SQL>select count(*) from  scott.emp;

  COUNT(*)                                                                                                                                          

        14                                                                     

SQL> --jeff:select on scott.emp --> emi

SQL>grant select on scott.emp to emi;

授权成功。

SQL>conn emi/password

已连接。

SQL>select count(*) from  scott.emp;

  COUNT(*)                                                                                                                                        

        14                                                                     

SQL>--回到scott

SQL>conn scott/tiger

已连接。

SQL>revoke select on emp from jeff;

撤销成功。

SQL>conn jeff/password

已连接。

SQL>select count(*) from scott.emp;

selectcount(*) from scott.emp

1 行出现错误:

ORA-00942:表或视图不存在

SQL>conn emi/password

已连接。

SQL>select count(*) from scott.emp;

selectcount(*) from scott.emp

1 行出现错误:

ORA-00942:表或视图不存在

SQL>host cls

SQL>--角色

SQL>conn / as sysdba

已连接。

SQL>create user myuser123 identified by password;

createuser myuser123 identified by password

1 行出现错误:

ORA-01920:用户名 'MYUSER123' 与另外一个用户名或角色名发生冲突

SQL>create user myuser1234 identified by password;

用户已创建。

SQL>grant connect,resource to myuser1234;

授权成功。

SQL>host cls

SQL>--自定义角色

SQL>create role myrole1234;

createrole myrole1234

1 行出现错误:

ORA-01921:角色名 'MYROLE1234' 与另一个用户名或角色名发生冲突

SQL>create role myrole123;

createrole myrole123 *

1 行出现错误:

ORA-01921:角色名 'MYROLE123' 与另一个用户名或角色名发生冲突

SQL>create role myrole321;

角色已创建。

SQL>grant create sessiont,create table to myrole321;

grantcreate sessiont,create table to myrole321

1 行出现错误:

ORA-00990:权限缺失或无效

SQL>grant create session,create table to myrole321;

授权成功。

SQL>spool off

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涂作权的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值