【Oracle学习笔记】基础

文章放置于:https://github.com/zgkaii/CS-Notes-Kz,欢迎批评指正!

一、简介

Oracle数据库系统是美国Oracle公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。

二、体系结构

1.数据库

Oracle数据库是数据的物理存储。这就包括(数据文件ORA或者DBF、控制文件、联机日志、参数文件)。其实Oracle数据库的概念和其它数据库不一样,这里的数据库是一个操作系统只有一个库。可以看作是Oracle就只有一个大数据库。

2.实例

一个Oracle实例(Oracle Instance)有一系列的后台进程(Backguound Processes)和内存结构(Memory Structures)组成。一个数据库可以有n个实例。

3.用户

用户是在实例下建立的。不同实例可以建相同名字的用户。

4.表空间

表空间是Oracle对物理数据库上相关数据文件(ORA或者DBF文件)的逻辑映射。一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关联的一组结构。每个数据库至少有一个表空间(称之为system表空间)。
每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件(datafile)。一个数据文件只能属于一个表空间。

5.数据文件(dbf、ora)

数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的,真正是在某一个或者多个数据文件中。而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间。一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行。
注:表的数据,是有用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中。

由于oracle的数据库不是普通的概念,oracle是有用户和表空间对数据进行管理和存放的。但是表不是有表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同一个名字的表!这里区分就是用户了。

下面我们创建一个表空间learn:

CREATE TABLESPACE learn   --表空间名称
DATAFILE 'd:\learn.dbf'   --指定表空间对应的数据文件
SIZE 100m                 --表空间的初始大小
AUTOEXTEND ON             --表空间存储都占满时,自动增长
NEXT 10m;                 --自动增长的大小

三、用户

oracle的表和其它的数据库对象都是存储在用户下的。

1.创建用户:
CREATE USER root
IDENTIFIED BY root         --用户的密码
DEFAULT TABLESPACE learn;  --表空间名称
2.赋予权限

初始化Oracle数据库只有system用户具有DBA权限,所有需要通过system用户给root用户赋予DBA权限,否则无法正常登陆root用户。

GRANT DBA TO root;

切换到root用户下:

注意
Oracle主要存在三个重要的角色:CONNECT角色,RESOURCE角色,DBA角色。

CONNECTRESOURCEDBA
授予最终用户的典型权利授予开发人员系统最高权限
ALTER SESSION --修改会话
CREATE CLUSTER --建立聚簇
CREATE DATABASE LINK --建立数据库链接
CREATE SEQUENCE --建立序列
CREATE SESSION --建立会话
CREATE SYNONYM --建立同义词
CREATE VIEW --建立视图
CREATE CLUSTER --建立聚簇
CREATE PROCEDURE --建立过程
CREATE SEQUENCE --建立序列
CREATE TABLE --建表
CREATE TRIGGER --建立触发器
CREATE TYPE --建立类型
任何操作

四、表的管理

1.Oracle数据类型
数据类型描述
Varchar,varchar2表示一个字符串
NUMBERNUMBER(n)表示一个整数,长度是n
NUMBER(m,n):表示一个小数,总长度是m,小数是n,整数是m-n
DATA表示日期类型
CLOB大对象,表示大文本数据类型,可存4G
BLOB大对象,表示二进制数据,可存4G
2.创建表
CREATE TABLE person(
       pid NUMBER(20),
       pname VARCHAR2(10),
       gender NUMBER(1) DEFAULT 1,
       brithday DATE
);
3.删除表
DELETE FROM person;
DROP TABLE person;
TRUNCATE TABLE person;
4.修改表
  • 添加一列
ALTER TABLE person ADD (gender NUMBER(1));
  • 修改列类型
ALTER TABLE person MODIFY father CHAR(10);
  • 修改列名称
ALTER TABLE person RENAME COLUMN gender TO sex;
  • 删除一列
ALTER TABLE person DROP COLUMN father;
5.数据库表数据的更新
  • 查询数据
SELECT * FROM person;
  • 插入数据
