多表查询:
会出现笛卡尔积,为了避免出现笛卡尔积,要使用where 语句对字段进行关联操作
左右连接
(+)在=左边表示右连接,(+)在= 右边表示左连接
select e.name ,e.id,m.name,m.id from emp e,emp m where e.id = m.id(+);
交叉连接 cross join 产生笛卡尔积
left join 和right join
natural join
自然连接,自动进行关联字段的匹配
select * from emp e natural join dept;
using
可以使用using关键字来简化连接查询,但是只是在查询满足下面两个条件时,才能使用using关键字进行简化。
1.查询必须是等值连接。
2.等值连接中的列必须具有相同的名称和数据类型。
select * from emp e join dept d using(deptno);
on
用户自己编写连接的条件 select * from emp e join dept d on (e.deptno = d.deptno);
组函数及分组计算
count()查询所有的记录数
max() min()最大,最小值
sum()求和
avg()平均值
select deptno, count(empno ) from emp group by deptno;
一、 如果程序中使用了分组函数,则有两种可以使用的情况:
1、程序中使用了group by ,并指定了分组条件,这样可以将分组条件一起查询出来。
2、如果不使用分组的话,则只能单独的使用分组函数。
二、 在使用分组函数的时候,不能出现分组函数和分组条件之外的字段
where 语句中不能使用分组函数 ,下面这句话是错误的
select deptno , avg(sal) from emp where avg(sal)>2000 group by deptno ;
正确的写法是:select deptno , avg(sal) from emp group by deptno having avg(sal)>2000
使用分组的情况:只有在某一列上存在重复的数据才有可能使用到分组;
注意:
分组函数可以嵌套使用,但是在分组函数嵌套使用的时候,不能再出现分组条件的查询语句
错误的语句: select deptno , max(avg(sal)) from emp group by deptno;
正确的语句: select max(avg(sal)) from emp group by deptno;
子查询
select * from emp where sal >(select sal from emp where empno=74);
子查询必须在()中包括
子查询在操作中分为三类:
1、单列子查询,返回的结果是一列的一个
2、单行子查询,返回多个列,有可能是一条完整的记录
3、多行子查询,返回多条记录
在子查询中存在三种符号:
in 指定查询的范围
select * from emp where sal in (select min(sal) from emp group by deptno );
any
=any 的时候,与in 的功能完全一样
<any 比最大的值要小
>any 比最小的值要大
all
>all比最大的值要大,<all比最小的只要小
约束
主键约束(primary key ): 表示唯一标识,不可为空
创建主键
create table user (
id varchar(32) primary key;
name varchar(25),
)
也可以这样设置:
create table user (
id varchar(32),
name varchar(25),
constraint user_id_pk primary key (id)
);
唯一约束: 在一个表中,只允许建立一个主键约束,其他列如果不希望出现重复值,就可以使用 唯一约束。
constraint user_name_uk unique(name);
create table user ( name varchar(25) unique);
检查约束(check):检查一个列的内容是否合法
非空约束: not null
外键约束 (foreign key):
注意:
1、在子表中设置的外键在主表中必须是主键,
2、删除时,应该先删除字表中的数据,然后删除父表数据
修改约束:
alter table 表名称 add constraint 约束名称 约束类型 (约束字段)
alter table 表名称 drop constraint 约束名
视图
封装了复杂的查询语句
create view 视图名 as 子查询
drop view 视图名
修改视图 create or replace view 视图名 as 子查询
注意:
1、为了避免创建视图的条件更改之后,导致视图查询失效,可以在创建视图的时候加入条件
create view 视图名 as 子查询 with check option
2、为了避免在视图 对主表进行修改 ,在创建视图的时候要添加 条件 with read only
序列
序列创建完成之后,所有的自动增长应该由用户自己处理,所以在序列中提供了一下两种操作:
nextval 取得序列的下一个值
currval 获取序列的当前值
创建序列 create sequence 序列名;
修改序列增长幅度 increment by 长度
指定序列的开始位置 start with 数字
创建序列,并指定序列在1,3,5,7,9中循环取值 create sequece 序列名 maxvalue 10 increment by 2 cycle;
同义词
create synonym 同义词名称 for 用户名.表名称(例如:dual)
用户管理
创建用户:create user 用户名 identified by 密码;
授权:grant connect resource to 用户名;
让用户密码失效:alter user 用户名 password expire;
锁住用户: alter user 用户名 account lock;
解锁用户:alter user 用户名 account unlock;
将 scott用户下的某张表的权限分配给另一个用户: grant delete ,select on scott.emp to 用户名;
回收权限: revoke 权限 on 用户名.表名称 from 用户;
数据库的备份与恢复
备份: exp
导入:imp
嵌套表
1、建立嵌套表的前提是指定类型:
create type project_ty as object(
id number(4) ,
name varchar(25)
);/
注意这个“/”不能省略
2、类型创建完成之后,并不意味着这个类型可以使用,因为此类型是一个完整的类型,还需指定一个名称。
create type project_nt as table of project_ty ;
/
这样以后直接使用project_nt 表示project_ty 类型,就类似 varchar2表示字符串。
3、开始制定嵌套表
create table department(
departId number(4) primary key ,
name varchar2(20),
project project_nt
)nested table project store as project_nt_emp ;
插入值
insert into department(
'1','技术部'
project_nt(
project_ty ('1','qq项目'),
project_ty ('2','微信项目')
)
);
查询
select * from table(select project from department from where departId =1);
更新
update table(select project from department where departId =1) pro
set value (pro) = (project_ty ('001','战狼项目')) where pro.id=1;
可变数组
创建过程与嵌套表类似,不同点在于第二步
create type project_nt as varry(10) of project_ty ;/
游标
1、用法:
declare cursor c is select * from emp ;
begin
for v_emp in c loop
dbms.output.putline(v_emp.name )
end loop;
end;
2、
declare cursor c is select * from emp for update ;
begin
for v_emp in c loop
if<v_emp.sal>2000> then
update emp set sal = sal *2 where current of c;
elseif <v_emp.sal=5000> then
update emp set sal =sal/2 where current of c;
end if;
end loop;
commit;
end;
存储过程
1、创建存储过程:
create or replace procedure p
is cursor c is select * from emp for update ;
begin
for v_emp in c loop
if2000> then
update emp set sal = sal *2 where current of c;
elseif then
update emp set sal =sal/2 where current of c;
end if;
end loop;
commit;
end;
2、执行存储过程
exec p;
包含参数的存储过程
创建过程:
create or replace procedure p <a in number, b number , c out number , d in out number>
is
begin
if <a>b> then
c:=a;
else
c := b;
end if ;
c:=d+1;
end ;
使用过程:
declare
a number :=1;
b number :=2;
c number ;
d number := 5;
begin
p<a,b,c,d> ;
dbms_output.put_line(c);
end
函数
create or replace function func<a number> return number;
is
begin
if<a>1600> then
return 0.3;
else
return 0.4;
end if
return 0.6;
end;
触发器
create or replace trigger trig
after update or delete or insert on emp for each row
begin
if inserting then
insert into log values ('user','do something','date');
end if ;
end;
递归存储过程
树状帖子表
create table article (
id number primary key,
content varchar(4000),
pid number,
alevel number;// 0 代表非叶子节点,1代表叶子节点
vlevel number , //代表层级,表示它属于第几层
);
创建递归过程显示帖子结构:
create or replace procedure p( id article.id%type ,vlevel binary_integer) is
cursor c is select article where id = id ;
preStr varchar(1000) := '';
begin
for i in 0..vlevel loop
preStr := preStr || '------';
end loop;
for temp in c loop
dbms_output_putline(preStr || temp.content);
if (temp.alevel = 0) then
p(temp.id,temp.vlevel);
end if;
end loop;
end;