oracle学习笔记--快速入门

【注】本笔记是看完黑马视频后的学习笔记

1. 创建

1.1.创建表空间

Create tablespace mytable –创建一个名为mytable的表空间
Datafile ‘c:\myraclefiel.dbf’ –数据存放位置
Size 100m –表空间大小为100m
Autoextend on –自动扩展大小
Next 10m; –每次拓展10m

1.2. 删除表空间

Deop tablespace mytable

1.3.创建用户

Create user mjn –-用户名
Identified by 123  ---密码
Default tablespace mytable  ---制定用户作用的表空间(每个用户能看到的表不一样)

1.4.用户授权

在这里插入图片描述

Grant 角色 to 用户名
例子:grant dba to mjn ---给mjn用户授dba角色的权力

此时mjn用户才可以进行登录

1.5.常用数据类型

oracle学习笔记--快速入门_第1张图片

char为定长,就算只有一个,也会占十位,所以会出现空格

varchar2为变长,需要几个位置就占几个位置

Bolb用于存储如视频类数据

Clob用于存储文本类型

1.6.建表

Create table person( ---创建person表
      Pid number(20),---pid字段为number型,20位长度
      Pname varchar2(10)
)

1.7.该表结构

---添加多列
Alter table person add (
      Age number(3),
      Email varchar2(20)
);
---修改列类型
Alter table person modify pname char(10);--- pname字段改为char(10)类型
---修改列名
Alter table person rename column email to addr;---把email列名改为addr
---删除一列
Alter table person drop column age;---删除age列

1.8.表内数据的操作

---加数据
Insert into person(pid, pname, age,addr) values(1, ‘小明’,12,‘撒法规’)Commit;
---修改数据
Update person set pname = ‘小马’ where pid=1;
Commit;
---删除数据
 

---序列不真的属于任何一张表,但可以逻辑上和表绑定
---序列,默认从1开始,依次递增,主要用来给逐渐复制使用
--- dual: 虚表,知识为了补全语法,没有任何意义
Create sequence s_person;---创建序列
Select s_person.nextval from dual;---序列默认是没有的,所以必须先执行一次这个
Select s_person.currval from dual;

---利用序列当id,插入语句
Insert into person(pid, pname, age,addr) values(s_person.nextval, ‘小明’,12,‘撒法规’)Commit;


1.9.scott用户—用于学习的用户

默认密码tiger

1.	用dba角色的用户解锁scott用户
Lock:锁定
Unlock:解锁
Alter user scott account unlock;---解锁scott用户
---解锁scott的密码(或者重置密码也可以)
Alter user scott identified by tiger;---重置密码也可以用这句


2. orcal操作

2.1. 单行函数

---字符函数
Select upper(‘yes’) from dual; ---转大写
Select lower(‘YES’) from dual; ---转小写
---数值函数
Select round(12.14,1) from dual; ---四舍五入,后面的参数表示保留的位数,如果为-1,则保留到十位数,以此类推。
Select trunc(23.28,-1) from dual; ---直接截取,后面的参数表示截取的位数
Select mod(10,3) from dual; ---求余数
---日期函数
例子:求emp中每个员工入职了多少天了
Select sysdate-e.hirdate from emp e;

例子:求明天的此刻
Select sysdate+1 from dual;

例子:查询emp每个员工入职几个月了
Select months_between(sysdate,e.hirdate) from emp e;

例子:查询emp每个员工入职几年了?
Select months_between(sysdate,e.hirdate)/12 from emp e;

例子:查询emp每个员工入职几周了?
Select round((sysdate-e.hirdate)/7 ) from emp e;
---转换函数

---日期转字符串
Select to_char(sysdate,’fm yyyy-mm-dd hh24:mi:ss’)  from dual; ---fm用去去掉0,24代表24小时计数法

---字符串转日期
Select to_date(2020-6-7 12:34:23,’fm yyyy-mm-dd hh24:mi:ss’) from dual;
---通用函数
---例子:计算所有员工的年薪(奖金中有null值)
Select e.sal*12+nvl(e.comm,0) from emp e;--- nvl(e.comm,0)用0代替null

---条件表达式(mysql与orcal通用,多用)
例子:给emp员工取中文名字
Select e.ename,
Case e.ename ---等值判断必须写
    When ‘smith’ then ‘曹操’
        When ‘allen’ then ‘周瑜’
            When ‘ward’ then ‘诸葛亮’
                else ‘无名氏’   ---其他人都取名为无名氏(此句可以不要)
                   end
