Oracle入门基本知识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37610397/article/details/82085755

Oracle基本概念及信息

  • Oracle数据库是适合操作较大数据量的收费数据库,在操作大量数据时明显会比MySQL的效率高出很多。
  • 版本主要分为:Oracle9i,Oracle10i(i表示internet),Oracle11g(g表示grid),Oracle12c(Cloud融合云计算服务器)。
  • Oracle数据库的主端口:1521。
  • Oracle服务器由实例和数据库组成。实例:理解为对象,看不见。数据库:理解为类,看得见,在D:\oracle\oradata\orcl*.DBF
  • 一个Oracle服务器中包含多个数据库,例如:orcl,orm,bbs等等,在D:\oracle\oracleDB\oradata\目录下,有多少个文件夹,就有多个数据库。

常用Oracle命令(以sqlplus工具操作为例)

sqlplus / as sysdba 以超级管理员角色进入(固定写法)
sqlplus scott/tigger 以普通用户的身份进入,scott为用户名,tigger为密码。
alter user scott/hr account unlock; 解锁用户
alter user scott/hr identified by tiger/lion 设置普通用户scott的密码为tiger
password为当前用户修改密码
show user;查询当前用户是谁
exit 退出登录
@ e:/crm.sql;使用@命令,将硬盘文件e:/crm.sql,读到orcl实例中,并执行文件中的sql语句
set time on; set time off; 打开时间的开关

常用SQL语句

sqlplus专用语句(不怎么用到,因为不怎么实际开发不怎么使用sqlplus)

-- 设置显示的列宽(字符型varchar2、日期型date),10个宽度位,a表示字符型,大小写均可
column ename format a10;

-- 设置显示的列宽(数值型number),9表示数字型,一个9表示一个数字位,四个9表示四个数字位 ,只能用9
column empno format 9999;

-- 设置一页显示80个条记录的高度
set pagesize 80;

使用/杠,执行最近一次的SQL语句
/

-- 清屏,属于SQL*PLUS工具中的命令
host cls;

-- 使用spool命令,保存SQL语句到硬盘文件e:/oracle-day01.sql,并创建sql文件
spool e:/oracle-day01.sql;

-- 使用spool  off命令,保存SQL语句到硬盘文件e:/oracle-day01.sql,并创建sql文件,结束语句
spool off;

-- 使用&占位符,动态输入值,&可以运用在任何一个DML语句中,在values子句中使用,例如:'&ename'和&sal
insert into emp values(&empno,'&ename','&job',&mgr,&hiredate,&sal,&comm,&xxxxxxxx);
-- 注意:&是sqlplus工具提供的占位符,如果是字符串或日期型要加''符,数值型无需加''

通用的常用语句

-- 创建新表new_emp,复制emp表中的结构和数据到new_emp表中
create table copy_emp  
as 
select * from emp;

-- 查询当前用户下所有的表,使用tab表,tab表每个用户都有
select * from tab;

-- 查询emp表的结构
desc emp;

-- 解决null的问题,使用NVL()函数,NVL(a,b):如果a是NULL,用b替代;如果a是非NULL,就不用b替代,直接返回a的值(这个尤其重要,通常在写查询语句时,要查询不是删除的行是都要加上这个。例如表示删除(DR)的值为0,则NVL(DR,0)=0,而不是DR=0)
select NVL(null,10) from emp;
注意:null与具体数字运算时,结果为null

-- 使用列别名
select empno AS "编号",ename as 姓名,sal "月    薪" 
from emp;
注意:不加双引号的别名不能有空格;加了双引号的别名可以有空格
要加只能加双引号,不能加单引号,因为在oracle中单引号表示字符串类型或者是日期类型
列名不能使用单引号,因为oracle认为单引号是字符串型或日期型

-- 使用dual哑表或者伪表,使用字符串连接符号||,输出"hello world",在oracle中from是必须写的(重要)
select 'hello' || ' world' "结果" from dual;

-- 使用sysdate,显示系统当前时间,在默认情况下,oracle只显示日期,而不显示时间,格式:26-4月-15
select sysdate from dual;