INSERT INTO person(pid, pname, gender, brithday)VALUES(1, '张三', 1, to_date('2000-01-01', 'yyyy-MM-dd'));
COMMIT;

  • 修改数据
UPDATE person SET pname = '李四' WHERE pid =1;
COMMIT;
6.序列

在很多数据库中都存在一个自动增长的列,如果现在要想在oracle 中完成自动增长的功能, 则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。

序列不属于任何一张表,但是可以逻辑和表绑定。
下面,创建一个s_person的序列,验证自动增长的操作:

CREATE SEQUENCE s_person;

序列创建完成之后,所有的自动增长应该由用户自己处理,所以在序列中提供了以下的两种操作:

SELECT s_person.nextval FROM dual; --取得序列的下一个内容 
SELECT s_person.currval FROM dual; --取得序列的当前内容 

其中,dual是虚表,补全语法,没有任何意义

在插入数据时需要自增的主键中可以这样使用:

INSERT INTO person (pid,pname) VALUES (s_person.nextval,'小明');
COMMIT;

五、单行函数

初始化Oracle数据库中有一个Scott用户,密码默认为tiger,我们就用它来学习。
解锁并切换到Scott用户:

ALTER USER scott ACCOUNT UNLOCK;

ALTER USER scott IDENTIFIED BY tiger;
1.字符函数

接收字符输入返回字符或者数值,dual是伪表。

SELECT UPPER('yes') FROM dual;  --字符转换为大写
SELECT LOWER('NO') FROM dual;   --字符转换为小写

其他更多操作可查看API。

2.数值函数
  • 四舍五入函数:ROUND()
SELECT ROUND(28.12,0) FROM dual; --28
SELECT ROUND(28.12,-1) FROM dual; --28.1
SELECT TRUNC(28.12,3) FROM dual; --28.12
  • 取余
SELECT MOD(10,3) FROM dual; --1

其他更多操作可查看API。

3.日期函数

Oracle中提供了很多和日期相关的函数,包括日期的加减,在日期加减时有一些规律:

  • 日期–数字= 日期
  • 日期+数字= 日期
  • 日期–日期= 数字

范例:
(1)查询雇员的进入公司的周数。

SELECT ROUND((SYSDATE-e.hiredate)/7) FROM emp e;

(2)获得两个时间段中的月数:months_between()

SELECT months_between(SYSDATE,e.hiredate) FROM emp e;

(3)获得两个时间段中的年数:

SELECT months_between(SYSDATE,e.hiredate)/12 FROM emp e;
4.转换函数
  • TO_CHAR:字符串转换函数

  • TO_DATE:日期转换函数

5.通用函数

(1)空值处理nvl
null和任何数值计算都是null。

使用nvl来处理:

(2)Decode函数
该函数类似if…else if…else
语法:DECODE(col/expression, [search1,result1],[search2, result2]....[default])

(3)case when

六、多行函数

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

1.统计记录数count()
SELECT COUNT(1) FROM emp;  
SELECT COUNT(*) FROM emp;
SELECT COUNT(ename) FROM emp;
2.最小值查询min()
SELECT MIN(sal) FROM emp;
3.最大值查询max()
SELECT MAX(sal) FROM emp;
4.查询平均值avg()
SELECT AVG(sal) FROM emp;
5.求和函数sum()
SELECT SUM(sal) FROM emp t WHERE t.deptno = 20;

七、分组统计

分组统计需要使用GROUP BY来分组。
例如,查询出每个部门的平均工资:

SELECT e.deptno,AVG(e.sal) FROM emp e GROUP BY e.deptno;

查询出来部门编号,和部门下的人数:

可见:

  • 如果使用分组函数,SQL只可以把GOURP BY分组条件字段和分组函数查询出来,不能有其他字段。
  • 如果使用分组函数,不使用GROUP BY 只可以查询出来分组函数的值。

可以这样修改:

又例如,查询出部门人数大于5人的部门:

八、多表查询

1.基础查询

使用一张以上的表做查询就是多表查询。例如:

