Oracle



group by语句: select deptno,round(avg(sal),2) from scott.emp group by deptno;

 select job,deptno,avg(sal) from scott.emp group by job,deptno;


select ename,max(sal) from scott.emp

*

第 1 行出现错误:

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

因为一个max(sal) 可能对应多个ename,所以必须出现group by语句

select ename,max(sal) from scott.emp group by ename;

单组函数必须对应的值是唯一的。


where语句是对单条语句进行过滤


having语句是对分组进行过滤。

select deptno,avg(sal) from scott.emp group by deptno having avg(sal)>2000;


select语句顺序


1 select*from scott.emp

2 where sal>1000

3 group by deptno

4 having

5 order by



子查询:查一个人赚的最多

SQL> select ename,sal from scott.emp

2 where sal=(select max(sal) from scott.emp);



自连接

SQL> select e1.ename,e2.ename from scott.emp e1,scott.emp e2 where e1.mgr=e2.empno;


SQL> select ename,dname,grade from scott.emp e,scott.dept d,scott.salgrade s

2 where e.deptno=d.deptno and e.sal between s.losal and s.hisal;


两张表的自连接

SQL> select ename,dname from scott.emp join scott.dept on(emp.deptno=dept.deptno

);


求薪水等级

SQL> select ename,grade from scott.emp e join scott.salgrade s on(e.sal between

s.losal and s.hisal);


综合

SQL> select ename,dname,grade

2 from scott.emp e join scott.dept d on(e.deptno=d.deptno)

3 join scott.salgrade s on(e.sal between s.losal and s.hisal)

4 where ename not like '_A%';


左(右)连接

SQL> select e1.ename,e2.ename from scott.emp e1 left(right) join scott.emp e2 on(e1.mgr

=e2.empno);


求部门中哪些人薪水最高

SQL> select ename,sal from scott.emp

2 join(select max(sal) Max_sal,deptno from scott.emp group by deptno) t

3 on(emp.sal=t.Max_sal and emp.deptno=t.deptno);


求部门中平均薪水的等级

select deptno,grade,Avg_sal from

(select deptno,avg(sal) Avg_sal from scott.emp group by deptno) t

join scott.salgrade s on(t.Avg_sal between s.losal and s.hisal );


部门中那些人是经理人

SQL> select ename from scott.emp where empno in(select mgr from scott.emp);


不用组函数求薪水的最高值

SQL> select distinct sal from scott.emp where sal not in(select distinct e1.sal

2 from scott.emp e1 join scott.emp e2 on(e1.sal<e2.sal));


平均薪水最高的部门的部门编号

1. select deptno,Avg_sal from

(select avg(sal) Avg_sal,deptno from scott.emp group by deptno)

//把那整条语句当成平均工资最高的值来对待。

where Avg_sal=

(select max(Avg_sal) from

(select avg(sal) Avg_sal,deptno from scott.emp group by deptno));


2. 组函数的嵌套:select deptno,avg_sal from

(select avg(sal) avg_sal,deptno from scott.emp group by deptno)

where avg_sal=

(select max(avg(sal)) from scott.emp group by deptno)

平均薪水最高的部门的部门名称

select dname from scott.dept where deptno=