-- 左外连接[是oracle专用的,不是SQL99规则]:
select dept.deptno "部门号",dept.dname "部门名",count(emp.empno) "人数"
from dept,emp
where dept.deptno = emp.deptno(+) 
group by dept.deptno,dept.dname;

-- 右外连接:
select dept.deptno "部门号",dept.dname "部门名",count(emp.empno) "人数"
from dept,emp
where emp.deptno(+) = dept.deptno
group by dept.deptno,dept.dname;

-- 查询工资比20号部门【任意any】一个员工工资【低<】的员工信息(多行子查询,使用any关键字) 
-- 第一:查询20号部门的所有工资?
      select sal from emp where deptno = 20;
-- 第二:查询工资比(800,2975,3000,1100,3000)任意一个低的员工信息?
      select * from emp where sal < any (800,2975,3000,1100,3000);   

-- 使用并集运算,查询20号部门或30号部门的员工信息
select * from emp where deptno = 20
union
select * from emp where deptno = 30;

-- 使用交集运算[intersect],查询工资在1000-2000和1500-2500之间的员工信息(方式一)或使用where
select * from emp where sal between 1000 and 2000
intersect
select * from emp where sal between 1500 and 2500;

-- 使用差集运算[minus],查询工资在1000-2000,但不在1500-2500之间的员工信息(方式一)或使用where
select * from emp where sal between 1000 and 2000
minus
select * from emp where sal between 1500 and 2500;

-- 进入回收站
drop table users;

-- 查询回收站中的对象
show recyclebin;

-- 闪回,即将回收站还原
flashback table 表名 to before drop;
flashback table 表名 to before drop rename to  新表名;

-- 彻底删除users表
drop table users purge;

-- 清空回收站
purge recyclebin;

-- 为emp表增加image列,alter table 表名 add 列名 类型(宽度) 
alter table emp
add image blob;

-- 修改ename列的长度为20个字节,alter table 表名 modify 列名 类型(宽度) 
alter table emp
modify ename varchar2(20);

-- 删除image列,alter table 表名 drop column 列名
alter table emp
drop column image;

-- 重名列名ename为username,alter table 表名 rename column 原列名 to 新列名
alter table emp
rename column ename to username;

-- 将emp表重命名emps,rename 原表名 to 新表名
rename emp to emps;

Oracle函数

Oracle函数分为单行函数和多行(分组)函数

单行函数

单行函数:输入一个参数,输出一个结果,例如:upper(‘baidu.com’)->BAIDU.COM

-- 测试lower/upper/initcap函数,使用dual哑表
-- 将字符全部转为小写
select lower('www.BAIdu.COM') from dual; 
-- 将字符全部转为大写
select upper('www.BAIdu.COM') from dual;
-- 将字符全部转为与开始值相反形式,即大写变为小写,小写变为大写
select initcap('www.BAIdu.COM') from dual;

-- 测试concat/substr函数,从1开始,表示字符,不论中英文
select concat('hello','你好') from dual; -- 正确
select concat('hello','你好','世界') from dual; -- 错误
select 'hello' || '你好' || '世界' from dual; -- 正确
select concat('hello',concat('你好','世界')) from dual; -- 正确
select substr('hello你好',5,3) from dual;
5表示从第几个字符开始算,第一个字符为1,中英文统一处理
3表示连续取几个字符

-- 测试length/lengthb函数,编码方式为UTF8/GBK,一个中文占3/2个字节长度,一个英文一个字节
select length('hello你好') from dual; 
select lengthb('hello你好') from dual; 

--  测试instr/lpad/rpad函数,从左向右找第一次出现的位置,从1开始
select instr('helloworld','o') from dual; -- 注意:找不到返回0,大小写敏感 
-- 将字符串用#填满10个字节,从左边填充
select LPAD('hello',10,'#') from dual;
-- 将字符串用#填满10个字节,从右边填充
select RPAD('hello',10,'#') from dual;

-- 测试trim/replace函数
-- 去掉字符串左右两边的空格
select trim(' ' from '  he  ll                ') from dual;
select replace('hello','l','L') from dual;