SELECT * FROM emp e,dept d WHERE e.deptno=d.deptno;

例子1:查询出雇员的编号,姓名,部门的编号和名称,地址

例子2:查询出每个员工的上级领导(自连接)

2.外连接(左右连接)

当我们在做基本连接查询的时候,查询出所有的部门下的员工,我们发现编号为40的部门下没有员工,但是要求把该部门也展示出来,我们发现上面的基本查询是办不到的。


使用(+)表示左连接或者右连接,当(+)在左边表的关联条件字段上时是左连接,如果是在右边表的关联条件字段上就是右连接。

九、子查询

在一个查询的内部还包括另一个查询,则此查询称为子查询。
Sql的任何位置都可以加入子查询。

子查询在操作中有三类:

  • 单列子查询——返回的结果是一列的一个内容
  • 单行子查询_返回多个列,有可能是一个完整的记录
  • 多行子查询:返回多条记录

范例:查询出比雇员7654的工资高,同时从事和7788的工作一样的员工

范例:要求查询每个部门的最低工资和最低工资的雇员和部门名称

十、ROWNUM与分页查询

ROWNUM:表示行号,实际上是一个列,但是这个列是一个伪列,此列可以在每张表中出现。
范例:查询emp表带有rownum列

注意
ROWNUM不支持大于号,只支持小于号。

如果想实现我们的需求怎么办呢?答案是使用子查询,也正是oracle分页的做法。

另一种写法:

十一、视图

视图就是封装了一条复杂查询的语句。
语法1:CREATE VIEW 视图名称AS 子查询
范例:建立一个视图,此视图包括了20部门的全部员工信息

CREATE VIEW empvd20 AS SELECT * FROM emp t WHERE t.deptno = 20;

视图创建完毕就可以使用视图来查询,查询出来的都是20部门的员工

语法2:CREATE OR REPLACE VIEW 视图名称AS 子查询

CREATE OR REPLACE VIEW empvd20 AS SELECT * FROM emp t WHERE t.deptno = 20;

语法3:CREATE OR REPLACE VIEW 视图名称AS 子查询WITH READ ONLY

视图作用:

  • 屏蔽掉一些敏感字段。
  • 保证总部和分部数据及时统一。

十二、索引

索引是用于加速数据存取的数据对象。合理的使用索引可以大大降低I/O 次数,从而提高数据访问性能。

1.单列索引

单列索引是基于单个列所建立的索引,比如:

CREATE index 索引名on 表名(列名)
2. 复合索引

复合索引是基于两个列或多个列的索引。在同一张表上可以有多个索引,但是要求列的组合必须不同,比如:
Create index emp_idx1 on emp(ename,job);
Create index emp_idx1 on emp(job,ename);
范例:给person表的name建立索引

CREATE INDEX pname_index ON person(pname);

范例:给person表创建一个name和gender的索引

CREATE INDEX pname_gender_index ON person(pname, sex);
3.查看索引
select * from user_ind_columns where table_name = upper('表名');

十三、PL/SQL基本语法

1.什么是PL/SQL

PL/SQL(Procedure Language/SQL)是Oracle对sql语言的过程化扩展,指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。
把SQL语言的数据操纵能力与过程语言的数据处理能力结合起来,使得PLSQL面向过程但比过程语言简单、高效、灵活和实用。

例如:为职工涨工资,每人涨10%的工资