From emp e;

---判断emp工资,高于3000现实高收入,1500~3000为中收入,其余为低收入
Select e.sal,
Case ---如果是范围判断,此处不写
    When e.sal>3000 then ‘高收入’
        When e.sal>1500 then ‘中收入’ 
            else ‘低收入‘ 
               end
From emp e;

---orcal专用条件表达式(少用)
Select e.ename,
decode(e.ename 
    ‘smith’ , ‘曹操’,
        ‘allen’ , ‘周瑜’,
            ‘ward’ , ‘诸葛亮’,
                ‘无名氏’) 中文名---修改列名为’中文名’,注意引号不要用单引号
                   
From emp e;

2.2. 多行函数(聚合函数)

作用于多行,返回一个数值

Select count(1) from emp; ---查询总数量

Select sum(sal) from emp; ---查询工资总和

Select max(sal) from emp; ---查询最大工资

Select min(sal) from emp; ---查询最小工资

Select avg(sal) from emp; ---查询工资平均数

2.3. 分组查询

【注】

  1. 分组查询中,只有出现在group by后面的原始列,才能在select后面出现,否则都必须加上聚合函数才能出现;
  2. 判断条件都不能使用别名
---例子:查询每个部门平均工资
Select e.deptno,avg(e.sal)
From emp e
Group by e.deptno

---例子:查询平均工资高于2000的部门信息
Select e.deptno,avg(e.sal) asal
From emp e
Group by e.deptno
Having avg(sal)>2000 ---这里不能使用asal

---例子:查询每个部门工资高于800的员工的平均工资
Select e.deptno,avg(e.sal) asal
From emp e
Where e.sal>800
Group by e.deptno

---例子:查询每个部门工资高于800的员工的平均工资,且平均工资高于2000的部门
Select e.deptno,avg(e.sal) asal
From emp e
Where e.sal>800
Group by e.deptno
Having avg(e,sal)>2000

3. 多表查询

3.1. 一些概念

--mysql与orcal通用(多用)
---笛卡尔积
Select * 
From emp e, dept d;

---等值连接
Select * 
From emp e, dept d
Where e.deptno=d.deptno

---内连接
Select * 
From emp e inner join dept d
on e.deptno=d.deptno

---外连接
---例子:查询所有部门以及部门下的员工信息
Select * 
From emp e right join dept d
on e.deptno=d.deptno

--例子:查询员工及其对应的部门
Select * 
From emp e leftjoin dept d
on e.deptno=d.deptno

