一 简介
1.为何需要数据库?存储大量数据,方便检索和访问。
2.文件组成:
数据文件:扩展名是.DBF,用于存储数据库数据的文件,数据库表和数据文件不存在一对一对应关系
控制文件:扩展名是.CTL,是数据库启动及运行所必需的文件,默认包含3个控制文件,各个控制文件内容相同
日志文件:扩展名是.LOG,它记录了对数据的所有更改信息,多个日志文件组之间循环使用
表空间:每个Oracle数据库都是由若干个表空间构成,用户在数据库中建立的所有内容都被存储到表空间中,创建数据库时会自动创建若干表空间
二 安装
1、windows、linux、docker随便,安装完成后,以windows为例:在计算机-管理-服务中,找到oracle服务只手动开TNSL listener和service orcl就行了,别的可以都禁用,这样电脑就不那么卡。另外,system ,sys是默认的超级用户。
2、连接数据库的工具,plsql developer开发功能强,DbVisualizer可连接数据库的种类多。不想用工具,可以直接使用oracle自带的sqlplus
三 基本操作
1、登录:1.使用plsql的超级用户SYSTEM 用户登录;2.创建表空间;3.创建用户并分配表空间;4.给用户分配相应的数据库权限
权限:指执行特定类型SQL 命令或访问其他对象的权利,分为系统权限和对象权限。系统权限允许用户执行某些数据库操作,对象权限允许用户对某一特定对象执行特定的操作。
角色是具有名称的一组权限的组合,常用系统预定义角色,CONNECT:临时用户;RESOURCE:更为可靠和正式的用户;DBA:数据库管理员角色,拥有管理数据库的最高权限。
#分配权限或角色GRANT privileges or role TO user; #撤销权限或角色REVOKE privileges or role FROM user;
2、创建表:数据存放在表中,数据完整性的问题大多是由于设计引起的。创建表的时候,就应当保证以后数据输入是正确的,错误的数据、不符合要求的数据不允许输入。
数据类型: 字符数据类型 CHAR:存储固定长度的字符串 VARCHAR2 :存储可变长度的字符串 NCHAR和NVARCHAR2 :存储Unicode字符集类型 数值数据类型 NUMBER:存储整数和浮点数,格式为NUMBER(p, s) column_name NUMBER { p = 38, s = 0} column_name NUMBER (p) {整数} column_name NUMBER (p, s) {浮点数} 日期时间数据类型 DATE:存储日期和时间数据 TIMESTAMP:比DATE更精确 LOB数据类型 BLOB:存储二进制对象,如图像、音频和视频文件 CLOB:存储字符格式的大型对象
3、创建序列:使用序列
获取下一个序列值 select MASTER_SEQ.NEXTVAL from dual 获取当前序列值 select MASTER_SEQ.Currval from dual; 插入数据时候使用 insert into GRADE values (MASTER_SEQ.NEXTVAL,'二年级');
四 SQL基础语法
1、简介:SQL——Structured Query Language:结构化查询语言。为何要使用SQL?——对数据进行增删改查。
2、组成
DML(数据操作语言):查询、插入、删除和修改数据库中的数据——SELECT、INSERT、 UPDATE 、DELETE等
DCL(数据控制语言):用来控制存取许可、存取权限等——GRANT、REVOKE 等
DDL(数据定义语言):用来建立数据库、数据库对象和定义其列——CREATE TABLE 、DROP TABLE 等
TCL(事务控制语言):COMMIT、 SAVEPOINT、ROLLBACK
2.1.DDL(数据定义语言):数据定义语言用于改变数据库结构,包括创建、更改和删除数据库对象。用于操纵表结构的数据定义语言命令有:CREATE TABLE、ALTER TABLE、DROP TABLE。
2.2.DML(数据操作语言):数据操纵语言用于检索、插入和修改数据,数据操纵语言是最常见的SQL命令,数据操纵语言命令包括:SELECT、INSERT、UPDATE、DELETE。
2.3.TCL(事务控制语言):事务是最小的工作单元,作为一个整体进行工作,保证事务的整体成功或失败,称为事务控制,用于事务控制的语句有:
COMMIT - 提交并结束事务处理
ROLLBACK - 撤销事务中已完成的工作
SAVEPOINT – 标记事务中可以回滚的点
2.4.DCL(数据控制语言):数据控制语言为用户提供权限控制命令,用于权限控制的命令有:GRANT 授予权限、REVOKE 撤销已授予的权限
3、DML详细语法
3.1 DML-SELECT命令
SELECT column_names FROM <table_name>; SQL> SELECT * FROM itemfile; SQL>SELECT itemcode, itemdesc, qty_hand FROM itemfile; SQL> CREATE TABLE newitemfile2 AS SELECT * FROM itemfile WHERE 1 = 2;
3.2 DML–INSERT命令
INSERT [INTO] <表名> [列名] VALUES <值列表> INSERT INTO Student (StudentName,Address,GradeId,Email,SEX) VALUES (1,‘张三’,‘地球’,6,‘MYY@hope-pact.com’,’男’)
#插入多行数据 INSERT INTO <表名>(列名) SELECT <列名> FROM <源表名> (1)INSERT INTO TongXunLu (姓名,地址,电子邮件) SELECT SName,SAddress,SEmail FROM Students (2)INSERT INTO <表名>(列名) SELECT <列名> from dual UNION SELECT <列名> from dual UNION …… (3)批量插入 INSERT into grade (gradeid, gradename) SELECT 8, ' 二年级 ' from dual UNION SELECT 9, '三年级' from dual;
3.3 DML–update命令
UPDATE <表名> SET <列名 = 更新值> [WHERE <更新条件>] (1)UPDATE Student SET SEX = 0 (2)UPDATE Student SET Address =’郑州大学' WHERE Address = ‘河南大学’ (3)UPDATE Result SET StudentResult = StudentResult + 5 WHERE StudentResult <= 95
3.4.DML-DELETE
DELETE FROM <表名> [WHERE <删除条件>] delete后面不能有*,直接from DELETE FROM Students WHERE SName =‘张三'; DELETE FROM 学员信息表 WHERE 学号 ='0010012'
4、DDL详细语法
4.1.CREATE TABLE 创建
CREATE TABLE 语句用于创建数据库中的表。 SQL CREATE TABLE 语法 CREATE TABLE 表名称 ( 列名称1 数据类型, 列名称2 数据类型, 列名称3 数据类型, .... ) 例如:使用sql创建学生表 create table STUDENT ( studentid NUMBER(8) not null, loginpwd VARCHAR2(50) not null, studentname VARCHAR2(50) not null, sex CHAR(2), gradeid NUMBER(6), phone VARCHAR2(50), address VARCHAR2(255), borndate DATE, email VARCHAR2(50), identitycard VARCHAR2(18) )
4.2 删除表
drop table table_name;
4.3 修改表
(1)如需在表中添加列,请使用下列语法: ALTER TABLE table_name ADD column_name datatype; (2)要删除表中的列,请使用下列语法: ALTER TABLE table_name DROP COLUMN column_name; 注释:某些数据库系统不允许这种在数据库表中删除列的方式 (DROP COLUMN column_name)。 (3)要改变表中列的数据类型,请使用下列语法: ALTER TABLE table_name ALTER COLUMN column_name datatype;
5、运算符
5.1 算数运算符
算术运算符用于执行数值计算。可以在SQL语句中使用算术表达式,算术表达式由数值数据类型的列名、数值常量和连接它们的算术操作符组成。算术操作符包括加(+)、减(-)、乘(*)、除(/)
SQL> SELECT SID, JAVASCORE +DBSCORE FROM SCORE WHERE STUID='10011';
5.2 比较运算符
比较运算符用于比较两个表达式的值。比较操作符包括 =、!=、<、>、<=、>=、BETWEEN…AND、IN、LIKE 和 IS NULL等
SQL> SELECT stuname,stuaddress FROM Student WHERE stuage >20; SQL> SELECT stuname,address FROM Student WHERE stuaddress IN ('洛阳,郑州,上海'); SQL> SELECT stuname,stuaddress FROM Student WHERE stuname LIKE '张%'; 注意:1)sex=’男’ or sex=’女’ 等同于 sex in(‘男’,’女’); 2)oracle里没有双引号,只用单引号 3)between包含边界。如between 80 and 90; 是指90>=x>=80;
5.3 逻辑运算符
逻辑运算符用于组合多个计较运算的结果以生成一个或真或假的结果。逻辑操作符包括与(AND)、或(OR)和非(NOT)。
SQL> SELECT * FROM Student WHERE borndate> =‘10-5月-91' AND borndate <= ‘26-5月-91’; -- 显示 1991-5月-10 至 1991-5月-26出生的学生
5.4 连接运算符
SQL> SELECT ('地址是'||address) address FROM Student WHERE studentid='10011';
通过使用连接操作符可以将表中的多个列合并成逻辑上的一行列
5.5 通配符
_ 一个字符 LIKE ’李_’ % 任意长度的字符串 LIKE ’李%’ [ ] 括号中所指定范围内的一个字符 regexp_like(C,'9W0[1-2]')
五、基础查询
1、语法
1.1 基础语法
SELECT <列名> FROM <表名> [WHERE <查询条件表达式>] [ORDER BY <排序的列名>[ASC或DESC]] SELECT StudentId,StudentName,Address --列名称 FROM Students --表名 WHERE SEX = ‘男’ --过滤条件 ORDER BY StudentId --排序条件 注意: [] 可选项 <> 必选项 ASC升序 DESC降序 * 别滥用,按需查询,提高性能 例如: --查询全部的行和列 SELECT * FROM Student --查询部分行 SELECT StudentId,StudentName,Address FROM Student WHERE Address = '河南洛阳' SELECT StudentId,StudentName,Address FROM Student WHERE Address <> '河南洛阳'(这个是oracle里的不等号)
1.2 别名
SELECT StudentId AS 学员编号,StudentName AS学员姓名,Address AS 学员地址 FROM Student WHERE Address <> '河南洛阳'
1.3 数据查询-空行常量列
--查询空行 SELECT StudentName FROM Student WHERE Email IS NULL --使用常量列 SELECT StudentName as 姓名,Address as 地址,'惠普洛阳基地' AS 学校名称 FROM Student
1.4 限制固定行数
SELECT StudentName, Address FROM Student WHERE rownum<=5 SSex = 0;
2、排序
2.1 升序排列
SELECT StudentID AS 学员编号,(StudentResult*0.9+5) AS 综合成绩 FROM Result WHERE (StudentResult*0.9+5)>60 ORDER BY StudentResult
2.2 降序排列
SELECT Au_Lname ||'.' ||Au_fName AS EMP FROM Authors Union SELECT fName ||’.’|| LName AS EMP FROM Employee ORDER BY EMP DESC
2.3 按多列排序
SELECT StudentID AS 学员编号, StudentResult AS 成绩 FROM Result WHERE StudentResult >60 ORDER BY StudentResult,SubjectID --注意:第一排序条件如果没有相同的值,第二排序条件不会启用。
3、单行函数
单行函数对于从表中查询的每一行只返回一个值。可以出现在SELECT子句中和WHERE子句中。单行函数可以大致分为:日期函数、字符函数、转换函数。
3.1 日期函数
ADD_MONTHS select add_months(sysdate,2) from dual; --当前月份加上2月
3.2 字符函数
Replace(char, searchstring,[rep string]) Select replace( ‘jack and jue’ , ’ j ’ , ‘ bl ‘ ) from dual; --输出:black and blue Substr (char, m, n) Select substr(‘abcdefg’,3,2) from dual; --输出:cd
3.3 转换函数
转换函数将值从一种数据类型转换为另一种数据类型。常用的转换函数有:TO_CHAR、TO_DATE、TO_NUMBER。例如:
SELECT TO_DATE(‘2005-12-06’ , ‘yyyy-mm-dd’) FROM dual; SELECT TO_NUMBER('100') FROM dual; SELECT TO_CHAR(sysdate,'YYYY-MM-DD HH24:MI:SS') FROM dual;
注意:
3.3.1) TO_DATE(‘2005-12-06’ , ‘yyyy-mm-dd’) 等同于 ’06-12月-05’ ,其它函数请查询工具书及其说明,这里就不一一举例; 3.3.2) (1)oracle中两个日期可以相减,但结果的单位是天,可以将天*24*60*60 转换成秒。 (2)oracle中两个日期不能相加,但日期可以加上或减去一个数值,这个数值也是天。 例如: stime:=to_date('2007-2-1 12:44:45','yyyy-mm-dd hh:mi:ss'); etime:=to_date('2007-2-1 12:45:04','yyyy-mm-dd hh:mi:ss'); 计算这两个时间差了多少秒: (etime-stime)*24*60*60
4、聚合函数
一组值进行计算,并返回计算后的值 ,具有统计数据的作用
4.1 SUM() SELECT SUM(StudentResult) AS 学号为23的学生总分 FROM Result WHERE StudentID =23 4.2 AVG() SELECT AVG(StudentResult) AS 及格平均成绩 FROM Result WHERE StudentResult >=60 4.3 MAX()、MIN() SELECT AVG(StudentResult) AS 平均成绩, MAX (StudentResult) AS 最高分, MIN (StudentResult) AS 最低分 FROM Result WHERE StudentResult>=60; 4.4 COUNT() SELECT COUNT (*) AS 及格人数 FROM Result WHERE StudentResult>=60
六、高级查询
1、模糊查询
1.1 LIKE
查询时,字段中的内容并不一定与查询内容完全匹配,只要字段中含有这些内容.
1.2 IS NULL
把某一字段中内容为空的记录查询出来
SELECT * FROM 数据表 WHERE 编号 IS NULL;
1.3 BETWEEN
SELECT StudentID, StudentResult FROM Result WHERE StudentResult BETWEEN 60 AND 80;
1.4 IN
SELECT StudentName AS 学员姓名,Address As 地址 FROM Students WHERE Address IN ('北京','广州','上海');
2、分组筛选
2.1 格式
GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用。
SELECT …… FROM <表名> WHERE …… GROUP BY …… HAVING…… 示例: SELECT COUNT(*) AS 人数,GradeId AS 年级 FROM Student GROUP BY GradeId HAVING COUNT(*)>10
注意:
单列分组统计
select gradeid,count(gradeid) from student group by gradeid; -- count(gradeid):统计组里的数量,旁边可以写别名 -- group by gradeid:相同的归为一组
多列分组统计
select gradeid,sex,count(gradeid) from student group by gradeid,sex;
--统计每个年级的男女人数。
2.2 WHERE与HAVING对比
WHERE子句:用来筛选 FROM 子句中指定的操作所产生的行
GROUP BY子句:用来分组 WHERE 子句的输出
HAVING子句:用来从分组的结果中筛选行
3、常用的多表联接查询
有时为了得到完整的结果,我们需要从两个或更多的表中获取结果。我们就需要执行 join。
数据库中的表可通过键将彼此联系起来。主键( Primary Key)是一个列,在这个列中的每一行的值都是唯一的。
在表中,每个主键的值都是唯一的。这样做的目的是在不重复每个表中的所有数据的情况下,把表间的数据交叉捆绑在一起。
下面列出了您可以使用的 JOIN 类型,以及它们之间的差异。
JOIN: 如果表中有至少一个匹配,则返回行
LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行,未匹配列值为null
RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行,未匹配列值为null
FULL JOIN: 只要其中一个表中存在匹配,就返回行,未匹配列值为null
注释: INNER JOIN 与 JOIN 是相同的
3.1 SQL INNER JOIN 关键字
在表中存在至少一个匹配时, INNER JOIN 关键字返回行。
SELECT column_name(s) FROM table_name1 INNER JOIN table_name2 ON table_name1.column_name=table_name2.column_name
3.2 LEFT JOIN 关键字
会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。
SELECT column_name(s) FROM table_name1 LEFT JOIN table_name2 ON table_name1.column_name=table_name2.column_name
3.3 SQL RIGHT JOIN 关键字
RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行, 即使在左表 (table_name1) 中没有匹配的行。
SELECT column_name(s) FROM table_name1 RIGHT JOIN table_name2 ON table_name1.column_name=table_name2.column_name
3.4 SQL FULL JOIN 关键字
只要其中某个表存在匹配, FULL JOIN 关键字就会返回行。
SELECT column_name(s) FROM table_name1 FULL JOIN table_name2 ON table_name1.column_name=table_name2.column_name
七、PL/SQL
1、PL/SQL概述
PL/SQL(Procedural Language/SQL),一种过程化语言,通过增加编程语言的特点,实现对SQL的扩展。
PL/SQL的特点:支持所有SQL的语法;支持case语句,方便的实现循环;通过继承,实现子类具有父类的属性和方法;设置了新的日期类型
2、详细语法
2.1 语句块
PL/SQL程序是按照块结构进行划分。块是PL/SQL程序的基本单位
完整例子: DECLARE v_name varchar2(30) := 'Jack'; --定义用户名称 v_age number := 6; --定义用户年龄 BEGIN --将用户的姓名和年龄插入到CLUB_USER 表中 insert into club_user values (v_name, v_age); Exception /*当出现异常时的处理*/ When others then DBMS_OUTPUT.PUT_LINE('插入数据失败'); END;
2.2 声明
使用declare关键字,用于定义变量或者常量
语法:
DECLARE variable_name [CONSTANT] type [NOT NULL] [:=value];
变量命名规则:
变量名首字母必须是英文字母,其后可以是字母、数字或者特殊字符$、#和下划线;
变量名长度不超过30个字符,变量名中不能有空格;
2.3 流程控制
(1)IF-THEN语句 IF condition THEN Statements END IF; (2)IF-THEN-ELSE语句 IF condition THEN Statements1 ELSE Statements2 END IF; (3)IF-THEN-ELSIF语句 IF condition1 THEN Statements1 ELSIF condition2 THEN Statements2 ELSE Statements3 END IF; --注意是ELSIF而不是ELSEIF (4)CASE语句 在Oracle 9i 后引入 语法: CASE variable WHEN value1 THEN statements1; WHEN value2 THEN statements2; …… WHEN valuen THEN statementsn; [ELSE else_statements;] END CASE; (5)循环结构 LOOP statements; END LOOP; --连续插入10条记录 DECLARE v_name varchar2(30) := 'Jack'; --定义用户名称 v_gradeid integer:= 10; --定义用户年龄 BEGIN LOOP v_gradeid:= v_gradeid+1; if v_gradeid <= 20 then --将用户的姓名和年龄插入到CLUB_USER 表中 insert into grade values (v_gradeid, v_name); ELSE EXIT; end if; END LOOP; Exception /*当出现异常时的处理*/ When others then DBMS_OUTPUT.PUT_LINE('插入数据失败'); END;
2.4 游标(CURSOR)
用来处理使用select语句从数据库中检索到的多行记录的工具
游标的分类:显示游标——返回多条记录时,使用显示游标逐行读取;隐式游标——PL/SQL自动为DML语句创建隐式游标,包含一条返回记录。
使用游标:1 声明游标;2 打开游标;3 提取游标;4 关闭游标
八、视图、存储过程、函数包
1、视图
1.1.视图的特点
是一个数据库中虚拟的表;经过查询操作形成的结果;具有普通表的结构;不能实现数据的存储;对视图的修改将会影响实际的数据表
1.2.视图的应用
(1)创建视图 CREATE [ OR REPLACE ] VIEW view_name AS <select statements> [ WITH CHECK OPTION ] VIEW:用于创建视图 CHECK POINT:必须要满足的视图的约束 (2)删除视图 DROP VIEW view_name (3)通过视图查询学生信息 创建视图 从视图中读取数据 删除视图 --创建视图-- create or replace view v_student as select * from students ; --从视图中检索数据-- select * from v_student; --删除视图-- DROP VIEW v_student;
2、存储过程
2.1 什么是过程:将SQL或者PL/SQL代码块集中用于完成特定功能的集合
2.2 过程的结构
声明部分:包括类型、变量、游标
执行部分:完成功能而编写的SQL语句或则是PL/SQL代码块
异常处理部分
2.3 创建过程
CREATE [ OR REPLACE] PROCEDURE procedure_name [ ( parameter1 [ { IN | OUT | IN OUT} param1_type parameter2 [ { IN | OUT | IN OUT} param2_type …… parameterN [ { IN | OUT | IN OUT} paramN_type]] {IS | AS} procedure _body;
创建过程不使用DECLARE关键字
在创建过程时可指定参数
示例: --创建名称为ShowInfo 的过程 CREATE OR REPLACE PROCEDURE ShowInfo --声明一个输入参数 ( Major IN varchar2 ) AS --声明一个游标,在查询语句中使用输入参数值作为查询条件 CURSOR s_info IS select firstname,lastname from student where major = Major; BEGIN --使用FOR 循环提取游标数据 FOR s_stu IN s_info LOOP Dbms_Output.put_line(s_stu.firstname||''||s_stu.lastname); END lOOP; END;
2.4 过程的调用与删除
--已定义好一个过程ShowInfo,接收一个参数 --调用有参过程 BEGIN ShowInfo('MUSIC'); END; --调用无参过程 BEGIN ShowInfo; END; --删除过程 DROP PROCEDURE 过程名
3、函数
什么是函数:与过程类似,是一组SQL语句或者PL/SQL语句块的集合,同时能够返回执行结果
函数的结构:
声明部分:包括类型、变量、游标
执行部分:完成功能而编写的SQL语句或则是PL/SQL代码块
异常处理部分
3.1 创建函数
CREATE [ OR REPLACE] FUNCTION function_name [ ( parameter1 [ { IN | OUT | IN OUT} param1_type parameter2 [ { IN | OUT | IN OUT} param2_type …… parameterN [ { IN | OUT | IN OUT} paramN_type]] RETURN returntype { IS | AS } function _body;
创建函数不使用DECLARE关键字
在创建函数时可指定参数
示例: --创建函数 CREATE OR REPLACE Function GETCOUNT(Major IN varchar2 ) --声明返回类型 return number AS f_count number; BEGIN --使用INTO 语句将结果赋值给变量 select count(*) into f_count from students where major=Major ; --使用RETURN 语句返回 return f_count; END;
函数题内允许有多个return
执行return语句,函数将执行结束并返回结果
3.2 函数的调用与删除
--调用函数-- DECLARE --声明变量接收函数的返回值 v_count number; BEGIN v_count:=GETCOUNT('MUSIC'); Dbms_Output.put_line(v_count); END; --删除过程 DROP FUNCTION 函数名 执行那个DROP语句后,函数将被永久删除
至此,初窥门径。
九、提高
1、用户操作:
用户锁定和解锁/密码设置: alter user [USER] account lock; alter user [USER] account unlock; alter user scott identified by tiger; select * from dba_users; --查看用户信息表 创建用户:create user [USER] identified by [PASSWD]; 删除用户:drop user [USER] cascade;
2、简单赋权
对于权限的赋予和收回语法如下: grant [权限] to [用户] revoke [权限] from [用户] 在oracle里有俩个最著名的角色: connect、resource 除了dba之外的最大角色。 查看当前用户的所有权限:select * from session_privs; 我们与scott用户下的权限进行对比,发现多了一个 unlimited,
其含义是拥有所有表空间配合的使用权限,这个权限太大了,一般来讲需要进行回收,然后重新进行分配一个表空间配合。 revoke unlimited tablespace from [USER]; 查看用户缺省表空间:select username,default_tablespace from user_users; alter user [USER] quota 10m on users;。 我们想让新建用户拥有对scott.emp表的查询权限:grant select on scott.emp to [USER]; 我们想让新建用户拥有对scott的建立表操作:grant create any table to tim; 我们想让新建用户拥有对scott.emp表的修改权限:grant select, update(sal) on emp to tim; <注意:可以精确到字段>
3、事务特性
事务必须具备以下四个属性,简称ACID 属性:
原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行
场景: 银行转账,A-100 B+100 同时成功或同时失败
一致性(Consistency):一个查询的结果必须与数据库在查询开始的状态一致(读不等待写,写不等待读)。
场景: 查询数据,9:00开始查询数据 9:15查询完毕,在这期间所查询的数据被其他操作更新,且在9:00-1:15之间查询结果显示的是9:00时候并没有被更改的数据. 一般oracle是把这个没有更新的数据放入'undo'里, 如果oracle在'undo'里没有找到数据,则宁可报错,也不会让你看到其他操作更新的新的数据.
隔离性(Isolation):对于其他会话来说,未完成的(也就是未提交的)事务必须不可见。
场景: 事务和事务之间相互隔离,2个session 一个查询 一个更新,那么在更新操作没有 commit之前, 查询所看到的数据是没有提交之前的,相互没有影响。
持久性(Durability):事务一旦提交完成后,数据库就不可以丢失这个事务的结果,数据库通过日志能够保持事务的持久性。
场景: 事务提交之后不可逆, 提交数据是由内存的数据刷新到磁盘上,这个过程的快慢和性能有关。那么oracle主要是靠 'rudo' 日志,先记录日志,在写到磁盘上。
事务采用隐性的方式,起始于session的第一条DML语句,注意登录的用户需要使用sysdba形式:conn system/tiger@orcl as sysdba;
查看事务:select * from v$transaction;
事务结束于:
1)COMMIT(提交)或ROLLBACK(回滚)
2)DDL语句被执行(提交)
3)DCL语句被执行(提交)
4)用户退出SQLPLUS(正常退出是提交,非正常退出是回滚)
5)机器故障或系统崩溃(回滚)
6)shutdowm immediate(回滚)
4、锁
锁大概分为:共享锁与排他锁。
排他锁(独占),排斥其他排他锁和共享锁。
共享锁,排斥其他排他锁,但不排斥其他共享锁。
锁类型:
DML锁(data locks,数据锁),用于保护数据的完整性。 TX(行级锁),TM(表级锁),我们日常所使用的DML操作就会产生事物和锁。
查看事物:select * from v$transaction;
查看锁:select * from v$lock;
DDL锁(dictionary locks,数据字典锁),用于保护数据库对象的结构,如表、索引等的结构定义。
SYSTEM锁(internal locks and latches),保护数据库的内部结构
锁用途:只有有事物才会产生锁,保证数据的完整性和正确性。
自动加锁:做DML操作时,如insert,update,delete,以及select....for update由oracle自动完成加锁.
select * from emp1 where deptno = 10 for update;
修改其部门为10的记录则会被锁定,我们可以进行试探要修改数据记录是否被加锁。如下三种形式均可:
select * from emp1 where empno = 7782 for update nowait; select * from emp1 where empno = 7782 for update wait 5; select * from emp1 where job= 'CLERK' for update skip locked;
如果这个锁占用的时间太长,我们可以通过管理员杀掉session用户。
首先要找到是哪个sid占用了太长时间,查看v$lock表
然后根据v$lock表的SID,去v$session里面去找到,进行kill操作。
select sid, serial# from v$session where sid = 170; alter system kill session 'sid,serial';
5、索引
索引的说明:
索引是与表相关的一个可选结构,在逻辑上和物理上都独立于表的数据,索引能优化查询,不能优化DML操作,Oracle自动维护索引,频繁的DML操作反而会引起大量的索引维护。
如果SQL语句仅访问被索引的列,那么数据库只需从索引中读取数据,而不用读取表,
如果该语句同时还要访问除索引列之外的列,那么,数据库会使用rowid来查找表中的行,
通常,为检索表数据,数据库以交替方式先读取索引块,然后读取相应的表块。
索引的目的是: 主要是减少IO,这是本质,这样才能体现索引的效率。
1 大表,返回的行数<5%
2 经常使用where子句查询的列
3 离散度高的列
4 更新键值代价低
5 逻辑AND、OR效率高
6 查看索引在建在那表、列:
select * from user_indexes;
select * from user_ind_columns;
建立索引的方式:
索引碎片问题:
查看执行计划:set autotrace traceonly explain;
索引碎片问题:由于对基表做DML操作,导致索引表块的自动更改操作,尤其是基表的delete操作会引起index表的index_entries的逻辑删除,注意只有当一个索引块中的全部index_entry都被删除了,才会把这个索引块删除,索引对基表的delete、insert操作都会产生索引碎片问题。
在Oracle文档里并没有清晰的给出索引碎片的量化标准,Oracle建议通过Segment Advisor(段顾问)解决表和索引的碎片问题(053课程会涉及),如果你想自行解决,可以通过查看index_stats视图,当以下三种情形之一发生时,说明积累的碎片应该整理了(仅供参考)。
1.HEIGHT >=4
2 PCT_USED< 50%
3 DEL_LF_ROWS/LF_ROWS>0.2
建立表、索引: create table t (id int); create index ind_1 on t(id); 执行插入记录: begin for i in 1..1000000 loop insert into t values (i); if mod(i, 100)=0 then commit; end if; end loop; end; 分析索引: analyze index ind_1 validate structure; select name,HEIGHT,PCT_USED,DEL_LF_ROWS/LF_ROWS from index_stats; delete t where rownum<700000; alter index ind_1 rebuild [online] [tablespace name];
至此,略有小成。