update emp set sal=sal*1.1
2.程序语法
DECLARE
       --说明部分(变量说明,游标申明,例外说明〕
BEGIN
       --语句序列(DML语句〕... 
EXCEPTION
       --例外处理语句
END;
3.常量和变量定义
  • 变量的基本类型
    变量的基本类型是oracle中的建表时字段的变量如char, varchar2, date, number, boolean, long。

定义语法:

varl char(15);
Psal number(9,2);

说明变量名、数据类型和长度后用分号结束说明语句。

married CONSTANT BOOLEAN:=TRUE
  • 引用变量:
myname emp.ename%TYPE;

引用型变量,即my_name的类型与emp表中ename列的类型一样在sql中使用into来赋值。

DECLARE
	emprec emp.ename%TYPE;
begin
	SELECT  t.ename INTO emprec FROM emp t WHERE t.empno = 7369;
	dbms_output.put_line(emprec);
END;

输出:

SMITH
  • 记录型变量
Emprec emp%ROWTYPE;

实例:

DECLARE
	p emp%ROWTYPE;
BEGIN
	SELECT * INTO p FROM emp t WHERE t.empno = 7369;
	dbms_output.put_line(p.ename || ' ' || p.sal);
END;

输出:

SMITH  800

十四、分支

if分支
  • 语法一
IF 条件 THEN 
	语句 1;
	语句 2;
END IF;
  • 语法二
IF 条件 THEN 
	语句序列 1;
ELSE 
	语句序列 2;
END IF;
  • 语法三
IF 条件 THEN 
	语句;
ELSIF 语句 THEN 
	语句;
ELSE 
	语句;
END IF;

范例:断人的不同年龄段18岁以下是未成年人,18岁以上40以下是成年人,40以上是老年人

DECLARE 
  mynum NUMBER:= #
BEGIN
  IF mynum<18 THEN
    dbms_output.put_line('未成年');
  ELSIF mynum >= 18 AND mynum < 40 THEN
    dbms_output.put_line('中年');
 ELSIF mynum >= 40 THEN
    dbms_output.put_line('老年人');
  END IF;
END;
2.LOOP循环语句
  • 语法一
WHILE total <= 25000 LOOP
	.. .
	total : = total + salary;
END LOOP;
  • 语法二
Loop
	EXIT [when 条件];
	……
End loop
  • 语法三
FOR I IN 1 . . 3 LOOP
	语句序列 ;
END LOOP ;

范例:用三种方式分别输出1-10

---while 
DECLARE
  i NUMBER(2) :=1;
BEGIN
  WHILE i<11 LOOP
    dbms_output.put_line(i);
    i := i+1;
  END LOOP;
END;
--exit循环
DECLARE
  i NUMBER(2) :=1;
BEGIN
  LOOP
    EXIT WHEN i>10;
    dbms_output.put_line(i);
    i := i+1;
   END LOOP;
END;
--for循环
DECLARE
  i NUMBER(2) :=1;
BEGIN
  FOR i IN 1..10 LOOP
    dbms_output.put_line(i);
  END LOOP;
END;
3.游标Cursor

游标类似于Java中的集合。游标可以存储查询返回的多条数据。语法:

CURSOR 游标名 [ (参数名 数据类型,参数名 数据类型,...)] IS SELECT 语句;

例如:

CURSOR c1 IS SELECT ename FROM emp;

游标的使用步骤:

  • 打开游标: open c1; (打开游标执行查询)
  • 取一行游标的值: fetch c1 into pjob; (取一行到变量中)
  • 关闭游标: close c1;(关闭游标释放资源)
  • 游标的结束方式 exit when c1%notfound

注意: 上面的 pjob 必须与 emp 表中的 job 列类型一致:
定义: pjob emp.empjob%type;

实例:

--输出emp表中所有员工的姓名
DECLARE 
  CURSOR c1 IS SELECT * FROM emp;
  emprow emp%ROWTYPE;
BEGIN
  OPEN c1;
      LOOP
        FETCH c1 INTO emprow;
        EXIT WHEN c1%NOTFOUND;
        dbms_output.put_line(emprow.ename);
      END LOOP;
  CLOSE c1;
END;


--给指定部门员工涨工资
DECLARE 
  CURSOR c2(eno emp.deptno%TYPE) IS SELECT empno FROM emp WHERE deptno =  eno;
  en emp.empno%TYPE;
BEGIN
  OPEN c2(10);
       LOOP
         FETCH c2 INTO en;
         EXIT WHEN c2%NOTFOUND;
         UPDATE emp SET sal = sal + 100 WHERE empno=en;
         COMMIT; 
       END LOOP;
  CLOSE c2;
END;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值