(

select deptno from

(select avg(sal) Avg_sal,deptno from scott.emp group by deptno)

where Avg_sal=

(select max(Avg_sal) from

(select avg(sal) Avg_sal,deptno from scott.emp group by deptno)

)


求平均薪水的等级最低的部门的部门名称

1 select t1.deptno,avg_sal,dname from

2 (select deptno,grade,avg_sal from

3 (select deptno,avg(sal) avg_sal from scott.emp group by deptno) t

4 join scott.salgrade s on(t.avg_sal between s.losal and s.hisal)

5 ) t1

6 join scott.dept on(t1.deptno=dept.deptno)

7 where grade=

8 (

9 select min(grade) from

10 (select grade from

11 (select avg(sal) avg_sal from scott.emp group by deptno) t

12 join scott.salgrade s on(t.avg_sal between s.losal and s.hisal)

13 )

14* )



授权键表格和视图

conn sys/bjsxt as sysdba;

grant create table,create view to scott;



commit 提交完成将不能rollback回退了。
dml 语句 select delete insert  update 
ddl语句 creat table
dcl语句 grant
当用户正常断开连接 cosection 会自动提交

数据库产生对象

怎么创建表

创建一个学生表

create table stu(
id number(6),
name varchar2(20),
sex number(1),
age number(3),
sdata data,
grade number(2) default 1,
class number(2),
email varchar2(50)
);


非空 constraint
create table stu(
id number(6),
name varchar2(20) constraint stu_name_nn not null,
sex number (1),
age number(3),
sdata data,
grade number(2) default 1,
class number(2),
email varchar2(50)
);

唯一约束 unique
create table stu(
id number(6),
name varchar2(20),
sex number(1),
age number(3),
sdata data,
grade number(2) default 1,
class number(2),
email varchar2(50) unique
);

组合约束
create table stu(
id number(6),
name varchar2(20) contraint stu_name_nn not null,
sex number(1),
age number(3),
sdata data,
grade number(2) default 1,
class number(2),
email varchar2(50),
constraint stu_name_email_uni unique(email,name)
)

加字段上,叫字段约束,加表上叫表级约束。

primary key 主键约束。既不能为空又不能重复

 create table stu
 (
 id number(6) primary key,
 name varchar2(20),
 class number(4),
 constriant stu_class_fk foreign key(class) references class(id),
 constraint stu_id_pk primary key(id)
 )

外键约束 foreign key

1  create table stu(
2  id number(6),
3  name varchar2(20),
4  class number(4),
5  constraint stu_class_fk foreign key(class) references class(id),
6  constraint stu_id_pk primary key(id)
7* )

修改表结构 alter
增加数据  alter table stu add(addr varchar2(50));
删除表数据  alter table stu drop (addr);
修改表数据 alter table stu modify(addr varchar(50));
取消约束条件 alter  table stu drop constraint stu_class_fk;
添加约束条件 alter table stu add constraint stu_class_fk foreign key(class) references class(id)

数据字典表
user_tables
user_constraints

创建索引(不能轻易创建,有需要在创建)
create index idx_stu_email on stu (email);

创建视图
功能:
就是一个子查询,简化查询、给出部分信息保护数据,坏处:维护数据。

创建序列 create sequence sqe;
序列下一个数 select sqe.nextval from dual;
删除 drop sequence sqe;

数据库设计三范式:
第一范式:要有主键,列不可分
第二范式:当一张表有多个字段作为主键的时候,非主键字段不能依赖部分主键。不能存在部分依赖。

35_三范式.avi

 数据库设计的三范式:
 范式:数据库设计时的一些规则。而这些规则是由一个姓范的人规定的,所以叫范式
 三范式设计的规则:
 三范式所追寻的原则是:不存在冗余数据(同样的数据我不存第二遍)
 
 第一范式的要求:1.要有主键(设计任何表都要有主键)
   2.列不可分

 第二范式的要求:当一张表里面有多个字段作为主键的时候,非主键的这些字段,不能依赖于部分主键
   (只能依赖整个组合的主键,不能依赖部分)
   叫做:不能存在部分依赖

 第三范式的要求:不能存在传递依赖(除了主键之外的任何其他字段必须直接依赖于主键)

36_BBS_1.avi
 
 1.论坛是要分板块的,板块里面有不同的帖子
 2.帖子是有回复的,第2个人回复第1个人,第3个人回复第2个人,第4个人回复第3个人,第5个人回复第2个人,这是一种树状结构
 3.只有注册的用户才能发表帖子
 4.每一个板块有自己的版主,版主可以删帖子
 按照上面需求,设计表,来支撑我们整个BBS项目

37_BBS_2.avi

 老师与学生探讨表的设计
 user(id,name,password)
 board(id,name,user_id)//版块(版块号,名字,版主)
 message(id,author_id,board_id,content)

PL/SQL语言
SQL> set serveroutput on;
// 默认是 off ,设成 on 是让 Oracle 可以在客户端输出数据
SQL> begin
  2  dbms_output.put_line('hello,world!');
  3  end;
  4  /
hello,world!

PL/SQL 过程已成功完成。
----------------pl/sql变量的赋值与输出----
       declare
              v_name varchar2(20);//声明变量v_name变量的声明以v_开头
       begin
              v_name := 'myname';
              dbms_output.put_line(v_name);
       end;

-----------pl/sql对于异常的处理(除数为0)-------------
       declare
              v_num number := 0;
       begin
              v_num := 2/v_num;
              dbms_output.put_line(v_num);
       exception
              when others then
              dbms_output.put_line('error');
       end;

----------变量的声明----------
       binary_integer:整数,主要用来计数而不是用来表示字段类型   number效率高
       number:数字类型
       char:定长字符串
       varchar2:变长字符串
       date:日期
       long:字符串,最长2GB
       boolean:布尔类型,可以取值truefalsenull//最好给一初值
----------变量的声明,使用 '%type'属性---------
       declare
              v_empno number(4);
              v_empno2 emp.empno%type;
              v_empno3 v_empno2%type;
       begin
              dbms_output.put_line('Test');
       end;
       /
//使用%type属性,可以使变量的声明根据表字段的类型自动变换,省去了维护的麻烦,而且%type属性,可以用于变量身上

constant 相当于java中final
42-----------------Record变量类型(相当于Java里面的类)--------------------------------------------
       declare
              type type_record_dept is record
              (
                     deptno dept.deptno%type,
                     dname dept.dname%type,
                     loc dept.loc%type
              );
              v_temp type_record_dept;
       begin
              v_temp.deptno:=50;
              v_temp.dname:='aaaa';
              v_temp.loc:='bj';
              dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname);
       end;