-- round/trunc/mod函数(可以用于数值型或数值型)
select round(3.1415,3) from dual;
select trunc(3.1415,3) from dual;
select mod(10,3) from dual;
select round(sysdate,'month') from dual;

-- 测试round作用于日期型(year)
select round(sysdate,'year') from dual;

-- 当前日期:sysdate = 26-4月-15

-- 时间类函数以下一些months_between,add_months,next_day,last_day

-- 使用to_char(日期,'格"常量"式')函数将日期转成字符串,显示如下格式:2015 年 04 月 25 日 星期六
select to_char(sysdate,'yyyy" 年 "mm" 月 "dd" 日 "day') from dual;

-- 使用to_char(日期,'格式')函数将日期转成字符串,显示如格式:2015-04-25今天是星期六 15:15:15
select to_char(sysdate,'yyyy-mm-dd"今天是"day hh24:mi:ss') from dual;
-- 或
select to_char(sysdate,'yyyy-mm-dd"今天是"day HH12:MI:SS AM') from dual;

-- 使用to_date('字符串','格式')函数,查询1980年12月17日入职的员工(方式二:日期显式转换)
select * from emp where hiredate = to_date('1980年12月17日','yyyy"年"mm"月"dd"日"');
-- 或
select * from emp where hiredate = to_date('1980#12#17','yyyy"#"mm"#"dd');
-- 或
select * from emp where hiredate = to_date('1980-12-17','yyyy-mm-dd');

-- 使用to_number('字符串')函数将字符串‘123’转成数字123
select to_number('123') from dual;

-- 使用NVL(a,b)通用函数,统计员工年收入,NVL()作用于任何类型,即(number/varchar2/date)

-- 使用NVL2(a,b,c)通用函数,如果a不为NULL,取b值,否则取c值,统计员工年收入 

-- 使用NULLIF(a,b)通用函数,在类型一致的情况下,如果a与b相同,返回NULL,否则返回a,比较10和10.0是否相同

-- 使用oracle专用语法中的decode()函数,职位是分析员的,工资+1000;职位是经理的,工资+800;职位是其它的,工资+400
-- decode(字段,条件1,表达式1,条件2,表达式2,...表达式n)
-- 相当于
-- 使用SQL99标准通用语法中的case表达式
-- case 字段 
--      when 条件 then 表达式1
--      when 条件 then 表达式2
--      else 表达式n
-- end 
select ename "姓名",job "职位",sal "涨前工资",
       case job
        when 'ANALYST' then sal+1000
        when 'MANAGER' then sal+800
            else sal+400
       end "涨后工资"
from emp; 

select ename "姓名",job "职位",sal "涨前工资",
       decode(job,'ANALYST',sal+1000,'MANAGER',sal+800,sal+400) "涨后工资"
from emp;

多行函数

多行函数:输入多个参数,或者是内部扫描多次,输出一个结果,例如:count(*)->14

-- 统计emp表中员工总人数
select count(*) from emp;

-- 统计有佣金的员工人数
select count(comm) from emp;
注意:这里的多个行函数,不统计NULL值

-- 员工总工资,平均工资,四舍五入,保留小数点后0位
select sum(sal) "总工资",round(avg(sal),0) "平均工资"
from emp;

-- 查询员工表中最高工资,最低工资
select max(sal) "最高工资",min(sal) "最低工资"
from emp;

-- 入职最早,入职最晚员工
select max(hiredate) "最晚入职时间",min(hiredate) "最早入职时间"
from emp;

Oracle分页

首先说一下rownum,什么是rownum,有何特点?
1)rownum是oracle专用的关健字
2)rownum与表在一起,表亡它亡,表在它在
3)rownum在默认情况下,从表中是查不出来的
4)只有在select子句中,明确写出rownum才能显示出来
5)rownum是number类型,且唯一连续
6)rownum最小值是1,最大值与你的记录条数相同
7)rownum也能参与关系运算
* rownum = 1 有值
* rownum < 5 有值
* rownum <=5 有值
* rownum > 2 无值
* rownum >=2 无值
* rownum <>2 有值 与 rownum < 2 相同
* rownum = 2 无值
8)基于rownum的特性,我们通常rownum只用于<或<=关系运算

rownum方式的分页

