【注】本笔记是看完黑马视频后的学习笔记
Create tablespace mytable –创建一个名为mytable的表空间
Datafile ‘c:\myraclefiel.dbf’ –数据存放位置
Size 100m –表空间大小为100m
Autoextend on –自动扩展大小
Next 10m; –每次拓展10m
Deop tablespace mytable
Create user mjn –-用户名
Identified by 123 ---密码
Default tablespace mytable ---制定用户作用的表空间(每个用户能看到的表不一样)
Grant 角色 to 用户名
例子:grant dba to mjn ---给mjn用户授dba角色的权力
此时mjn用户才可以进行登录
char为定长,就算只有一个,也会占十位,所以会出现空格
varchar2为变长,需要几个位置就占几个位置
Bolb用于存储如视频类数据
Clob用于存储文本类型
Create table person( ---创建person表
Pid number(20),---pid字段为number型,20位长度
Pname varchar2(10)
)
---添加多列
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列
---加数据
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;
默认密码tiger
1. 用dba角色的用户解锁scott用户
Lock:锁定
Unlock:解锁
Alter user scott account unlock;---解锁scott用户
---解锁scott的密码(或者重置密码也可以)
Alter user scott identified by tiger;---重置密码也可以用这句
---字符函数
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;
作用于多行,返回一个数值
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; ---查询工资平均数
【注】
---例子:查询每个部门平均工资
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
--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(+)
---自连接:站在不同的角度吧一张表看做多张表
---例子:查询员工姓名,其领导的姓名
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
From (
Select 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
概念: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
必须有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.保障总部分布数据及时统一
---单列索引
---创建索引
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’;---不触发索引
---声明方法
---赋值操作可以用:=也可以用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;
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
---方法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;
可存放多个对象,多行记录
---输出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;
就是一段已经编译好的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)
语法
![在这里插入图片描述](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)
---使用存储过程计算年薪
--- 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才是参数。
|
存储过程 |
存储函数 |
关键字不同 |
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;
---例子:插入一条记录,输出一个新员工入职
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)
---例子:不能给员工降薪(不允许更新前的工资高于更新后的工资)
--- 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没有效果
Oracle版本与jar包版本对应
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020091114261956.png#pic_center)<dependency>
<groupId>com.oraclegroupId>
<artifactId>ojdbc14artifactId>
<version>10.2.0.4.0version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.10version>
<scope>testscope>
dependency>
@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)/**
* 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();
}
}