zoukankan      html  css  js  c++  java
  • oracle所有操作

    --等值连接
    --查询员工信息: 员工号 姓名 月薪 部门名称
    select p.deptno,p.ename,p.sal ,t.dname from emp p,dept t where p.deptno=t.deptno;
    --不等值连接
    --查询员工信息: 员工号 姓名 月薪 工资级别
    select e.deptno,e.ename,e.sal,s.grade from emp e,salgrade s where e.sal between s.losal and s.hisal;
    --外连接
    --按部门统计员工人数: 部门号 部门名称 人数
    select d.deptno,d.dname,count(d.deptno) from emp e,dept d where e.deptno=d.deptno group by d.deptno,d.dname;
    ---希望: 在最后的结果中,包含某些不成立的记录
    ---外连接:
    ---左外连接: 当where e.deptno=d.deptno不成立的时候,等号左边所代表的表 任然被包含
    ----写法: where e.deptno=d.deptno(+)

    select d.deptno,d.dname,count(e.deptno) from emp e,dept d where e.deptno=d.deptno(+) group by d.deptno,d.dname;
    ---右外连接: 当where e.deptno=d.deptno不成立的时候,等号右边所代表的表 任然被包含
    ---写法:where e.deptno(+)=d.deptno
    select d.deptno,d.dname,count(e.deptno) from emp e,dept d where e.deptno(+)=d.deptno group by d.deptno,d.dname;
    --自连接
    ---查询员工信息:***的老板是***
    --自连接:通过表的别名,将同一张表视为多张表
    select e.ename||'的老板是'||p.ename from emp e,emp p where e.mgr=p.empno;
    --层次查询
    select level,empno,ename,sal,mgr from emp connect by prior empno=mgr start with mgr is null order by 1;
    --查询工资比SCOTT高的员工信息
    select e.* from emp e where e.sal > (select sal from emp p where p.ename='SCOTT');
    注意的问题
    --- 1. 括号
    --- 2. 合理的书写风格
    --- 3. 可以主查询的where select from having后面放置子查询
    --- 4. 不可以在主查询的group by后面放置子查询
    --- 5. 强调from后面的子查询
    --- 6. 主查询和子查询可以不是同一张表,只要子查询返回的结果 主查询可以使用即可
    --- 7. 一般不在子查询使用order by,但在Top-N分析问题中 必须使用order by
    --- 8. 一般先执行子查询,再执行主查询;但相关子查询除外
    --- 9. 单行子查询只能使用单行操作符 多行子查询只能使用多行操作符
    --- 10. 子查询中null
    -- 3. 可以主查询的where select from having后面放置子查询
    select e.ename,e.deptno,(select job from emp where empno=7839) from emp e ;
    --5. 强调from后面的子查询
    --查询员工的姓名和薪水
    select e.ename,e.sal from emp e;
    select f.* from (select e.ename,e.sal ,e.sal*12 from emp e) f;
    --6. 主查询和子查询可以不是同一张表,只要子查询返回的结果 主查询可以使用即可
    --查询部门名称为SALES的员工信息
    select e.* from emp e where e.deptno =(select deptno from dept where dname='SALES');
    --优化5:理论上,尽量使用多表查询

    --in 在集合中
    --查询部门名称是SALES和ACCOUNTING的员工
    select * from emp where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING');
    select e.* from emp e,dept d where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING');
    --any: 和集合中 任意一个值比较
    --查询工资比30号部门任意一个员工高的员工信息
    select e.* from emp e where e.sal> any (select sal from emp where deptno=30);
    select e.* from emp e where e.sal> (select min(sal) from emp where deptno=30);
    --all:和集合的所有值比较
    --查询工资比30号部门所有员工高的员工信息
    select e.* from emp e where e.sal> all (select sal from emp where deptno=30);
    select e.* from emp e where e.sal> (select max(sal) from emp where deptno=30);
    --多行子查询中null
    --查询不是老板的员工信息
    select e.* from emp e where e.empno in (select mgr from emp );
    select e.* from emp e where e.empno not in (select mgr from emp where mgr is not null );
    ---查询部门号是10和20的员工信息
    select * from emp e where e.deptno in (10,20);
    select empno,ename,job,sal from emp where deptno=10
    union
    select empno,ename,job,sal from emp where deptno=20;

    select deptno,job,sum(sal) from emp group by rollup(deptno,job);

    select deptno,job,sum(sal) from emp group by deptno,job
    union
    select deptno,to_char(null),sum(sal) from emp group by deptno
    union
    select to_number(null),to_char(null),sum(sal) from emp ;
    -----工资最高的前三名
    select rownum, t.ename,t.sal
    from
    (select ename,sal,row_number() over (order by sal desc) rn from emp) t
    where rn<=3;
    select * from (select * from emp order by sal desc) where rownum<=3;
    --第一题
    select * from (
    select rownum r,u.* from
    (select ename,deptno,sal from emp order by sal desc) u
    where rownum<=8) q where r>5
    --第二题
    select e.ename,e.sal,o.m from emp e,(select deptno, avg(sal) m from emp group by deptno) o where e.deptno=o.deptno and e.sal>o.m;
    select e.ename,e.sal,(select avg(sal) m from emp where deptno=e.deptno) avga from emp e where e.sal>(select avg(sal) from emp where deptno=e.deptno);
    --第三题
    --组函数 行转列 wm_concat
    select * from emp;
    select deptno,wm_concat(ename) from emp group by deptno;
    select count(*) ,sum(decode(to_char(hiredate,'RR'),'80',1,0)) "1980",sum(decode(to_char(hiredate,'RR'),'81',1,0)) "1981",sum(decode(to_char(hiredate,'RR'),'82',1,0)) "1982",sum(decode(to_char(hiredate,'RR'),'87',1,0)) "1987" from emp;
    ---管理员登录
    sqlplus sys/你的密码 as sysdba (密码认证)
    sqlplus / as sysdba (主机认证 优先)
    ---解锁
    alter user scott account unlock;
    ---改密码
    alter user scott identified by 新密码;
    ---SQL类型
    ---1. DML(Data Manipulation Lanuage 数据操作语言): select insert update delete
    ---2. DDL(Data Definition Language 数据定义语言): create/alter/drop/truncate table create/drop view/sequence/index/synonym
    ---3. DCL(Data Control Language 数据控制语言): commit rollback
    --插入数据 insert
    insert into emp (empno,ename,sal ,deptno) values(1001,'Tom',6000,20);
    --隐式/显式插入null
    -----地址符 &
    insert into emp (empno,ename,sal ,deptno) values(&empno,'&ename',&sal,&deptno);
    select empno,ename,deptno from &t;
    rollback;
    --批处理
    create table emp10 as select * from emp where 1=2;
    select * from emp10;
    --一次性从emp中 将所有10号部门的员工插入到emp10
    insert into emp10 select * from emp where deptno=10;
    --更新数据
    --删除数据
    ----delete 和truncate的区别
    ---1. delete逐条删除 truncate 先摧毁表 再重建
    ---2. **** delete 是DML(可以回滚),truncate是DDL(不可以回滚)
    ---3. delete不会释放空间 truncate会
    ---4. delete会产生碎片 truncate不会
    ---5. delete可以闪回,truncate不可以
    create table testdelete(tid number ,tname varchar2(20));
    CREATE SEQUENCE SI_EXTERNAL_SEQ --SI_EXTERNAL_SEQ要创建的sequence的名字
    INCREMENT BY 1 -- 每次加几个
    START WITH 1 -- 从1开始计数
    NOMAXVALUE -- 不设置最大值
    NOCYCLE -- 一直累加,不循环
    CACHE 10;
    insert into testdelete values(SI_EXTERNAL_SEQ.NEXTVAL,'aaa');
    commit;
    select * from testdelete;
    set timing on
    create table testdelete2 as select * from testdelete;
    ------保存点
    create table testsavepoint
    (tid number,tname varchar2(20));
    set feedback on
    insert into testsavepoint values(1,'Tom');
    insert into testsavepoint values(2,'Mary');
    savepoint a;
    insert into testsavepoint values(3,'Moke');
    select * from testsavepoint;
    rollback to savepoint a;
    commit;
    ---
    create table test1(
    tid number,
    tname varchar2(20),
    hirdate date default sysdate
    )
    insert into test1(tid,tname) values(1,'tom');
    select * from test1;
    --行地址
    select rowid,empno,ename,job from emp;
    --保存20号部门的员工
    create table emp20 as select * from emp where deptno=20;
    select * from emp20;
    --创建表: 员工号 姓名 月薪 年薪 部门名称
    create table empinfo as select e.empno,e.ename,e.sal,e.sal*12 niansal ,d.dname from dept d,emp e where d.deptno=e.deptno;
    select * from empinfo;
    --修改表: 追加新列 修改列 删除列 重名列
    select * from test1;
    alter table test1 add age2 number;
    alter table test1 modify age varchar2(40);
    alter table test1 drop column age;
    alter table test1 rename column tid to ttid;
    select * from tab;
    drop table test1;
    --Oracle的回收站
    select * from recyclebin;
    ---清空回收站
    purge recyclebin;
    --drop table test1 purge; --> 不经过回收站直接删除
    --注意: 管理员没有回收站
    --检查性约束
    create table student(
    sid number primary key,
    sname varchar2(40) not null,
    age number check (age>0),
    gender varchar2(4) check(gender in ('男','女'))
    )
    select * from student;
    insert into student(sid,sname,age,gender) values(2,'aaa',25,'a');
    commit;
    create table teacher(
    sid number constraint t_pk primary key,
    sname varchar2(40) constraint t_name not null,
    age number constraint t_age check (age>0),
    gender varchar2(4) constraint t_gender check(gender in ('男','女'))
    )
    insert into teacher(sid,sname,age,gender) values(2,'aaa',25,'a');
    ----Hello World
    set serveroutput on

    declare

    begin

    dbms_output.put_line('Hello World');
    end;
    /
    -----if语句
    set serveroutput on
    accept num prompt '请输入一个数字';
    declare
    pnum number :=&num;
    begin

    if pnum=1 then dbms_output.put_line('输入的值为1');
    elsif pnum=2 then dbms_output.put_line('输入的值为2');
    elsif pnum=3 then dbms_output.put_line('输入的值为3');
    else dbms_output.put_line('输入的值为其它');
    end if;
    end;
    /
    --带参数的光标
    --查询某个部门中员工的姓名
    set serveroutput on
    accept num prompt '请输入一个数字';
    declare
    cursor cemp(dmo number) is select ename from emp where deptno=dmo;
    pname emp.ename%type;
    pnum number :=&num;
    begin
    open cemp(pnum);
    loop
    fetch cemp into pname;
    exit when cemp%notfound;
    dbms_output.put_line(pname);
    end loop;
    close cemp;

    end;
    /
    -----涨工资 总裁1000 经理800 其他400
    set serveroutput on

    declare
    cursor cemp is select empno,empjob from emp;
    pempno emp.empno%type;
    pjob emp.empjob%type;

    begin
    open cemp;
    loop
    fetch cemp into pempno,pjob;
    exit when cemp%notfound;
    if pjob='PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
    elsif pjob='MANAGER' then update emp set sal=sal+800 where empno=pempno;
    else update emp set sal=sal+400 where empno=pempno;
    end if;
    end loop;
    close cemp;
    commit;
    dbms_output.put_line('完成!');
    end;
    /
    select * from emp;

    -----使用游标查询员工姓名和工资,并打印
    /*
    1. 光标的属性
    %isopen: 是否打开
    %rowcount: 行数
    %notfound: 没有记录

    2. 默认允许一次打开300个光标(修改光标: 第四天 管理方案)
    SQL> show parameters cursor

    NAME TYPE VALUE
    ------------------------------------ ----------- -------
    cursor_sharing string EXACT
    cursor_space_for_time boolean FALSE
    open_cursors integer 300
    session_cached_cursors integer 20
    */
    show parameters cursor;

    set serveroutput 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;
    /
    --------查询并打印7839的姓名和薪水
    --记录型变量 代表一行
    set serveroutput on

    declare

    rec emp%rowtype;
    begin
    select * into rec from emp where empno=7839;
    dbms_output.put_line(rec.empno||'aaaa'||rec.sal);
    end;
    /
    实例1:统计每年入职的员工个数。
    set serveroutput on

    declare
    cursor cemp is select to_char(hiredate,'RR') 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='80' then count80:=count80+1;
    elsif phiredate='81' then count81:=count81+1;
    elsif phiredate='82' then count82:=count82+1;
    else count87:=count87+1;
    end if;
    end loop;
    close cemp;
    dbms_output.put_line('total'||(count80+count81+count82+count87));
    dbms_output.put_line(count80);
    dbms_output.put_line(count81);
    dbms_output.put_line(count82);
    dbms_output.put_line(count87);
    end;
    /
    ---为员工长工资。从最低工资调起每人长10%,但工资总额不能超过5万元,
    ----请计算长工资的人数和长工资后的工资总额,并输出输出长工资人数及工资总额。
    set serveroutput on

    declare
    cursor cemp is select empno,sal from emp;
    pempno emp.empno%type;
    psal emp.sal%type;
    countEmp number :=0;
    salTotal number ;
    begin
    select sum(sal) into salTotal from emp;
    open cemp;
    loop
    exit when salTotal>200000;
    fetch cemp into pempno,psal;
    exit when cemp%notfound;

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

    countEmp :=countEmp+1;
    if salTotal+psal*0.1<200000 then salTotal :=salTotal+psal*0.1;
    else exit;
    end if;
    end loop;
    close cemp;
    commit;
    dbms_output.put_line('人数:'||countEmp||' 工资总额:'||salTotal);
    end;
    /
    -----用PL/SQL语言编写一程序,实现按部门分段(6000以上、(6000,3000)、3000元以下)
    ----统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)

    set serveroutput on

    declare
    cursor cdept is select deptno from dept;
    pdeptno dept.deptno%type;

    cursor cemp(dno number) is select sal from emp where deptno=dno;
    psal emp.sal%type;
    count1 number;count2 number;count3 number;
    salTotal number;
    begin
    open cdept;
    loop
    fetch cdept into pdeptno;
    exit when cdept%notfound;
    count1 :=0;count2 :=0;count3 :=0;
    select sum(sal) into salTotal from emp where deptno=pdeptno;
    open cemp(pdeptno);
    loop
    fetch cemp into psal;
    exit when cemp%notfound;
    if psal<3000 then count1 :=count1+1;
    elsif psal>3000 and psal<6000 then count2 :=count2+1;
    else count3 :=count3+1;
    end if;
    end loop;
    close cemp;
    insert into msg1 values(pdeptno,count1,count2,count3,nvl(salTotal,0));
    end loop;
    close cdept;
    commit;
    dbms_output.put_line('完成');
    end;
    /
    create table msg1(
    n1 number,
    n2 number,
    n3 number,
    n4 number,
    n5 number
    )
    select *  from msg1;
    -----被0除
    set serveroutput on

    declare
    pnum number;
    begin
    pnum :=1/0;

    exception
    when Zero_Divide then dbms_output.put_line('1:0不能做被除数');
    dbms_output.put_line('2:0不能做被除数');
    when Value_error then dbms_output.put_line('算术或转换错误');
    when others then dbms_output.put_line('其他例外');
    end;
    /
    ----循环
    set serveroutput on

    declare
    pnum number;
    begin
    pnum :=0;
    loop
    exit when pnum>10;
    dbms_output.put_line(pnum);
    pnum :=pnum+1;
    end loop;
    end;
    /
    -----查询并打印7839的姓名和薪水
    set serveroutput on

    declare
    pename emp.ename%type;
    psal emp.sal%type;
    begin
    select ename,sal into pename,psal from emp where empno=7839;
    dbms_output.put_line(pename||'的薪水是'||psal);
    end;
    /
    ------查询50号部门的员工
    set serveroutput on

    declare
    cursor cemp is select ename from emp where deptno=30;
    pename emp.ename%type;
    no_emp_found exception;
    begin
    open cemp;
    fetch cemp into pename;
    if cemp%notfound then
    raise no_emp_found;
    end if;


    close cemp;
    exception
    when no_emp_found then dbms_output.put_line('没有找到员工');
    when others then dbms_output.put_line('其他例外');
    end;
    /


    select * from emp;
    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;
    查询并返回某个员工的姓名 月薪和职位

    思考: out参数太多???
    */
    create or replace procedure queryEmpInfo(
    eno in number,
    pename out varchar2,
    psal out number,
    pjob out varchar2
    )
    as
    begin
    select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
    end;
    /
    /*
    实施复杂的安全性检查

    禁止在非工作时间 往emp表中插入数据
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    PLSQL 块

    周末:to_char(sysdate,'day') in ('星期六','星期日')
    上班前 下班后: to_number(to_char(sysdate,'hh24')) not between 9 and 18
    */
    create or replace trigger securityEmp
    before insert
    on emp
    begin
    if to_char(sysdate,'day') in ('星期三','星期六') or
    to_number(to_char(sysdate,'hh24')) not between 9 and 18 then
    raise_application_error(-20001,'不能在非工作时间插入数据');
    end if;
    end;
    /
    select * from emp;
    insert into emp(empno,ename,empjob,sal) values(100,'hhh','manager',8000);
    select * from user_source where name like '%SECURITYEMP%';
    drop trigger checksal;
    /*
    数据确认

    涨后的薪水不能少于涨前的薪水
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    [FOR EACH ROW [WHEN(条件) ] ]
    PLSQL 块

    */
    create or replace trigger checksal
    before update
    on emp
    for each row
    begin
    if :new.sal<:old.sal then
    raise_application_error(-20002,'涨后的薪水不能少于涨前的薪水.涨前:'||:old.sal||' 涨后:'||:new.sal);
    end if;
    end;
    /
    update emp set sal=sal-100 where empno=7839;
    /*
    CREATE [OR REPLACE] FUNCTION 函数名(参数列表)
    RETURN 函数值类型
    AS
    PLSQL子程序体;

    查询某个员工的年收入

    */
    create or replace function queryEmpIncome(eno in number)
    return number
    as
    psal emp.sal%type;
    pcomm emp.comm%type;
    begin
    select sal,comm into psal,pcomm from emp where empno=eno;
    return psal*12+nvl(pcomm,0);
    end;
    /
    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;

    为指定的员工涨100块钱 并打印涨前和涨后的薪水
    */
    create or replace procedure raiseSalary(
    eno in number
    )
    as
    psal emp.sal%type;
    begin
    select sal into psal from emp where empno=eno;
    update emp set sal=sal+100 where empno=eno;
    dbms_output.put_line('涨前:'||psal||' 涨后:'||(psal+100));
    end;
    /

    create or replace trigger sayNewEmp
    after insert on emp
    declare

    begin
    dbms_output.put_line('插入数据!');

    end;
    /
    delete from emp where empno=1000;
    select * from emp;
    select * from user_source where type='CURSOR';
    /*
    1.错误的删除了数据,并且已经提交
    2.错误的删除了表drop table
    3.如何获取表上的历史记录
    4.如何撤销已经提交的事务
    闪回的类型
    1.闪回表:将表返回到过去的一个时间上
    2.闪回删除:操作oracle的回收站
    3.闪回版本查询:表上的历史记录
    4.闪回事务查询:获取表上的一个UNDO_SQL
    5.闪回数据库:将数据库返回到过去的一个时间上
    6.闪回归档日志
    */
    ---查询没有提交的数据
    show parameter undo;
    ----设置闪回时间 scope的取值:memoery(本次回话) spfile(重启后生效) both()
    alter system set undo_retention=1200 scope=both;
    ---系统改变号SCN----6952590965600 6952590966674
    select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss:mm') 时间,
    timestamp_to_scn(sysdate) SCN
    from dual;
    ---闪回表
    create table flashback_table (fid number,fname varchar2(40));
    insert into flashback_table values(1,'tom');
    insert into flashback_table values(2,'marry');
    insert into flashback_table values(3,'mike');

    delete from flashback_table where fid=2;
    select * from flashback_table;
    ---启动行移动ALTER TABLE table_name ENABLE ROW MOVEMENT
    alter table flashback_table enable row movement;
    flashback table flashback_table to SCN 6952590966674;
    ---如何获取离操作最近的一个时间或者SCN?
    select * from tab;
    drop table EMP20 purge;
    ----闪回删除的表
    flashback table MSG1 to before drop rename to msg5 ;
    create table MSG1(mid number,mname varchar2(30));
    select * from msg4;
    show recyclebin;
    purge recyclebin;
    -------管理员没有回收站

    create table ggg(mid number,mname varchar2(30));
    insert into ggg values(1,'ssss');
    drop table ggg;
    select * from ggg;
    flashback table ggg to before drop ;
    flashback table ggg to before drop rename to msg5 ;
    select * from msg5;
    -----返回版本
    create table version_table(tid number,tname varchar2(30));
    insert into version_table values(1,'tom');
    insert into version_table values(2,'mary');
    insert into version_table values(3,'mike');
    update version_table set tname='mary123' where tid=2;
    select * from version_table;
    -----查询返回版本的语法
    select tid,tname,versions_operation,versions_starttime,versions_endtime,versions_xid from version_table versions between timestamp minvalue and maxvalue;
    ----闪回事务查询
    create table tracation_table(tid number,tname varchar2(30));

    insert into tracation_table values(1,'tom');
    insert into tracation_table values(2,'mary');

    insert into tracation_table values(3,'mike');
    update tracation_table set tname='dfdfd' where tid=2;


    select tid,tname,versions_operation,versions_starttime,versions_endtime,versions_xid from tracation_table versions between timestamp minvalue and maxvalue;
    select operation,undo_sql from flashback_transaction_query where xid='0B00080016DF0000';
    exp scott/tiger @10.4.237.4:1521:orcl file=f:/a.dmp log=f:/log.log tables=dept,emp

    --等值连接
    --查询员工信息: 员工号 姓名 月薪 部门名称
    select p.deptno,p.ename,p.sal ,t.dname from emp p,dept t where p.deptno=t.deptno;
    --不等值连接
    --查询员工信息: 员工号 姓名 月薪 工资级别
    select e.deptno,e.ename,e.sal,s.grade from emp e,salgrade s where e.sal between s.losal and s.hisal;
    --外连接
    --按部门统计员工人数: 部门号 部门名称 人数
    select d.deptno,d.dname,count(d.deptno) from emp e,dept d where e.deptno=d.deptno group by d.deptno,d.dname;
    ---希望: 在最后的结果中,包含某些不成立的记录
    ---外连接:
    ---左外连接: 当where e.deptno=d.deptno不成立的时候,等号左边所代表的表 任然被包含
    ----写法: where e.deptno=d.deptno(+)

    select d.deptno,d.dname,count(e.deptno) from emp e,dept d where e.deptno=d.deptno(+) group by d.deptno,d.dname;
    ---右外连接: 当where e.deptno=d.deptno不成立的时候,等号右边所代表的表 任然被包含
    ---写法:where e.deptno(+)=d.deptno
    select d.deptno,d.dname,count(e.deptno) from emp e,dept d where e.deptno(+)=d.deptno group by d.deptno,d.dname;
    --自连接
    ---查询员工信息:***的老板是***
    --自连接:通过表的别名,将同一张表视为多张表
    select e.ename||'的老板是'||p.ename from emp e,emp p where e.mgr=p.empno;
    --层次查询
    select level,empno,ename,sal,mgr from emp connect by prior empno=mgr start with mgr is null order by 1;
    --查询工资比SCOTT高的员工信息
    select e.* from emp e where e.sal > (select sal from emp p where p.ename='SCOTT');
    注意的问题
    --- 1. 括号
    --- 2. 合理的书写风格
    --- 3. 可以主查询的where select from having后面放置子查询
    --- 4. 不可以在主查询的group by后面放置子查询
    --- 5. 强调from后面的子查询
    --- 6. 主查询和子查询可以不是同一张表,只要子查询返回的结果 主查询可以使用即可
    --- 7. 一般不在子查询使用order by,但在Top-N分析问题中 必须使用order by
    --- 8. 一般先执行子查询,再执行主查询;但相关子查询除外
    --- 9. 单行子查询只能使用单行操作符 多行子查询只能使用多行操作符
    --- 10. 子查询中null
    -- 3. 可以主查询的where select from having后面放置子查询
    select e.ename,e.deptno,(select job from emp where empno=7839) from emp e ;
    --5. 强调from后面的子查询
    --查询员工的姓名和薪水
    select e.ename,e.sal from emp e;
    select f.* from (select e.ename,e.sal ,e.sal*12 from emp e) f;
    --6. 主查询和子查询可以不是同一张表,只要子查询返回的结果 主查询可以使用即可
    --查询部门名称为SALES的员工信息
    select e.* from emp e where e.deptno =(select deptno from dept where dname='SALES');
    --优化5:理论上,尽量使用多表查询

    --in 在集合中
    --查询部门名称是SALES和ACCOUNTING的员工
    select * from emp where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING');
    select e.* from emp e,dept d where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING');
    --any: 和集合中 任意一个值比较
    --查询工资比30号部门任意一个员工高的员工信息
    select e.* from emp e where e.sal> any (select sal from emp where deptno=30);
    select e.* from emp e where e.sal> (select min(sal) from emp where deptno=30);
    --all:和集合的所有值比较
    --查询工资比30号部门所有员工高的员工信息
    select e.* from emp e where e.sal> all (select sal from emp where deptno=30);
    select e.* from emp e where e.sal> (select max(sal) from emp where deptno=30);
    --多行子查询中null
    --查询不是老板的员工信息
    select e.* from emp e where e.empno in (select mgr from emp );
    select e.* from emp e where e.empno not in (select mgr from emp where mgr is not null );
    ---查询部门号是10和20的员工信息
    select * from emp e where e.deptno in (10,20);
    select empno,ename,job,sal from emp where deptno=10
    union
    select empno,ename,job,sal from emp where deptno=20;

    select deptno,job,sum(sal) from emp group by rollup(deptno,job);

    select deptno,job,sum(sal) from emp group by deptno,job
    union
    select deptno,to_char(null),sum(sal) from emp group by deptno
    union
    select to_number(null),to_char(null),sum(sal) from emp ;
    -----工资最高的前三名
    select rownum, t.ename,t.sal
    from
    (select ename,sal,row_number() over (order by sal desc) rn from emp) t
    where rn<=3;
    select * from (select * from emp order by sal desc) where rownum<=3;
    --第一题
    select * from (
    select rownum r,u.* from
    (select ename,deptno,sal from emp order by sal desc) u
    where rownum<=8) q where r>5
    --第二题
    select e.ename,e.sal,o.m from emp e,(select deptno, avg(sal) m from emp group by deptno) o where e.deptno=o.deptno and e.sal>o.m;
    select e.ename,e.sal,(select avg(sal) m from emp where deptno=e.deptno) avga from emp e where e.sal>(select avg(sal) from emp where deptno=e.deptno);
    --第三题
    --组函数 行转列 wm_concat
    select * from emp;
    select deptno,wm_concat(ename) from emp group by deptno;
    select count(*) ,sum(decode(to_char(hiredate,'RR'),'80',1,0)) "1980",sum(decode(to_char(hiredate,'RR'),'81',1,0)) "1981",sum(decode(to_char(hiredate,'RR'),'82',1,0)) "1982",sum(decode(to_char(hiredate,'RR'),'87',1,0)) "1987" from emp;
    ---管理员登录
    sqlplus sys/你的密码 as sysdba (密码认证)
    sqlplus / as sysdba (主机认证 优先)
    ---解锁
    alter user scott account unlock;
    ---改密码
    alter user scott identified by 新密码;
    ---SQL类型
    ---1. DML(Data Manipulation Lanuage 数据操作语言): select insert update delete
    ---2. DDL(Data Definition Language 数据定义语言): create/alter/drop/truncate table create/drop view/sequence/index/synonym
    ---3. DCL(Data Control Language 数据控制语言): commit rollback
    --插入数据 insert
    insert into emp (empno,ename,sal ,deptno) values(1001,'Tom',6000,20);
    --隐式/显式插入null
    -----地址符 &
    insert into emp (empno,ename,sal ,deptno) values(&empno,'&ename',&sal,&deptno);
    select empno,ename,deptno from &t;
    rollback;
    --批处理
    create table emp10 as select * from emp where 1=2;
    select * from emp10;
    --一次性从emp中 将所有10号部门的员工插入到emp10
    insert into emp10 select * from emp where deptno=10;
    --更新数据
    --删除数据
    ----delete 和truncate的区别
    ---1. delete逐条删除 truncate 先摧毁表 再重建
    ---2. **** delete 是DML(可以回滚),truncate是DDL(不可以回滚)
    ---3. delete不会释放空间 truncate会
    ---4. delete会产生碎片 truncate不会
    ---5. delete可以闪回,truncate不可以
    create table testdelete(tid number ,tname varchar2(20));
    CREATE SEQUENCE SI_EXTERNAL_SEQ --SI_EXTERNAL_SEQ要创建的sequence的名字
    INCREMENT BY 1 -- 每次加几个
    START WITH 1 -- 从1开始计数
    NOMAXVALUE -- 不设置最大值
    NOCYCLE -- 一直累加,不循环
    CACHE 10;
    insert into testdelete values(SI_EXTERNAL_SEQ.NEXTVAL,'aaa');
    commit;
    select * from testdelete;
    set timing on
    create table testdelete2 as select * from testdelete;
    ------保存点
    create table testsavepoint
    (tid number,tname varchar2(20));
    set feedback on
    insert into testsavepoint values(1,'Tom');
    insert into testsavepoint values(2,'Mary');
    savepoint a;
    insert into testsavepoint values(3,'Moke');
    select * from testsavepoint;
    rollback to savepoint a;
    commit;
    ---
    create table test1(
    tid number,
    tname varchar2(20),
    hirdate date default sysdate
    )
    insert into test1(tid,tname) values(1,'tom');
    select * from test1;
    --行地址
    select rowid,empno,ename,job from emp;
    --保存20号部门的员工
    create table emp20 as select * from emp where deptno=20;
    select * from emp20;
    --创建表: 员工号 姓名 月薪 年薪 部门名称
    create table empinfo as select e.empno,e.ename,e.sal,e.sal*12 niansal ,d.dname from dept d,emp e where d.deptno=e.deptno;
    select * from empinfo;
    --修改表: 追加新列 修改列 删除列 重名列
    select * from test1;
    alter table test1 add age2 number;
    alter table test1 modify age varchar2(40);
    alter table test1 drop column age;
    alter table test1 rename column tid to ttid;
    select * from tab;
    drop table test1;
    --Oracle的回收站
    select * from recyclebin;
    ---清空回收站
    purge recyclebin;
    --drop table test1 purge; --> 不经过回收站直接删除
    --注意: 管理员没有回收站
    --检查性约束
    create table student(
    sid number primary key,
    sname varchar2(40) not null,
    age number check (age>0),
    gender varchar2(4) check(gender in ('男','女'))
    )
    select * from student;
    insert into student(sid,sname,age,gender) values(2,'aaa',25,'a');
    commit;
    create table teacher(
    sid number constraint t_pk primary key,
    sname varchar2(40) constraint t_name not null,
    age number constraint t_age check (age>0),
    gender varchar2(4) constraint t_gender check(gender in ('男','女'))
    )
    insert into teacher(sid,sname,age,gender) values(2,'aaa',25,'a');
    ----Hello World
    set serveroutput on

    declare

    begin

    dbms_output.put_line('Hello World');
    end;
    /
    -----if语句
    set serveroutput on
    accept num prompt '请输入一个数字';
    declare
    pnum number :=&num;
    begin

    if pnum=1 then dbms_output.put_line('输入的值为1');
    elsif pnum=2 then dbms_output.put_line('输入的值为2');
    elsif pnum=3 then dbms_output.put_line('输入的值为3');
    else dbms_output.put_line('输入的值为其它');
    end if;
    end;
    /
    --带参数的光标
    --查询某个部门中员工的姓名
    set serveroutput on
    accept num prompt '请输入一个数字';
    declare
    cursor cemp(dmo number) is select ename from emp where deptno=dmo;
    pname emp.ename%type;
    pnum number :=&num;
    begin
    open cemp(pnum);
    loop
    fetch cemp into pname;
    exit when cemp%notfound;
    dbms_output.put_line(pname);
    end loop;
    close cemp;

    end;
    /
    -----涨工资 总裁1000 经理800 其他400
    set serveroutput on

    declare
    cursor cemp is select empno,empjob from emp;
    pempno emp.empno%type;
    pjob emp.empjob%type;

    begin
    open cemp;
    loop
    fetch cemp into pempno,pjob;
    exit when cemp%notfound;
    if pjob='PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
    elsif pjob='MANAGER' then update emp set sal=sal+800 where empno=pempno;
    else update emp set sal=sal+400 where empno=pempno;
    end if;
    end loop;
    close cemp;
    commit;
    dbms_output.put_line('完成!');
    end;
    /
    select * from emp;

    -----使用游标查询员工姓名和工资,并打印
    /*
    1. 光标的属性
    %isopen: 是否打开
    %rowcount: 行数
    %notfound: 没有记录

    2. 默认允许一次打开300个光标(修改光标: 第四天 管理方案)
    SQL> show parameters cursor

    NAME TYPE VALUE
    ------------------------------------ ----------- -------
    cursor_sharing string EXACT
    cursor_space_for_time boolean FALSE
    open_cursors integer 300
    session_cached_cursors integer 20
    */
    show parameters cursor;

    set serveroutput 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;
    /
    --------查询并打印7839的姓名和薪水
    --记录型变量 代表一行
    set serveroutput on

    declare

    rec emp%rowtype;
    begin
    select * into rec from emp where empno=7839;
    dbms_output.put_line(rec.empno||'aaaa'||rec.sal);
    end;
    /
    实例1:统计每年入职的员工个数。
    set serveroutput on

    declare
    cursor cemp is select to_char(hiredate,'RR') 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='80' then count80:=count80+1;
    elsif phiredate='81' then count81:=count81+1;
    elsif phiredate='82' then count82:=count82+1;
    else count87:=count87+1;
    end if;
    end loop;
    close cemp;
    dbms_output.put_line('total'||(count80+count81+count82+count87));
    dbms_output.put_line(count80);
    dbms_output.put_line(count81);
    dbms_output.put_line(count82);
    dbms_output.put_line(count87);
    end;
    /
    ---为员工长工资。从最低工资调起每人长10%,但工资总额不能超过5万元,
    ----请计算长工资的人数和长工资后的工资总额,并输出输出长工资人数及工资总额。
    set serveroutput on

    declare
    cursor cemp is select empno,sal from emp;
    pempno emp.empno%type;
    psal emp.sal%type;
    countEmp number :=0;
    salTotal number ;
    begin
    select sum(sal) into salTotal from emp;
    open cemp;
    loop
    exit when salTotal>200000;
    fetch cemp into pempno,psal;
    exit when cemp%notfound;

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

    countEmp :=countEmp+1;
    if salTotal+psal*0.1<200000 then salTotal :=salTotal+psal*0.1;
    else exit;
    end if;
    end loop;
    close cemp;
    commit;
    dbms_output.put_line('人数:'||countEmp||' 工资总额:'||salTotal);
    end;
    /
    -----用PL/SQL语言编写一程序,实现按部门分段(6000以上、(6000,3000)、3000元以下)
    ----统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)

    set serveroutput on

    declare
    cursor cdept is select deptno from dept;
    pdeptno dept.deptno%type;

    cursor cemp(dno number) is select sal from emp where deptno=dno;
    psal emp.sal%type;
    count1 number;count2 number;count3 number;
    salTotal number;
    begin
    open cdept;
    loop
    fetch cdept into pdeptno;
    exit when cdept%notfound;
    count1 :=0;count2 :=0;count3 :=0;
    select sum(sal) into salTotal from emp where deptno=pdeptno;
    open cemp(pdeptno);
    loop
    fetch cemp into psal;
    exit when cemp%notfound;
    if psal<3000 then count1 :=count1+1;
    elsif psal>3000 and psal<6000 then count2 :=count2+1;
    else count3 :=count3+1;
    end if;
    end loop;
    close cemp;
    insert into msg1 values(pdeptno,count1,count2,count3,nvl(salTotal,0));
    end loop;
    close cdept;
    commit;
    dbms_output.put_line('完成');
    end;
    /
    create table msg1(
    n1 number,
    n2 number,
    n3 number,
    n4 number,
    n5 number
    )
    select *  from msg1;
    -----被0除
    set serveroutput on

    declare
    pnum number;
    begin
    pnum :=1/0;

    exception
    when Zero_Divide then dbms_output.put_line('1:0不能做被除数');
    dbms_output.put_line('2:0不能做被除数');
    when Value_error then dbms_output.put_line('算术或转换错误');
    when others then dbms_output.put_line('其他例外');
    end;
    /
    ----循环
    set serveroutput on

    declare
    pnum number;
    begin
    pnum :=0;
    loop
    exit when pnum>10;
    dbms_output.put_line(pnum);
    pnum :=pnum+1;
    end loop;
    end;
    /
    -----查询并打印7839的姓名和薪水
    set serveroutput on

    declare
    pename emp.ename%type;
    psal emp.sal%type;
    begin
    select ename,sal into pename,psal from emp where empno=7839;
    dbms_output.put_line(pename||'的薪水是'||psal);
    end;
    /
    ------查询50号部门的员工
    set serveroutput on

    declare
    cursor cemp is select ename from emp where deptno=30;
    pename emp.ename%type;
    no_emp_found exception;
    begin
    open cemp;
    fetch cemp into pename;
    if cemp%notfound then
    raise no_emp_found;
    end if;


    close cemp;
    exception
    when no_emp_found then dbms_output.put_line('没有找到员工');
    when others then dbms_output.put_line('其他例外');
    end;
    /


    select * from emp;
    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;
    查询并返回某个员工的姓名 月薪和职位

    思考: out参数太多???
    */
    create or replace procedure queryEmpInfo(
    eno in number,
    pename out varchar2,
    psal out number,
    pjob out varchar2
    )
    as
    begin
    select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
    end;
    /
    /*
    实施复杂的安全性检查

    禁止在非工作时间 往emp表中插入数据
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    PLSQL 块

    周末:to_char(sysdate,'day') in ('星期六','星期日')
    上班前 下班后: to_number(to_char(sysdate,'hh24')) not between 9 and 18
    */
    create or replace trigger securityEmp
    before insert
    on emp
    begin
    if to_char(sysdate,'day') in ('星期三','星期六') or
    to_number(to_char(sysdate,'hh24')) not between 9 and 18 then
    raise_application_error(-20001,'不能在非工作时间插入数据');
    end if;
    end;
    /
    select * from emp;
    insert into emp(empno,ename,empjob,sal) values(100,'hhh','manager',8000);
    select * from user_source where name like '%SECURITYEMP%';
    drop trigger checksal;
    /*
    数据确认

    涨后的薪水不能少于涨前的薪水
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    [FOR EACH ROW [WHEN(条件) ] ]
    PLSQL 块

    */
    create or replace trigger checksal
    before update
    on emp
    for each row
    begin
    if :new.sal<:old.sal then
    raise_application_error(-20002,'涨后的薪水不能少于涨前的薪水.涨前:'||:old.sal||' 涨后:'||:new.sal);
    end if;
    end;
    /
    update emp set sal=sal-100 where empno=7839;
    /*
    CREATE [OR REPLACE] FUNCTION 函数名(参数列表)
    RETURN 函数值类型
    AS
    PLSQL子程序体;

    查询某个员工的年收入

    */
    create or replace function queryEmpIncome(eno in number)
    return number
    as
    psal emp.sal%type;
    pcomm emp.comm%type;
    begin
    select sal,comm into psal,pcomm from emp where empno=eno;
    return psal*12+nvl(pcomm,0);
    end;
    /
    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;

    为指定的员工涨100块钱 并打印涨前和涨后的薪水
    */
    create or replace procedure raiseSalary(
    eno in number
    )
    as
    psal emp.sal%type;
    begin
    select sal into psal from emp where empno=eno;
    update emp set sal=sal+100 where empno=eno;
    dbms_output.put_line('涨前:'||psal||' 涨后:'||(psal+100));
    end;
    /

    create or replace trigger sayNewEmp
    after insert on emp
    declare

    begin
    dbms_output.put_line('插入数据!');

    end;
    /
    delete from emp where empno=1000;
    select * from emp;
    select * from user_source where type='CURSOR';
    /*
    1.错误的删除了数据,并且已经提交
    2.错误的删除了表drop table
    3.如何获取表上的历史记录
    4.如何撤销已经提交的事务
    闪回的类型
    1.闪回表:将表返回到过去的一个时间上
    2.闪回删除:操作oracle的回收站
    3.闪回版本查询:表上的历史记录
    4.闪回事务查询:获取表上的一个UNDO_SQL
    5.闪回数据库:将数据库返回到过去的一个时间上
    6.闪回归档日志
    */
    ---查询没有提交的数据
    show parameter undo;
    ----设置闪回时间 scope的取值:memoery(本次回话) spfile(重启后生效) both()
    alter system set undo_retention=1200 scope=both;
    ---系统改变号SCN----6952590965600 6952590966674
    select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss:mm') 时间,
    timestamp_to_scn(sysdate) SCN
    from dual;
    ---闪回表
    create table flashback_table (fid number,fname varchar2(40));
    insert into flashback_table values(1,'tom');
    insert into flashback_table values(2,'marry');
    insert into flashback_table values(3,'mike');

    delete from flashback_table where fid=2;
    select * from flashback_table;
    ---启动行移动ALTER TABLE table_name ENABLE ROW MOVEMENT
    alter table flashback_table enable row movement;
    flashback table flashback_table to SCN 6952590966674;
    ---如何获取离操作最近的一个时间或者SCN?
    select * from tab;
    drop table EMP20 purge;
    ----闪回删除的表
    flashback table MSG1 to before drop rename to msg5 ;
    create table MSG1(mid number,mname varchar2(30));
    select * from msg4;
    show recyclebin;
    purge recyclebin;
    -------管理员没有回收站

    create table ggg(mid number,mname varchar2(30));
    insert into ggg values(1,'ssss');
    drop table ggg;
    select * from ggg;
    flashback table ggg to before drop ;
    flashback table ggg to before drop rename to msg5 ;
    select * from msg5;
    -----返回版本
    create table version_table(tid number,tname varchar2(30));
    insert into version_table values(1,'tom');
    insert into version_table values(2,'mary');
    insert into version_table values(3,'mike');
    update version_table set tname='mary123' where tid=2;
    select * from version_table;
    -----查询返回版本的语法
    select tid,tname,versions_operation,versions_starttime,versions_endtime,versions_xid from version_table versions between timestamp minvalue and maxvalue;
    ----闪回事务查询
    create table tracation_table(tid number,tname varchar2(30));

    insert into tracation_table values(1,'tom');
    insert into tracation_table values(2,'mary');

    insert into tracation_table values(3,'mike');
    update tracation_table set tname='dfdfd' where tid=2;


    select tid,tname,versions_operation,versions_starttime,versions_endtime,versions_xid from tracation_table versions between timestamp minvalue and maxvalue;
    select operation,undo_sql from flashback_transaction_query where xid='0B00080016DF0000';
    exp scott/tiger @10.4.237.4:1521:orcl file=f:/a.dmp log=f:/log.log tables=dept,emp

  • 相关阅读:
    SQL临时表加分页操作
    JS 操作Url参数
    C#字符串根据特定字符串分割
    windows下python读写excel
    怎样才是更好的自己 多好才算更好的未来
    IndentationError: unindent does not match any outer indentation level
    LinAlgError: Array must not contain infs or NaNs
    c#操作xml
    sql索引碎片产生的原理 解决碎片的办法(sql碎片整理)(转)
    利用sys.dm_db_index_physical_stats查看索引碎片等数据(转)
  • 原文地址:https://www.cnblogs.com/zszitman/p/4668300.html
Copyright © 2011-2022 走看看