-- 显示emp表中3-8条记录
select xx.*
from (select rownum ids,emp.* from emp where rownum<=8) xx 
where ids>=2;
-- 注意:在子查询中的别名,不可加""引号

用row_num() over(order by id)函数

SELECT * FROM ( 
SELECT t.*,row_number() over(ORDER BY n_count DESC) r 
FROM t_news t 
ORDER BY t.n_count DESC 
) t 
WHERE r BETWEEN 4 AND 6 

Oracle的数据类型

number(5) 表示最多存99999

number(6,2) 其中2表示最多显示2位小数,采用四舍五入,不足位数补0,其中6表示小数+整数不多于6位.其中整数位数不得多于4位,可以等于4位

varchar2(8) 8表示字节,一个中文字符在UTF-8中3个字节,在GBK中有2个字节,英文都是一个字节。

date 默认格式为:’27-4月-15’,可以使用to_char函数格式化
CLOB 【Character Large OBject】:大文本对象,即超过65565字节的数据对象,最多存储4G
BLOB 【Binary Large OBject】:大二进制对象,即图片,音频,视频,最多存储4G

三大数据类型的隐式数据类型转换

(1)varchar2变长/char定长–>number,例如:’123’->123
(2)varchar2/char–>date,例如:’25-4月-15’->’25-4月-15’
(3)number—->varchar2/char,例如:123->’123’
(4)date——>varchar2/char,例如:’25-4月-15’->’25-4月-15’

同义词

https://blog.csdn.net/qq_35448976/article/details/75213803

序列

https://blog.csdn.net/qq_35448976/article/details/75213796

索引

https://blog.csdn.net/kevin_love_it/article/details/60766438

PLSQL

是专用于Oracle服务器,在SQL基础之上,添加了一些过程化控制语句,叫PLSQL.

PLSQL程序的完整组成结构如下:
     [declare]
          变量声明;
      变量声明;
     begin
          DML/TCL操作;
      DML/TCL操作;
     [exception]
          例外处理;
      例外处理;
     end;
     /
注意:在PLSQL程序中,;号表示每条语句的结束,/表示整个PLSQL程序结束

--例子:
--使用基本类型变量,常量和注释,求10+100的和
declare
    --定义变量
    mysum number(3) := 0;
    tip varchar2(10) := '结果是';
begin
    /*业务算法*/   
    mysum := 10 + 100;
    /*输出到控制器*/
    dbms_output.put_line(tip || mysum);
end;
/

可以参考:
https://www.2cto.com/database/201803/726650.html

存储过程,触发器

https://blog.csdn.net/zxiang248/article/details/52128026

oracle事务

回顾MySQL的事务开始:start transaction
Oracle的事务只针对DML操作,即select/insert/update/delet
Oracle的事务开始:第一条DML操作做为事务开始

Oracle的提交事务
(1)显示提交:commit
(2)隐藏提交:DDL/DCL/exit(sqlplus工具)
注意:提交是的从事务开始到事务提交中间的内容,提交到ORCL数据库中的DBF二进制文件

Oracle的回滚事务
(1)显示回滚:rollback
(2)隐藏回滚:关闭窗口(sqlplus工具),死机,掉电
注意:回滚到事务开始的地方

-- 使用savepoint 回滚点,设置回滚点a   
savepoint a;

-- 使用rollback to savepoint,回滚到回滚点a处
rollback to savepoint a;

mysql支持的四种事务隔离级别及能够解决的问题
(1)read uncommitted – 不能解决任何缺点
(2)read committed – 脏读,Oracle默认
(3)reapatable read – 不可重复读,脏读,MySQL默认
(4)serializable – 幻读,不可重复读,脏读,效率低

Oracle支持的二种事务隔离级别及能够解决的问题
Oracle支持:read committed 和 serializable

SQL92/[99]标准的四大SQL分类

(A)DML(数据操控语言):select,insert,update,delete
(B)DDL(数据定义语言):create table,alter table,drop table,truncate table
(C)DCL(数据控制语言):grant 权限 to scott, revoke 权限 from scott …
(D)TCL(事务控制语言):commit,rollback,rollback to savepoint …