-----------使用 %rowtype声明record变量,直接参照表来声明record-------------------
       declare
              v_temp dept%rowtype;
       begin
              v_temp.deptno:=50;
              v_temp.dname:='aaaa';
              v_temp.loc:='bj';
       dbms_output.put_line(v temp.deptno || '' || v temp.dname)                
       end;


       
43 --------------select 语句的运用 ( 必须保证 select 语句有相应的返回记录 , 并且只能返回一个值 )-------------------
       declare
              v_ename emp.ename%type;
              v_sal emp.sal%type;
       begin
              select ename,sal into v_ename,v_sal from emp where empno = 7369;
              dbms_output.put_line(v_ename || '' || v_sal);
       end;
---------------------------select 语句的应用( record ----------------------------------------
       declare
              v_emp emp%rowtype;
       begin
              select * into v_emp from emp where empno=7369;
              dbms_output_line(v_emp.ename);
       end;
------------- insert 语句的应用 -----------------------------
       declare
              v_deptno dept.deptno%type := 50;
              v_dname dept.dname%type :='aaa';
              v_loc dept.loc%type := 'bj';
       begin
              insert into dept2 values(v_deptno,v_dname,v_loc);
               commit;
       end;
       ------------- update 语句的应用 ------------------------------
       declare
              v_deptno emp2.deptno%type := 50;
              v_count  number;
       begin
              update emp2 set sal = sal/2 where deptno = v_deptno;
              dbms_output.put_line(sql%rowcount || ‘ 条记录被影响 ’);
               commit;
       end;
注: sql%rowcount 统计上一条 sql 语句更新的记录条数
ddl是create语句
dcl 是 grant语句
if语句
  1  declare
  2  v_sal emp2.sal%type;
  3  begin
  4  select sal into v_sal from emp2 where empno=7839;
  5  if(v_sal>2500)then
  6     dbms_output.put_line(v_sal/2);
  7  elsif(v_sal=2500)then
  8  dbms_output.put_line(v_sal);
  9  else
 10  dbms_output.put_line(v_sal*2);
 11  end if;
 12* end;
loop语句
 1  declare
 2  i binary_integer:=1;
 3  begin
 4  loop
 5  dbms_output.put_line(i);
 6  i:=i+1;
 7  exit when(i>=11);
 8  end loop;
 9* end;

while loop语句
SQL>  declare
  2  j binary_integer:=1;
  3  begin
  4  while j<11 loop
  5  dbms_output.put_line(j);
  6  j:=j+1;
  7  end loop;
  8  end;
  9  /

for循环
  1  begin
  2  for k in 1..10 loop
  3  dbms_output.put_line(k);
  4  end loop;
  5  for k in reverse 1..10 loop
  6  dbms_output.put_line(k);
  7  end loop;
  8* end;

46、-----------------------异常(1) ---------------------------
  declare
  v_temp number(4);
  begin
  select empno into v_temp from emp where deptno = 10;
  exception
  when too_many_rows then
  dbms_output.put_line('太多记录了');
  when others then
  dbms_output.put_line('error');
  end;
-----------------------异常(2) ---------------------------
  declare
  v_temp number(4);
  begin
  select empno into v_temp from emp where empno = 2222;
  exception
  when no_data_found then
  dbms_output.put_line('没有该项数据');
  end;
----------------错误记录日志(用表记录:将系统日志存到数据库便于以后查看) -----------

创建序列(用来处理递增的ID):
  create sequence seq_errorlog_id start with 1 increment by 1;

  创建日志表:
  create table errorlog
  (
  id number primary key,
  errcode number,
  errmsg varchar2(1024),
  errdate date
  );

  示例程序:
  declare
  v_deptno dept.deptno%type := 10;
  v_errcode number;
  v_errmsg varchar2(1024);
  begin
  delete from dept where deptno = v_deptno;
  commit;
  exception
  when others then
  rollback;
  v_errcode := SQLCODE;
  v_errmsg := SQLERRM;
  insert into errorlog values (seq_errorlog_id.nextval, v_errcode,v_errmsg, sysdate);
  commit;
  end;

---------------------PL/SQL 中的重点 cursor( 游标 ) 和指针的概念差不多 ----------------------
       declare
              cursor c is
select * from emp; // 此处的语句不会立刻执行,而是当下面的 open c 的时候,才会真正去数据库中取数据
              v_emp c%rowtype;
       begin
              open c;
                     fetch c into v_emp;
dbms_output.put_line(v_emp.ename); // 这样会只输出一条数据 134 将使用循环的方法输出每一条记录
         close c;
       end;
---------------------- 使用 do while  循环遍历游标中的每一个数据 ---------------------
       declare
              cursor c is
                     select * from emp;
              v_emp c%rowtype;
       begin
              open c;    
              loop
                     fetch c into v_emp;
(1)   exit when (c%notfound);  //notfound oracle 中的关键字,作用是判断是否还有下一条数据
(2)   dbms_output.put_line(v_emp.ename);  //(1)(2) 的顺序不能颠倒,否则会把最后一条结果再多打印一次。
          end loop;
          close c;
       end;
------------------------ 使用 while 循环,遍历游标 ---------------------
       declare
              cursor c is
                     select * from emp;
              v_emp emp%rowtype;
       begin
              open c;
              fetch c into v_emp;
              while(c%found) loop
                 dbms_output.put_line(v_emp.ename);
                 fetch c into v_emp;
          end loop;
          close c;
       end;
-------------------------- 使用for 循环,遍历游标(最方便快捷的方法!) ---------------------
       declare
              cursor c is
                 select * from emp;
       begin
              for v_emp in c loop
                     dbms_output.put_line(v_emp.ename);
              end loop;
       end;
--------------------------- 带参数的游标(相当于函数) ---------------------
       declare
              cursor c(v_deptno emp.deptno%type, v_job emp.job%type)
              is
                 select ename, sal from emp where deptno=v_deptno and job=v_job;
       begin
              for v_temp in c(30, 'CLERK') loop
                     dbms_output.put_line(v_temp.ename);
              end loop;
       end;
------------------------- 可更新的游标 -----------------------------
       declare
              cursor c
              is
                 select * from emp2 for update;
       begin
          for v_temp in c loop
              if(v_temp.sal < 2000) then
                     update emp2 set sal = sal * 2 where current of c;
             elsif (v_temp.sal =5000) then
              delete from emp2 where current of c;
              end if;
            end loop;
            commit;
       end;

-----------------------------创建触发器(trigger) 触发器不能单独的存在,必须依附在某一张表上
写 主语 谓语 宾语 游戏
  创建触发器的依附表:

  create table emp2_log
  (
  ename varchar2(30) ,
  eaction varchar2(20),
  etime date
  );

  create or replace trigger trig
after insert or delete or update on emp2 for each row --加上此句,每更新一行,触发一次,不加入则值触发一次
  begin
  if inserting then
  insert into emp2_log values(USER, 'insert', sysdate);
  elsif updating then
  insert into emp2_log values(USER, 'update', sysdate);
  elsif deleting then
  insert into emp2_log values(USER, 'delete', sysdate);
  end if;
  end;
更新
update emp2 set sal=sal*2 where deptno=30;
查看更新日志。
select*from emp2_log;

-------------------- 触发器用法之一:通过触发器更新约束的相关数据 -------------------
       create or replace trigger trig
              after update on dept
              for each row
       begin
              update emp set deptno =:NEW.deptno where deptno =: OLD.deptno;
       end;
       
       // 只编译不显示的解决办法 set serveroutput on;

52 ------------------------------- 通过创建存储过程完成递归
    

 create or replace procedure p(v_pid article.pid%type,v_level binary_integer) is
              cursor c is select * from article where pid = v_pid;
              v_preStr varchar2(1024) := '';
       begin
         for i in 0..v_level loop
              v_preStr := v_preStr || '----';
         end loop;
         for v_article in c loop
              dbms_output.put_line(v_preStr||v_article.cont);
              if(v_article.isleaf = 0) then
                     p(v_article.id,v_level+1);
              end if;
              end loop;
       end;

通过创建存储过程完成递归(完成输出表)
create or replace procedure p is
cursor c is select*from scott.emp;
c_row c%rowtype;
begin
for c_row in c loop
dbms_output.put_line(c_row.ename||' '||c_row.deptno||' '||c_row.mgr||' '||c_row.job||' '||to_char(c_row.hiredate,'YYYY-MM-DD')||' '||c_row.sal||' '||nvl(c_row.comm,0));
end loop;
end;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值