---orcal中专用外连接(少用)
---例子:查询员工信息,且要求显示部门表所有数据
Select * 
From emp e, dept d
Where e.deptno(+=d.deptno

---例子:查询员工信息,且要求显示emp表所有数据
Select * 
From emp e, dept d
Where e.deptno = d.deptno(+

3.2. 复杂的多表查询

---自连接:站在不同的角度吧一张表看做多张表
---例子:查询员工姓名,其领导的姓名
Select e1.ename,e2.ename 
From emp e1, emp e2  ---e1是员工表,e2是领导表
Where e1.mgr=e2.empno

---例子:查询员工姓名,员工部门名称,其领导的姓名,领导部门名称
Select e1.ename, d1.dname, e2.ename d2.dname
From emp e1, emp e2,dept d1, dept d2
Where e1.mgr=e2.empno
And e1.deptno=d1.deptno
And e2.deptno=d2.deptno;
---子查询
---子查询返回一个数值
---例子:查询工资和scott一样的员工
Select * from emp where sal in(
Selct sal from where ename=’scott’)

---子查询返回一个集合
---例子:查询工资和10号部门任意员工一样的员工信息
Select * from emp where sal in(
Selct sal from where deptno=10)

---子查询返回一张表
---查询每个部门最低工资,和最低工资员工姓名及该员工部门名字
----1.先查每个部门的最低工资
Select deptno,min(sal) msal
From emp
Group by deptno
----2.三表联查,得到最终结果
Select t.deptno, t.msal,e.ename, d.dname
FromSelect deptno,min(sal) msal
From emp
Group by deptno)t, emp e,dept d
Where t.deptno=e.deptno
And t.msal = e.sal
And e.deptno = d.deptno

3.3.orcal中的分页

概念:rownum行号

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911143232248.png#pic_center)

【注】

排序会影响rownum的顺序,再查一次即可解决

Rownum不能写rownum>某正数

---emp按工资倒序排列后,每页五条,查询第二页
Select * from
(Select rownum rn,e.* from  ---- rownum取名为rn,变成普通列
(Select e.* from emp e order by e.sal desc) e
Where rownum<11) t
Where rn>5

4. 视图

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911143251654.png#pic_center)

4.1. 创建视图

必须有dba权限

---通过查询语句创建表(把scott用户的emp表取过来)
Creat table emp as select * from scott.emp
Select * from emp;
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140441660.png#pic_center)


---创建视图
Create view v_emp as select ename,job from emp;---视图名称叫v_emp
---创建只读视图
Create view v_emp1 as select ename,job from emp with readonly;
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140603514.png#pic_center)


---查询视图
Select * from v_emp;
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140712436.png#pic_center)


---修改视图【不推荐】
Update v_emp set job=’clerk’ where ename=’allen’;---修改第二个人的工作
Commit;
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140721272.png#pic_center)

【视图改变,则原表的数据也改变了】
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140736491.png#pic_center)


---视图作用
---1.用于屏蔽敏感字段;
---2.保障总部分布数据及时统一

5. 索引

---单列索引
---创建索引
Create index idx_ename on emp(ename);
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140808564.png#pic_center)

---单列索引触发规则:条件必须是索引列中的原始值,
---单行函数、模糊查询,都会影响索引的触发。
Select * from emp where ename=’scott’;---触发
---复合索引
---创建复合索引
Create index idx_ename on emp(ename,job);
 
---复合索引第一列为优先检索列,要触发,必须包含有优先检索列中的原始值
Select * from emp where ename = ‘scott’ and job=’xx’;---触发复合索引
Select * from emp where ename = ‘scott’;---触发单列索引
Select * from emp where ename = ‘scott’ or job=’xx’;---不触发索引


6. pl/sql编程语言

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140855607.png#pic_center)

6.1.声明方法和变量

---声明方法
---赋值操作可以用:=也可以用into语句赋值
declare
i  number(2) :=10;  ---定义一个2位的number型变量i,复制10
s varchar2(10) :=’小明’;
ena emp.ename%type; ---定义一个与ename同类型的变量(引用型变量)
emprow emp%rowtype;--存一个一行的对象(记录型变量)
begin 
dbms_output.put_line(i); ---打印i
dbms_output.put_line(s);
select ename into ena from emp where empno=7788;---将查询结果赋给ena
dbms_output.put_line(ena);
select * into emprow from emp where empno=7788;---将查询结果赋给emprow
dbms_output.put_line(emprow.ename || ‘的工作是’ || emprow.job);---字符串拼接
end;

6.2.if判断

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911140941240.png#pic_center)
Declare
    i number(3) := &x;
Begin
If i<18 then
    Dbms_output.putline(‘未成年’);
Elsif i<40 then
    Dbms_output.putline(‘中年’);
Else
    Dbms_output.putline(‘老年’);
End if;
End;

【注】也可以用if代替所有elsif 和else

6.3.循环

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141017438.png#pic_center)
 
---方法1:while
Declare
    i number(3) :=1;
Begin
While i<11 loop;
    Dbms_output.putline(i);
    I := i+1;
End loop;
End;

---方法2:exit退出循环(常用)
Declare
    i number(3) :=1;
Begin
loop;
    exit when i>10;
    Dbms_output.putline(i);
    I := i+1;
End loop;
End;
---方法3:for循环
Declare
    i number(3) :=1;
Begin
For I in 1..10 loop
    dbms_output.putline(i);
End loop
End;


6.4.游标

可存放多个对象,多行记录

---输出emp中所有员工姓名
Declare
cursor c1 is select * from emp;--将emp全部存入c1游标中
emprow emp%rowtype;
Begin
open c1;
    loop
        fetch c1 into emprow;--遍历每一行
        exit when c1%notfound;--当查不到时退出
        dbms_output.putline(emprow.ename);
    end loop;
close c1;
End;

---给制定部门员工涨工资
Declare
cursor c2(eno emp.deptno%type) --eno是c2中的参数,存的指定部门
is select empno from emp where deptno = eno; --取出部门为10的所有员工的编号
en emp.empno%type;--用来存每一个编号
Begin
open c2(10;--打开时,要给参数eno赋值为10
    loop
        fetch c2 into emprow;--遍历每一个部门编号
        exit when c2%notfound;--当查不到时退出
        update emp set sal=sal+100 where empno=en;---执行sql
        commit;
    end loop;
close c2;
End;

执行前
在这里插入图片描述
执行后
在这里插入图片描述

6.5.存储过程

就是一段已经编译好的pl/sql语言,放置在数据库端,可以直接被调用。这一段pl/sql一般都是固定的步骤的业务。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141311648.png#pic_center)
---给制定员工涨薪100
--- or replace用于如果名字重复时,直接在旧的基础上修改,一般加上
create or replace procedure p1(eno emp.empno%type)---传递变量进来
is

begin
update emp set sal=sal+100 where empno=eno;
commit;
end
直接执行后:如果创建成功
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141344691.png#pic_center)

如果创建失败
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141351442.png#pic_center)

---测试调用p1
declare
    
begin
p1(7788)
end;
执行前
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020091114135742.png#pic_center)

执行后
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141401349.png#pic_center)


6.6.存储函数

语法

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141434611.png#pic_center)
---通过存储函数计算制定员工的年薪
---注:存储过程和存储函数的参数都不能带长度
---(emp.empno%type---引用型变量在不用长度时会自动去掉长度,所以自己写number时不能带长度)
---存储函数的返回值类型(下文的number)不能带长度
create or replace function f_yearsal(eno emp.empno%type) return number—这里不带长度
is
    s number(10);
begin
select sal*12+nvl(comm,0) into s from emp where empno=eno;
return s; ---往外输出的数值
end
运行之后:
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141449723.png#pic_center)

---测试f_yearsal,存储函数在调用的时候,返回值必须要接受
Declare
    S number(10);
Begin
S := f_yearsal(7788);
dbms_ouput.put_line(S);
End
输出结果:
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141454888.png#pic_center)

6.7.out类型参数如何使用

---使用存储过程计算年薪
--- yearsal为向外输出数值使用的变量,也不能指定长度
Create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number)
Is
s number(10);---存工资
c emp.comm%type;---存奖金
Begin
Select sal * 12, nvl(comm,0) into s, c from emp where empno=eno;
yearsal :=s+c;
end
运行后:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911141843290.png#pic_center)
 
---测试
Declare
    yearsal number(10)
Begin
p_yearsal(7788, yearsal);
dbms_ouput.put_line(yearsal);
end

In和out的区别:

Create语句中,凡是涉及into查询语句或者:=赋值操作的参数,都必须使用out来修饰(如上文的yearsal)。其余的度使用in(如上文的eno)。

【注】:上文的s,c不是参数,是普通变量,create中的eno和yearsal才是参数。

6.8.存储过程和存储函数的区别

 

存储过程

存储函数

关键字不同

procedure

function

有无reutrn返回值

没有

存储过程和存储函数的区别

语法区别:关键字不一样,

存储函数比存储过程多了两个return。

本质区别:存储函数有返回值,而存储过程没有返回值。

如果存储过程想实现有返回值的业务,我们就必须使用out类型的参数。

即便是存储过程使用了out类型的参数,起本质也不是真的有了返回值,

而是在存储过程内部给out类型参数赋值,在执行完毕后,我们直接拿到输出类型参数的值。

【注】可以使用存储函数有单回执的特性来自定义函数,而存储过程不能自定义函数

---例子:查询员工姓名,所在部门名称
----准备工作:把scott下的dept表复制过来
Creat table dept as select * from scott.dept;
---通过传统方式实现
Select e.ename,d.dname
From emp e, dept d
Where e.deptno=d.deptno

---使用存储函数实现:提供一个部门编号,输出一个部门名称
create or replace function fdna(dno dept.deptno%type) return dept.dname%type
is
dna dept.dname%type;
begin
select dname into dna from dept where deptno=dno;
return dna;
end;
运行后
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020091114200754.png#pic_center)

---使用fdna存储函数来实现需求:查询员工姓名,所在部门名称
Select e.ename,fdna(e.deptno)---这种操作只有存储函数能做,因为只有它有返回值
From emp e;

7. 触发器

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142014511.png#pic_center) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142338349.png#pic_center)

7.1. 语句级触发器

---例子:插入一条记录,输出一个新员工入职
Create or replace trigger t1  --- trigger是触发器关键字,t1是触发器名称
after  ---触发时间:操作完成之后
insert  ---触发动作:插入数据
on person ---监视对象:person表
declare

begin
    dbms_ouput.put_line(‘一个新员工入职’);
end;
运行后:
 
---触发t1
Insert into person values(1,’小红’)Commit;
---执行完上文后,会触发t1,而后输出:
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142407756.png#pic_center)

7.2. 行级触发器

---例子:不能给员工降薪(不允许更新前的工资高于更新后的工资)
--- raise_application_error(-20001~-20999之间,不能重复,’提示信息’);---自定义的异常
Create or replace trigger t2
Befor
Update
On emp
For each row
Declare

Begin
If :old.sal>:new.sal then---如果更新之前的sal大于更新后的
    raise_application_error(-20001,’不能给员工降薪’);---抛出异常
End if;
End;
执行后:
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142501678.png#pic_center)

---触发t2
Update emp set sal=sal-1 where empno=7788;
Commit;
执行时:
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142533170.png#pic_center)

---查看结果:sal没有减少
 
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142538403.png#pic_center)

---例子:用触发器实现主键自增(行级触发器)
---分析:在用户插入前拿到即将插入的数据,给主键列赋值
Create or replace trigger auid
Befor
Insert
On person
For each row
Declare

Begin
    Select s_person.next into :new.pid from dual;---从虚表获取新的id赋值给pid
End;
执行后:
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142556537.png#pic_center)

---使用auid实现主键自增
Insert into person (pname) values(‘a’);
Commit;
---结果
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142602551.png#pic_center)

---如果执行
Insert into person values(1,‘b’);
Commit;
---结果
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020091114260922.png#pic_center)

---依然可以递增的增加,所以传入的id没有效果


8. Java调用存储过程和存储函数

Oracle版本与jar包版本对应

![在这里插入图片描述](https://img-blog.csdnimg.cn/2020091114261956.png#pic_center)

8.1.maven导包

<dependency>
          <groupId>com.oraclegroupId>
          <artifactId>ojdbc14artifactId>
          <version>10.2.0.4.0version>
 dependency>
 <dependency>
       <groupId>junitgroupId>
         <artifactId>junitartifactId>
         <version>4.10version>
         <scope>testscope>
 dependency>

8.2.demo

@Test
    public void javaCallOracle() throws Exception {
        //加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //得到Connection连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.6:1521:orcl",
                "itheima", "itheima");
        //得到预编译的Statement对象
        PreparedStatement pstm = connection.prepareStatement("select * from emp where empno = ?");
        //给参数赋值
        pstm.setObject(1, 7788);
        //执行数据库查询操作
        ResultSet rs = pstm.executeQuery();
        //输出结果
        while(rs.next()){
            System.out.println(rs.getString("ename"));
        }
        //释放资源
        rs.close();
        pstm.close();
        connection.close();
}

执行结果:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200911142815500.png#pic_center)

8.3.调用存储过程和存储函数

/**
     * java调用存储过程
     * {?= call [(,, ...)]}   调用存储函数使用
     *  {call [(,, ...)]}   调用存储过程使用
     * @throws Exception
     */
    @Test
    public void javaCallProcedure() throws Exception {
        //加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //得到Connection连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.6:1521:orcl",
                "itheima", "itheima");
        //得到预编译的Statement对象
        CallableStatement pstm = connection.prepareCall("{call p_yearsal(?, ?)}");
        //给参数赋值
        pstm.setObject(1, 7788);//第一个参数是7788
        pstm.registerOutParameter(2, OracleTypes.NUMBER);//第二个参数是输出类型
        //执行数据库查询操作
        pstm.execute();
        //输出结果[第二个参数]
        System.out.println(pstm.getObject(2));
        //释放资源
        pstm.close();
        connection.close();
}

结果
在这里插入图片描述

/**
     * java调用存储函数
     * {?= call [(,, ...)]}   调用存储函数使用
     *  {call [(,, ...)]}   调用存储过程使用
     * @throws Exception
     */
    @Test
    public void javaCallFunction() throws Exception {
        //加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //得到Connection连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.6:1521:orcl",
                "itheima", "itheima");
        //得到预编译的Statement对象
        CallableStatement pstm = connection.prepareCall("{?= call f_yearsal(?)}");
        //给参数赋值
        pstm.setObject(2, 7788);
        pstm.registerOutParameter(1, OracleTypes.NUMBER);
        //执行数据库查询操作
        pstm.execute();
        //输出结果[第一个参数]
        System.out.println(pstm.getObject(1));
        //释放资源
        pstm.close();
        connection.close();
    }
}

在这里插入图片描述

你可能感兴趣的:(Java,oracle,数据库,oracle)