SQL语句与SQPLUS命令的特定

SQL语句的特点
1)是SQL92/99的ANSI官方标准,只要按照该标准来写,在任何的关系型数据库中都可以直接执行
2)SQL语句的关健字不能简写,例如:select,where,from
3)大小写不敏感,提倡大写
4)能够对表数据进行增删改查操作
5)必须以分号结束
6)通常称做语句

SQLPLUS命令的特点
1)是oracle自带的一款工具,在该工具中执行的命令叫SQLPLUS命令
2)SQLPLUS工具的命令中的关健字可以简写,也可以不简写,例如:col ename for a10;
3)大小写不敏感,提倡大写
4)不能够对表数据进行增删改查操作,只能完成显示格式控制,例如:设置显示列宽,清屏,记录执行结果
5)可以不用分号结束,也可以用分号结束,个人提倡不管SQL或SQLPLUS,都以分号结束
6)通常称做命令,是SQLPLUS工具中的命令
注意:SQLPLUS命令是SQLPLUS工具中特有的语句

oracle 权限管理常用命令或语句

声明:scott或hr叫用户名/方案名/空间名
scott–tiger
hr—–lion

-- 查询当前用户是谁
show user;

-- 查询scott自己表空间下的所有对象时,可加,或不加用户名
select * from emp;select * from scott.emp;

-- 以sysdba身份解锁hr普通帐户
alter user hr account unlock;

-- 以sysdba身份设置hr普通帐户的密码
alter user hr identified by lion;

-- 当scott查询hr表空间下的所有表时,必须得加用户名
select * from hr.jobs;

-- 在默认情况下,每个用户只能查询自已空间下的对象的权限,不能查询其它用户空间下的对象

-- 以sysdba身份角色,授予scott用户查询所有用户空间下的对象权限
grant select any table to scott;

-- 以sysdba身份,撤销scott用户查询所有用户空间下的对象权限
revoke select any table from scott;

-- scott自已查看自己所拥有的权限
select * from user_sys_privs;

-- 从scott用户空间导航到sysdba用户空间
conn / as sysdba;

-- 从sysdba用户空间导航到scott用户空间
conn scott/tiger;

-- 从scott用户空间导航到hr用户空间
conn hr/lion;

-- 查询hr用户空间中的所有对象
select * from tab;

-- 从hr用户空间导航到scott用户空间
conn scott/tiger;

-- 在scott用户空间下,查询hr用户空间下的jobs表,必须加上hr用户空间名
select * from hr.jobs;

--   查询Oracle中有哪些用户
 select * from all_users;

用户权限控制更多内容:https://blog.csdn.net/poxiao58/article/details/52328849

oracle的一些注意事项

  1. oracle的每条查询语句必须要有表。
  2. oracle中dual是必定存在的表,为哑表,用来显示一条记录。
  3. 单引号出现的地方如下:(1)字符串型,例如:’hello’ || ’ world’。(2)日期型,例如’25-4月-15’。(3)to_char/to_date(日期,’YYYY-MM-DD HH24:MI:SS’)
  4. 双引号出现的地方如下:(1)列别名,例如:sal*12 “年 薪”,或 sal*12 年薪,个人提倡用”“双引号作列别名。(2)to_char/to_date(日期,’YYYY”年”MM”月”DD”日” HH24:MI:SS’)
  5. 字符串使用”,内容大小写敏感
  6. null不能使用=运算,null不能参加number/date/varchar2类型运算。判断是否为null,用 is null 或者 is not null;
  7. 字符类函数,如:substr函数,索引是从1开始,不论中英文
  8. (1)日期-日期=天数。(2)日期+-天数=日期
  9. select ‘123’ + 123 from dual;246
  10. select ‘123’ || 123 from dual;123123
  11. count/sum/avg/max/min多行函数不统计null值
  12. union:二个集合中,如果都有相同的,取其一。union all:二个集合中,如果都有相同的,都取
  13. 当多个集合操作时,结果的列名由第一个集合列别名决定
  14. 当多表查询,子查询,集合查询都能完成同样任务时,按如下优化方案选择:多表查询->子查询->集合查询
  15. 注意:在子查询中的别名,不可加”“引号
  16. 修改表不可回滚

面试题

  1. 笔试题:有【1000亿】条会员记录,如何用最高效的方式将薪水字段清零,其它字段内容不变?

第一:从emp表中删除sal字段
alter table emp
drop column sal;

第二:向emp表中添加sal字段,且内容默认0
alter table emp
add sal number(6) default 0;

2.Oracle之所以能回滚的原因是?
主要机制是实例池

3.什么情况下会用到视图
(1)如果你不想让用户看到所有数据(字段,记录),只想让用户看到某些的数据时,此时可以使用视图
(2)当你需要减化SQL查询语句的编写时,可以使用视图,但不提高查询效率

Oracle优化20条建议

(01)选择最有效率的表名顺序(笔试常考)
  ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,
  FROM子句中写在最后的表将被最先处理,
  在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表放在最后,
  如果有3个以上的表连接查询,那就需要选择那个被其他表所引用的表放在最后。

-- 例如:查询员工的编号,姓名,工资,工资等级,部门名
select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname
from salgrade,dept,emp
where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)        

  1)如果三个表是完全无关系的话,将记录和列名最少的表,写在最后,然后依次类推
  2)如果三个表是有关系的话,将引用最多的表,放在最后,然后依次类推

(02)WHERE子句中的连接顺序(笔试常考)
  ORACLE采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之左,
  那些可以过滤掉最大数量记录的条件必须写在WHERE子句的之右。

-- 例如:查询员工的编号,姓名,工资,部门名  
select emp.empno,emp.ename,emp.sal,dept.dname
from emp,dept
where (emp.deptno = dept.deptno) and (emp.sal > 1500)   

(03)SELECT子句中避免使用*号
   ORACLE在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间

select empno,ename from emp;

(04)使用DECODE函数来减少处理时间
  使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表

(05)整合简单,无关联的数据库访问

(06)用TRUNCATE替代DELETE

(07)尽量多使用COMMIT
  因为COMMIT会释放回滚点

(08)用WHERE子句替换HAVING子句
WHERE先执行,HAVING后执行

(09)多使用内部函数提高SQL效率

(10)使用表的别名
salgrade s

(11)使用列的别名
ename e

(12)用索引提高效率
  在查询中,善用索引

(13)字符串型,能用=号,不用like
  因为=号表示精确比较,like表示模糊比较

(14)SQL语句用大写的
  因为Oracle服务器总是先将小写字母转成大写后,才执行
  在eclipse中,先写小写字母,再通过ctrl+shift+X转大写;ctrl+shift+Y转小写

(15)避免在索引列上使用NOT
  因为Oracle服务器遇到NOT后,他就会停止目前的工作,转而执行全表扫描

(16)避免在索引列上使用计算
  WHERE子句中,如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描,这样会变得变慢

--例如,SAL列上有索引,
--低效:
SELECT EMPNO,ENAME
FROM EMP 
WHERE SAL*12 > 24000;
--高效:
SELECT EMPNO,ENAME
FROM EMP
WHERE SAL > 24000/12;

(17)用 >= 替代 >

--低效:
SELECT * FROM EMP WHERE DEPTNO > 3   
--首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录
--高效:
SELECT * FROM EMP WHERE DEPTNO >= 4  
--直接跳到第一个DEPT等于4的记录

(18)用IN替代OR

select * from emp where sal = 1500 or sal = 3000 or sal = 800;
select * from emp where sal in (1500,3000,800);

(19)总是使用索引的第一个列
  如果索引是建立在多个列上,只有在它的第一个列被WHERE子句引用时,优化器才会选择使用该索引
  当只引用索引的第二个列时,不引用索引的第一个列时,优化器使用了全表扫描而忽略了索引

create index emp_sal_job_idex
on emp(sal,job);
----------------------------------
select *
from emp  
where job != 'SALES';    

(20)避免改变索引列的类型,显示比隐式更安全
  当字符和数值比较时,ORACLE会优先转换数值类型到字符类型
select 123 || '123' from dual;

猜你喜欢

转载自blog.csdn.net/weixin_37610397/article/details/82085755